@checksum-ai/runtime 2.0.14 → 2.0.15-beta

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.
@@ -447,7 +447,7 @@ Additional information: BADCLIENT: Bad error code, ${T} not found in range ${l}.
447
447
  `+Ie.map(rWe).join(`
448
448
  `):" "+rWe(Ie[0]):"as no adapter specified";throw new rs("There is no suitable adapter to dispatch the request "+it,"ERR_NOT_SUPPORT")}return re},"getAdapter"),adapters:Abe};function Nbe(E){if(E.cancelToken&&E.cancelToken.throwIfRequested(),E.signal&&E.signal.aborted)throw new M1(null,E)}t(Nbe,"throwIfCancellationRequested");function uee(E){return Nbe(E),E.headers=Ep.from(E.headers),E.data=FJ.call(E,E.transformRequest),["post","put","patch"].indexOf(E.method)!==-1&&E.headers.setContentType("application/x-www-form-urlencoded",!1),lee.getAdapter(E.adapter||AF.adapter,E)(E).then(t(function(J){return Nbe(E),J.data=FJ.call(E,E.transformResponse,J),J.headers=Ep.from(J.headers),J},"onAdapterResolution"),t(function(J){return LJ(J)||(Nbe(E),J&&J.response&&(J.response.data=FJ.call(E,E.transformResponse,J.response),J.response.headers=Ep.from(J.response.headers))),Promise.reject(J)},"onAdapterRejection"))}t(uee,"dispatchRequest");var _ee={};["object","boolean","number","function","string","symbol"].forEach((E,C)=>{_ee[E]=t(function(J){return typeof J===E||"a"+(C<1?"n ":" ")+E},"validator")});var nWe={};_ee.transitional=t(function(C,F,J){function re(ve,Ie){return"[Axios v"+xN+"] Transitional option '"+ve+"'"+Ie+(J?". "+J:"")}return t(re,"formatMessage"),(ve,Ie,it)=>{if(C===!1)throw new rs(re(Ie," has been removed"+(F?" in "+F:"")),rs.ERR_DEPRECATED);return F&&!nWe[Ie]&&(nWe[Ie]=!0,console.warn(re(Ie," has been deprecated since v"+F+" and will be removed in the near future"))),C?C(ve,Ie,it):!0}},"transitional");_ee.spelling=t(function(C){return(F,J)=>(console.warn(`${J} is likely a misspelling of ${C}`),!0)},"spelling");function qEt(E,C,F){if(typeof E!="object")throw new rs("options must be an object",rs.ERR_BAD_OPTION_VALUE);let J=Object.keys(E),re=J.length;for(;re-- >0;){let ve=J[re],Ie=C[ve];if(Ie){let it=E[ve],Et=it===void 0||Ie(it,ve,E);if(Et!==!0)throw new rs("option "+ve+" must be "+Et,rs.ERR_BAD_OPTION_VALUE);continue}if(F!==!0)throw new rs("Unknown option "+ve,rs.ERR_BAD_OPTION)}}t(qEt,"assertOptions");var UJ={assertOptions:qEt,validators:_ee};var tk=UJ.validators,Ibe=class Ibe{constructor(C){this.defaults=C||{},this.interceptors={request:new q1e,response:new q1e}}async request(C,F){try{return await this._request(C,F)}catch(J){if(J instanceof Error){let re={};Error.captureStackTrace?Error.captureStackTrace(re):re=new Error;let ve=re.stack?re.stack.replace(/^.+\n/,""):"";try{J.stack?ve&&!String(J.stack).endsWith(ve.replace(/^.+\n.+\n/,""))&&(J.stack+=`
449
449
  `+ve):J.stack=ve}catch{}}throw J}}_request(C,F){typeof C=="string"?(F=F||{},F.url=C):F=C||{},F=c2(this.defaults,F);let{transitional:J,paramsSerializer:re,headers:ve}=F;J!==void 0&&UJ.assertOptions(J,{silentJSONParsing:tk.transitional(tk.boolean),forcedJSONParsing:tk.transitional(tk.boolean),clarifyTimeoutError:tk.transitional(tk.boolean)},!1),re!=null&&(Wr.isFunction(re)?F.paramsSerializer={serialize:re}:UJ.assertOptions(re,{encode:tk.function,serialize:tk.function},!0)),F.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?F.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:F.allowAbsoluteUrls=!0),UJ.assertOptions(F,{baseUrl:tk.spelling("baseURL"),withXsrfToken:tk.spelling("withXSRFToken")},!0),F.method=(F.method||this.defaults.method||"get").toLowerCase();let Ie=ve&&Wr.merge(ve.common,ve[F.method]);ve&&Wr.forEach(["delete","get","head","post","put","patch","common"],ht=>{delete ve[ht]}),F.headers=Ep.concat(Ie,ve);let it=[],Et=!0;this.interceptors.request.forEach(t(function(Tt){typeof Tt.runWhen=="function"&&Tt.runWhen(F)===!1||(Et=Et&&Tt.synchronous,it.unshift(Tt.fulfilled,Tt.rejected))},"unshiftRequestInterceptors"));let Bt=[];this.interceptors.response.forEach(t(function(Tt){Bt.push(Tt.fulfilled,Tt.rejected)},"pushResponseInterceptors"));let Nt,Kr=0,Ae;if(!Et){let ht=[uee.bind(this),void 0];for(ht.unshift(...it),ht.push(...Bt),Ae=ht.length,Nt=Promise.resolve(F);Kr<Ae;)Nt=Nt.then(ht[Kr++],ht[Kr++]);return Nt}Ae=it.length;let ri=F;for(;Kr<Ae;){let ht=it[Kr++],Tt=it[Kr++];try{ri=ht(ri)}catch(Ei){Tt.call(this,Ei);break}}try{Nt=uee.call(this,ri)}catch(ht){return Promise.reject(ht)}for(Kr=0,Ae=Bt.length;Kr<Ae;)Nt=Nt.then(Bt[Kr++],Bt[Kr++]);return Nt}getUri(C){C=c2(this.defaults,C);let F=hN(C.baseURL,C.url,C.allowAbsoluteUrls);return gN(F,C.params,C.paramsSerializer)}};t(Ibe,"Axios");var jF=Ibe;Wr.forEach(["delete","get","head","options"],t(function(C){jF.prototype[C]=function(F,J){return this.request(c2(J||{},{method:C,url:F,data:(J||{}).data}))}},"forEachMethodNoData"));Wr.forEach(["post","put","patch"],t(function(C){function F(J){return t(function(ve,Ie,it){return this.request(c2(it||{},{method:C,headers:J?{"Content-Type":"multipart/form-data"}:{},url:ve,data:Ie}))},"httpMethod")}t(F,"generateHTTPMethod"),jF.prototype[C]=F(),jF.prototype[C+"Form"]=F(!0)},"forEachMethodWithData"));var WJ=jF;var fee=class fee{constructor(C){if(typeof C!="function")throw new TypeError("executor must be a function.");let F;this.promise=new Promise(t(function(ve){F=ve},"promiseExecutor"));let J=this;this.promise.then(re=>{if(!J._listeners)return;let ve=J._listeners.length;for(;ve-- >0;)J._listeners[ve](re);J._listeners=null}),this.promise.then=re=>{let ve,Ie=new Promise(it=>{J.subscribe(it),ve=it}).then(re);return Ie.cancel=t(function(){J.unsubscribe(ve)},"reject"),Ie},C(t(function(ve,Ie,it){J.reason||(J.reason=new M1(ve,Ie,it),F(J.reason))},"cancel"))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(C){if(this.reason){C(this.reason);return}this._listeners?this._listeners.push(C):this._listeners=[C]}unsubscribe(C){if(!this._listeners)return;let F=this._listeners.indexOf(C);F!==-1&&this._listeners.splice(F,1)}toAbortSignal(){let C=new AbortController,F=t(J=>{C.abort(J)},"abort");return this.subscribe(F),C.signal.unsubscribe=()=>this.unsubscribe(F),C.signal}static source(){let C;return{token:new fee(t(function(re){C=re},"executor")),cancel:C}}};t(fee,"CancelToken");var Obe=fee,iWe=Obe;function Fbe(E){return t(function(F){return E.apply(null,F)},"wrap")}t(Fbe,"spread");function Lbe(E){return Wr.isObject(E)&&E.isAxiosError===!0}t(Lbe,"isAxiosError");var Rbe={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Rbe).forEach(([E,C])=>{Rbe[C]=E});var aWe=Rbe;function sWe(E){let C=new WJ(E),F=CJ(WJ.prototype.request,C);return Wr.extend(F,WJ.prototype,C,{allOwnKeys:!0}),Wr.extend(F,C,null,{allOwnKeys:!0}),F.create=t(function(re){return sWe(c2(E,re))},"create"),F}t(sWe,"createInstance");var qd=sWe(AF);qd.Axios=WJ;qd.CanceledError=M1;qd.CancelToken=iWe;qd.isCancel=LJ;qd.VERSION=xN;qd.toFormData=ID;qd.AxiosError=rs;qd.Cancel=qd.CanceledError;qd.all=t(function(C){return Promise.all(C)},"all");qd.spread=Fbe;qd.isAxiosError=Lbe;qd.mergeConfig=c2;qd.AxiosHeaders=Ep;qd.formToJSON=E=>eee(Wr.isHTMLForm(E)?new FormData(E):E);qd.getAdapter=lee.getAdapter;qd.HttpStatusCode=aWe;qd.default=qd;var pee=qd;var{Axios:T3t,AxiosError:k3t,CanceledError:C3t,isCancel:E3t,CancelToken:w3t,VERSION:D3t,all:P3t,Cancel:A3t,isAxiosError:N3t,spread:I3t,toFormData:O3t,AxiosHeaders:F3t,HttpStatusCode:L3t,formToJSON:R3t,getAdapter:M3t,mergeConfig:j3t}=pee;var mee=require("fs");var Mbe=class Mbe{constructor(C,F,J,re,ve=!1,Ie={start:t(it=>{},"start"),complete:t(it=>{},"complete"),error:t((it,Et)=>{},"error")}){this.apiBaseURL=C;this.apiKey=F;this.uploadTimeout=J;this.makeGetUploadUrlAPIPath=re;this.isolationMode=ve;this.reporter=Ie}async uploadAsset(C){if(C.uploadStarted=!0,this.isolationMode){C.lastProgress=Date.now(),C.loadedBytes=0,C.sizeBytes=100,C.response=new Promise(J=>{setTimeout(()=>{C.complete=!0,C.lastProgress=Date.now(),C.loadedBytes=100,J({statusCode:200,ok:!0,body:"OK"})},10)});return}let{path:F}=C.info;try{let re=(0,mee.statSync)(F).size;if(C.sizeBytes=re,C.loadedBytes=0,C.lastProgress=Date.now(),this.reporter.start(F),await this.getSignedURLForUpload(C),!C.uploadURL){C.error=!0;return}let ve=(0,mee.createReadStream)(F),Ie=await pee.put(C.uploadURL,ve,{headers:{"Content-Type":wBe[C.info.type]??""},maxBodyLength:1/0,maxContentLength:1/0,onUploadProgress:t(it=>{C.lastProgress=it.loaded>C.loadedBytes?Date.now():C.lastProgress,C.loadedBytes=it.loaded,C.sizeBytes=it.total??re},"onUploadProgress"),timeout:this.uploadTimeout??void 0});if(Ie.status!==200)throw new Error(`Upload failed with status ${Ie.status}`);this.reporter.complete(F),C.complete=!0,C.response=Ie.data}catch(J){this.reporter.error(F,J),C.error=!0}}async getSignedURLForUpload(C){try{let F=JSON.stringify(C.info),J=`${this.apiBaseURL}/${this.makeGetUploadUrlAPIPath(C)}`,re={Accept:"application/json","Content-Type":"application/json",ChecksumAppCode:this.apiKey},ve=await fetch(J,{method:"POST",headers:re,body:F}),{url:Ie}=await ve.json();C.uploadURL=Ie}catch(F){return this.reporter.error(C.info.path,"Error getting signed URL for artifact"+String(F)),null}}};t(Mbe,"TestAssetUploader");var dee=Mbe;var Bbe=class Bbe{constructor(){}sendToCLI(...C){console.log(`{trm}${C.map(F=>F.toString()).join(`,
450
- `)}{/trm}`)}event(C,F){return new Promise(J=>{let re=F?`${C}=${F}`:C;setTimeout(()=>{this.sendToCLI(`monitor:${re}`),J(!0)},100)})}trace(C,F){let J=F?`${C}=${JSON.stringify(F)}`:C;setTimeout(()=>{this.sendToCLI(`trace:${J}`)},100)}log(C){return this.event("log",C)}debug(...C){this.sendToCLI(C)}};t(Bbe,"CLIChannel");var jbe=Bbe,Jbe=class Jbe{constructor(C,F=!1){this.config=C;this.isolationMode=F;this.MAX_UPLOADS=15;this.MONITOR_INTERVAL=2500;this.UPLOAD_TIMEOUT=10*60*1e3;this.UPLOAD_STALL_TIMEOUT=3*60*60*1e3;this.WATCH_TIMEOUT=2*60*1e3;this.assets=[];this.watchAssets=[];this.reportComplete=!1;this.processingInProgress=!1;this.pwTestIdToChecksumTestId={};this.checksumTestIdToUsingPlaceholder={};this.channel=new jbe,this.testAssetUploader=new dee(C.apiURL,C.apiKey,this.UPLOAD_TIMEOUT,()=>`client-api/test-runs/${this.config.sessionId}/get-upload-url`,this.isolationMode,{start:t(J=>this.channel.trace("Upload Start",{filename:J}),"start"),complete:t(J=>{if(!this.reportAsset||J!==this.reportAsset.info.path)try{(0,ed.unlinkSync)(J),this.channel.debug(`[TestAssetUploader] Deleted file after successful upload: ${J}`)}catch(re){this.channel.debug(`[TestAssetUploader] Failed to delete file after upload: ${J}`,re)}this.channel.trace("Upload Complete",{filename:J})},"complete"),error:t((J,re)=>this.channel.trace("Upload Failed",{filename:J,error:re}),"error")}),setInterval(this.monitorUploads.bind(this),this.MONITOR_INTERVAL),this.listenForMessages(),this.startServer()}listenForMessages(){process.stdin.on("data",async C=>{let F=C.toString().trim();if(!F.startsWith("cli:"))return;let[J,re]=F.substring(4).split("=");switch(this.channel.debug("Received message from CLI "+J+" "+re),J){case"report":if(this.testRunEndTime=Date.now(),re!=="false")try{let ve=Buffer.from(re,"base64").toString("utf-8"),Ie=JSON.parse(ve);await this.handleReport(Ie)}catch(ve){this.channel.debug("Error JSON parsing report payload, continue without report. Error: "+this.stringify(ve)),this.reportComplete=!0}else this.reportComplete=!0;this.monitorUploadsCompletion();break;case"shutdown":this.shutdown();break}})}async readMetadataFile(C){try{let F=await(0,lWe.readFile)(C,"utf-8");return JSON.parse(F)}catch(F){return this.channel.trace("Runtime Error",`Error reading checksum metadata file ${C}: ${F.message}`),{}}}async serveReport(C){try{let F=(0,j1.dirname)(C);await this.channel.log("Serving report in browser: "+F);let J=wZ.isRepoMode?`yarn playwright show-report ${F}`:`npx playwright show-report ${F}`,re=(0,cWe.execSync)(J,{encoding:"utf8",stdio:"pipe"});await this.channel.log("Success: Report opened in browser")}catch(F){await this.channel.log(`Error serving report in browser: ${F.message}`),F.stderr&&await this.channel.log(F.stderr.toString())}}async handleReport(C){let{reportPath:F,pathToChecksumMetadata:J,didFail:re,openReportCriteria:ve,checksumRoot:Ie,projectRoot:it}=C;this.channel.debug(`Handling report ${this.isolationMode?"(isolation mode)":""}`+F),this.uploadReportData((0,j1.dirname)(F));try{let Et=await this.readMetadataFile(J),Bt=new jZ(F,this.config.sessionId,this.pwTestIdToChecksumTestId,Et,{hosted:!this.isolationMode},this.channel,Ie,it,this.checksumTestIdToUsingPlaceholder);try{this.reportAsset=this.initAsset({type:"report",path:void 0}),await Bt.process(),this.reportAsset.info.path=Bt.getProcessedFilePath(),this.uploadAsset(this.reportAsset)}catch(Kr){this.channel.debug("Error processing report, "+Kr.message),this.reportAsset.error=!0}this.stats=Bt.getReportsStats(),this.channel.debug("Checking watch assets");let Nt=this.watchAssets.filter(Kr=>!(Kr.type!=="trace"||Bt.testHasTrace(Kr.testId,Kr.project)));Nt.length>0&&(this.channel.debug("Removed watch assets - "),this.channel.debug(JSON.stringify(Nt.map(Kr=>Kr.path)))),this.watchAssets=this.watchAssets.filter(Kr=>Kr.type!=="trace"||Bt.testHasTrace(Kr.testId,Kr.project))}catch(Et){this.channel.debug("Error processing report, "+this.stringify(Et)),this.reportAsset.error=!0}finally{if((ve==="always"||ve==="on-failure"&&re)&&await this.serveReport(F),J&&(0,ed.existsSync)(J))try{(0,ed.unlinkSync)(J)}catch(Bt){console.error(`Error deleting checksum metadata file ${J}: ${Bt.message}`)}}}async uploadReportData(C){let F=(0,j1.join)(C,"data");try{let J=(0,ed.readdirSync)(F),re=[".zip",".webm"],ve=J.filter(Ie=>!re.includes((0,j1.extname)(Ie)));this.channel.debug("Preparing to upload report data files,"+ve);for(let Ie of ve)this.channel.debug("Uploading report data file,"+Ie),this.addAsset({type:"report-data-file",fileName:Ie,path:`${F}/${Ie}`})}catch(J){this.channel.debug(`Error reading/adding report data files from dir ${F}`+J.message)}}shutdown(){this.channel.debug("Received shutdown message from CLI"),this.server.close(),process.exit(0)}async monitorUploadsCompletion(){var C;if(!this.reportComplete&&this.reportAsset&&(this.reportAsset.complete||this.reportAsset.error)){this.reportComplete=!0;let F="";try{let J=JSON.stringify(this.stats),re=`checksum-stats-${(0,BF.randomBytes)(8).toString("hex")}.json`;F=(0,j1.join)((0,pWe.tmpdir)(),re),(0,ed.writeFileSync)(F,J,"utf-8"),this.channel.debug(`Stats written to temporary file: ${F}`)}catch(J){this.channel.debug("Error writing stats to file"),this.channel.log(`[monitorUploadsCompletion] Error writing stats to file: ${J.message}`)}this.channel.event("report-complete",`${(C=this.reportAsset)!=null&&C.complete?"true":"false"}:${F}`)}if(!this.processingInProgress&&this.reportComplete&&(this.assets.filter(F=>F.complete||F.error).length===this.assets.length||this.isUploadStalled())&&(this.watchAssets.length===0||this.testRunEndTime&&Date.now()-this.testRunEndTime>this.WATCH_TIMEOUT)){let F=this.assets.find(re=>re.error)?"uploads-complete-with-errors":"uploads-complete",J=F==="uploads-complete"?{}:{uploadErrors:this.assets.filter(re=>re.error).map(re=>{try{return JSON.stringify(re)}catch{return re.info.path}}),watchAssets:this.watchAssets,testRunEndTime:this.testRunEndTime,now:Date.now()};this.cleanUp(),this.channel.event(F,JSON.stringify(J));return}await xve(1e3),this.monitorUploadsCompletion()}cleanUp(){let C;for(let F of this.assets)if(F.info.type==="rrweb-recording"){C=(0,j1.dirname)(F.info.path);break}C&&(0,ed.rmdirSync)(C,{recursive:!0})}isUploadStalled(){let C=this.assets.reduce((F,J)=>Math.max(F,J.lastProgress??0),0)-Date.now()>this.UPLOAD_STALL_TIMEOUT;return C&&this.channel.log("Uploads are stalled"),C}async startServer(){let C=await this.acquirePortNumber();this.channel.event("port",C.toString()),this.server=(0,_We.createServer)((F,J)=>{let re=t(Ie=>{J.writeHead(400,{"Content-Type":"text/plain"}),J.end(Ie)},"returnErrorWithMessage");if(F.method!=="POST"){J.writeHead(404,{"Content-Type":"text/plain"}),J.end("Method not allowed");return}let ve="";F.on("data",Ie=>{ve+=Ie.toString()}),F.on("end",()=>{let Ie;try{Ie=JSON.parse(ve)}catch{return re("Invalid body")}let{type:it,payload:Et,watch:Bt}=Ie;switch(this.channel.debug(`Server received message, ${it}, ${this.stringify(Et)}`),it){case"asset":if(!Et.path||!Et.type)return re("Missing arguments");Bt?this.watchAsset(Et):this.processAsset(Et);break;case"testInfo":if(!Et.pwTestId||!Et.checksumTestId)return re("Missing arguments");this.pwTestIdToChecksumTestId[Et.pwTestId]=Et.checksumTestId,Et.usingChecksumTestIdPlaceholder!==void 0&&(this.checksumTestIdToUsingPlaceholder[Et.checksumTestId]=Et.usingChecksumTestIdPlaceholder);break;case"checksumTestMetadata":let Nt=Et;if(!Nt.checksumTestId||!Et.data)return re("Missing arguments");this.channel.event("checksumTestMetadata",JSON.stringify({...Nt}));break;case"testStats":break;case"playwrightConfig":this.channel.event("playwrightConfig",JSON.stringify(Et));break;default:return re("Invalid message type")}J.writeHead(200,{"Content-Type":"text/plain"}),J.end("OK")})}),this.server.listen(C)}stringify(C){try{return JSON.stringify(C)}catch{return"message"in C?C.message:C}}monitorUploads(){let{totalSizeBytes:C,totalUploadedBytes:F}=this.calculateUploadProgress();if(C>0&&!this.isolationMode){let ve=(F/C*100).toFixed(2);this.channel.event("upload-progress",ve)}let J=this.assets.filter(ve=>!ve.uploadStarted);if(J.length===0)return;let re=t(()=>this.assets.filter(ve=>ve.uploadStarted&&!ve.complete&&!ve.error).length,"getNumOfActiveUploads");if(!(re()>=this.MAX_UPLOADS))for(;J.length>0&&re()<this.MAX_UPLOADS;){let ve=J.pop();this.uploadAsset(ve)}}calculateUploadProgress(){let C=this.assets.reduce((J,{sizeBytes:re})=>J+(re??0),0),F=Math.min(C,this.assets.reduce((J,{loadedBytes:re})=>J+(re??0),0));return{totalSizeBytes:C,totalUploadedBytes:F}}getUploadLogMessage(C){switch(C.info.type){case"report":return"Uploading report";case"har":return`Uploading har file for test ${C.info.testId}`;case"trace":return`Uploading trace file for test ${C.info.testId}`;case"esra":return`Uploading metadata file for test ${C.info.testId}`;case"test-files":return`Uploading auto-healed test code for file ${C.info.path}`}}async uploadAsset(C){try{C.uploadStarted=!0;let F=this.getUploadLogMessage(C);F&&!this.isolationMode&&this.channel.event("log",F),await this.testAssetUploader.uploadAsset(C)}catch(F){C.error=!0,this.channel.debug("Error uploading asset"+this.stringify(F)),this.channel.trace("Upload Failed",{asset:C.info.fileName,error:String(F)})}}async getSignedURLForUpload(C){try{let{apiKey:F,sessionId:J,apiURL:re}=this.config,ve=C.info,Ie=await fetch(`${re}/client-api/test-runs/${J}/get-upload-url`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",ChecksumAppCode:F},body:JSON.stringify(ve)}),{url:it}=await Ie.json();C.uploadURL=it}catch(F){return this.channel.debug("Error getting signed URL for artifact"+this.stringify(F)),null}}watchAsset(C){this.channel.debug("Watching file "+C.path),this.watchAssets.push({...C,addedAt:Date.now()});let F=t(async()=>{await this.waitForFileComplete(C.path)&&(this.processAsset(C),this.watchAssets=this.watchAssets.filter(re=>re.path!==C.path))},"waitForCompletion");if((0,ed.existsSync)(C.path))F();else{let J=(0,j1.dirname)(C.path),re=(0,j1.basename)(C.path),ve=!1,Ie=(0,ed.watch)(J,async(it,Et)=>{if(!(Et!==re||ve))try{this.channel.debug("Watched file changed "+C.path),ve=!0,await F()}finally{Ie.close()}})}}waitForFileComplete(C,F=1e3,J=6e4,re=1){return new Promise(ve=>{let Ie=Date.now(),it=0,Et=t(()=>{if(!(0,ed.existsSync)(C))return this.channel.debug(`Asset required for upload doesn't exist anymore ${C}`),ve(!1);let Bt=(0,ed.statSync)(C).size;if(Bt===it){if(re>0){this.channel.debug(`File size has not changed, verifying stabilization, ${C}, size: ${Bt}, equalSizeValidationCountLeft: ${re}`),re--,setTimeout(Et,F);return}return this.channel.debug(`File size has not changed, stabilization verified, ${C}, size: ${Bt}`),ve(!0)}if(this.channel.debug(`File size changed, waiting for stabilization, ${C}, previous size: ${it}, current size: ${Bt}`),Date.now()-Ie>J)return this.channel.debug(`Asset required for upload is taking over ${J} ms to write to disk ${C}`),ve(!0);it=Bt,setTimeout(Et,F)},"checkFile");Et()})}processAsset(C){switch(C.type){case"trace":return this.processTrace(C.path,C.testId);case"har":return this.processHar(C.path,C.testId);case"rrweb-recording":case"esra":case"test-files":return this.addAsset(C)}}async processHar(C,F){}calculateSha1(C){let F=(0,BF.createHash)("sha1");return F.update(C),F.digest("hex")}async calculateFileSha1Streaming(C){let F=(0,BF.createHash)("sha1"),J=(0,ed.createReadStream)(C);return await(0,uWe.pipeline)(J,F),F.digest("hex")}async processTrace(C,F){try{this.processingInProgress=!0,await xve(1e3);let J=C;if(!this.isolationMode){this.channel.debug(`Preparing trace for upload (testId: ${F})...`),J=C.replace(".zip",".actual.zip"),(0,ed.renameSync)(C,J);let Ie="checksum-playwright-trace:"+Date.now().toString()+(0,BF.randomBytes)(1024).toString("hex");(0,ed.writeFileSync)(C,Ie)}let ve=await t(async()=>await this.calculateFileSha1Streaming(C)+(0,j1.extname)(C),"makePlaywrightHTMLReporterName")();this.channel.debug(`Trace file for test ${F} has been manipulated with file name ${ve}, sending for upload...`),this.addAsset({type:"report-data-file",path:J,testId:F,fileName:ve})}catch(J){let re=String(J);this.channel.debug("Error processing trace file"+re),this.channel.trace("Trace Processing Error",{error:re})}finally{this.processingInProgress=!1}}addAsset(C){this.channel.debug("Adding file "+C.path);let F=this.initAsset(C);return this.assets.push(F),F}initAsset(C){return{complete:!1,error:!1,response:void 0,info:C,removeAfterUpload:C.type==="rrweb-recording"}}async acquirePortNumber(){return await new Promise((C,F)=>{let J=fWe.createServer();J.unref(),J.on("error",F),J.listen(0,()=>{let re=J.address().port;J.close(()=>{C(re)})})})}};t(Jbe,"TestRunMonitor");var gee=Jbe,dWe;try{dWe=JSON.parse(process.argv[2])}catch(E){console.log("Error starting test run monitor",E),process.exit(1)}var oWe;new gee(dWe,((oWe=process.argv)==null?void 0:oWe[3])==="isolated");0&&(module.exports={TestRunMonitor});
450
+ `)}{/trm}`)}event(C,F){return new Promise(J=>{let re=F?`${C}=${F}`:C;setTimeout(()=>{this.sendToCLI(`monitor:${re}`),J(!0)},100)})}trace(C,F){let J=F?`${C}=${JSON.stringify(F)}`:C;setTimeout(()=>{this.sendToCLI(`trace:${J}`)},100)}log(C){return this.event("log",C)}debug(...C){this.sendToCLI(C)}};t(Bbe,"CLIChannel");var jbe=Bbe,Jbe=class Jbe{constructor(C,F=!1){this.config=C;this.isolationMode=F;this.MAX_UPLOADS=15;this.MONITOR_INTERVAL=2500;this.UPLOAD_TIMEOUT=10*60*1e3;this.UPLOAD_STALL_TIMEOUT=3*60*60*1e3;this.WATCH_TIMEOUT=2*60*1e3;this.assets=[];this.watchAssets=[];this.processingPaths=new Set;this.reportComplete=!1;this.processingInProgress=!1;this.pwTestIdToChecksumTestId={};this.checksumTestIdToUsingPlaceholder={};this.channel=new jbe,this.testAssetUploader=new dee(C.apiURL,C.apiKey,this.UPLOAD_TIMEOUT,()=>`client-api/test-runs/${this.config.sessionId}/get-upload-url`,this.isolationMode,{start:t(J=>this.channel.trace("Upload Start",{filename:J}),"start"),complete:t(J=>{if(!this.reportAsset||J!==this.reportAsset.info.path)try{(0,ed.unlinkSync)(J),this.channel.debug(`[TestAssetUploader] Deleted file after successful upload: ${J}`)}catch(re){this.channel.debug(`[TestAssetUploader] Failed to delete file after upload: ${J}`,re)}this.channel.trace("Upload Complete",{filename:J})},"complete"),error:t((J,re)=>this.channel.trace("Upload Failed",{filename:J,error:re}),"error")}),setInterval(this.monitorUploads.bind(this),this.MONITOR_INTERVAL),this.listenForMessages(),this.startServer()}listenForMessages(){process.stdin.on("data",async C=>{let F=C.toString().trim();if(!F.startsWith("cli:"))return;let[J,re]=F.substring(4).split("=");switch(this.channel.debug("Received message from CLI "+J+" "+re),J){case"report":if(this.testRunEndTime=Date.now(),re!=="false")try{let ve=Buffer.from(re,"base64").toString("utf-8"),Ie=JSON.parse(ve);await this.handleReport(Ie)}catch(ve){this.channel.debug("Error JSON parsing report payload, continue without report. Error: "+this.stringify(ve)),this.reportComplete=!0}else this.reportComplete=!0;this.monitorUploadsCompletion();break;case"shutdown":this.shutdown();break}})}async readMetadataFile(C){try{let F=await(0,lWe.readFile)(C,"utf-8");return JSON.parse(F)}catch(F){return this.channel.trace("Runtime Error",`Error reading checksum metadata file ${C}: ${F.message}`),{}}}async serveReport(C){try{let F=(0,j1.dirname)(C);await this.channel.log("Serving report in browser: "+F);let J=wZ.isRepoMode?`yarn playwright show-report ${F}`:`npx playwright show-report ${F}`,re=(0,cWe.execSync)(J,{encoding:"utf8",stdio:"pipe"});await this.channel.log("Success: Report opened in browser")}catch(F){await this.channel.log(`Error serving report in browser: ${F.message}`),F.stderr&&await this.channel.log(F.stderr.toString())}}async handleReport(C){let{reportPath:F,pathToChecksumMetadata:J,didFail:re,openReportCriteria:ve,checksumRoot:Ie,projectRoot:it}=C;this.channel.debug(`Handling report ${this.isolationMode?"(isolation mode)":""}`+F),this.uploadReportData((0,j1.dirname)(F));try{let Et=await this.readMetadataFile(J),Bt=new jZ(F,this.config.sessionId,this.pwTestIdToChecksumTestId,Et,{hosted:!this.isolationMode},this.channel,Ie,it,this.checksumTestIdToUsingPlaceholder);try{this.reportAsset=this.initAsset({type:"report",path:void 0}),await Bt.process(),this.reportAsset.info.path=Bt.getProcessedFilePath(),this.uploadAsset(this.reportAsset)}catch(Kr){this.channel.debug("Error processing report, "+Kr.message),this.reportAsset.error=!0}this.stats=Bt.getReportsStats(),this.channel.debug("Checking watch assets");let Nt=this.watchAssets.filter(Kr=>!(Kr.type!=="trace"||Bt.testHasTrace(Kr.testId,Kr.project)));Nt.length>0&&(this.channel.debug("Removed watch assets - "),this.channel.debug(JSON.stringify(Nt.map(Kr=>Kr.path)))),this.watchAssets=this.watchAssets.filter(Kr=>Kr.type!=="trace"||Bt.testHasTrace(Kr.testId,Kr.project))}catch(Et){this.channel.debug("Error processing report, "+this.stringify(Et)),this.reportAsset.error=!0}finally{if((ve==="always"||ve==="on-failure"&&re)&&await this.serveReport(F),J&&(0,ed.existsSync)(J))try{(0,ed.unlinkSync)(J)}catch(Bt){console.error(`Error deleting checksum metadata file ${J}: ${Bt.message}`)}}}async uploadReportData(C){let F=(0,j1.join)(C,"data");try{let J=(0,ed.readdirSync)(F),re=[".zip",".webm"],ve=J.filter(Ie=>!re.includes((0,j1.extname)(Ie)));this.channel.debug("Preparing to upload report data files,"+ve);for(let Ie of ve)this.channel.debug("Uploading report data file,"+Ie),this.addAsset({type:"report-data-file",fileName:Ie,path:`${F}/${Ie}`})}catch(J){this.channel.debug(`Error reading/adding report data files from dir ${F}`+J.message)}}shutdown(){this.channel.debug("Received shutdown message from CLI"),this.server.close(),process.exit(0)}async monitorUploadsCompletion(){var C;if(!this.reportComplete&&this.reportAsset&&(this.reportAsset.complete||this.reportAsset.error)){this.reportComplete=!0;let F="";try{let J=JSON.stringify(this.stats),re=`checksum-stats-${(0,BF.randomBytes)(8).toString("hex")}.json`;F=(0,j1.join)((0,pWe.tmpdir)(),re),(0,ed.writeFileSync)(F,J,"utf-8"),this.channel.debug(`Stats written to temporary file: ${F}`)}catch(J){this.channel.debug("Error writing stats to file"),this.channel.log(`[monitorUploadsCompletion] Error writing stats to file: ${J.message}`)}this.channel.event("report-complete",`${(C=this.reportAsset)!=null&&C.complete?"true":"false"}:${F}`)}if(!this.processingInProgress&&this.reportComplete&&(this.assets.filter(F=>F.complete||F.error).length===this.assets.length||this.isUploadStalled())&&(this.watchAssets.length===0||this.testRunEndTime&&Date.now()-this.testRunEndTime>this.WATCH_TIMEOUT)){let F=this.assets.find(re=>re.error)?"uploads-complete-with-errors":"uploads-complete",J=F==="uploads-complete"?{}:{uploadErrors:this.assets.filter(re=>re.error).map(re=>{try{return JSON.stringify(re)}catch{return re.info.path}}),watchAssets:this.watchAssets,testRunEndTime:this.testRunEndTime,now:Date.now()};this.cleanUp(),this.channel.event(F,JSON.stringify(J));return}await xve(1e3),this.monitorUploadsCompletion()}cleanUp(){let C;for(let F of this.assets)if(F.info.type==="rrweb-recording"){C=(0,j1.dirname)(F.info.path);break}C&&(0,ed.rmdirSync)(C,{recursive:!0})}isUploadStalled(){let C=this.assets.reduce((F,J)=>Math.max(F,J.lastProgress??0),0)-Date.now()>this.UPLOAD_STALL_TIMEOUT;return C&&this.channel.log("Uploads are stalled"),C}async startServer(){let C=await this.acquirePortNumber();this.channel.event("port",C.toString()),this.server=(0,_We.createServer)((F,J)=>{let re=t(Ie=>{J.writeHead(400,{"Content-Type":"text/plain"}),J.end(Ie)},"returnErrorWithMessage");if(F.method!=="POST"){J.writeHead(404,{"Content-Type":"text/plain"}),J.end("Method not allowed");return}let ve="";F.on("data",Ie=>{ve+=Ie.toString()}),F.on("end",()=>{let Ie;try{Ie=JSON.parse(ve)}catch{return re("Invalid body")}let{type:it,payload:Et,watch:Bt}=Ie;switch(this.channel.debug(`Server received message, ${it}, ${this.stringify(Et)}`),it){case"asset":if(!Et.path||!Et.type)return re("Missing arguments");Bt?this.watchAsset(Et):this.processAsset(Et);break;case"testInfo":if(!Et.pwTestId||!Et.checksumTestId)return re("Missing arguments");this.pwTestIdToChecksumTestId[Et.pwTestId]=Et.checksumTestId,Et.usingChecksumTestIdPlaceholder!==void 0&&(this.checksumTestIdToUsingPlaceholder[Et.checksumTestId]=Et.usingChecksumTestIdPlaceholder);break;case"checksumTestMetadata":let Nt=Et;if(!Nt.checksumTestId||!Et.data)return re("Missing arguments");this.channel.event("checksumTestMetadata",JSON.stringify({...Nt}));break;case"testStats":break;case"playwrightConfig":this.channel.event("playwrightConfig",JSON.stringify(Et));break;default:return re("Invalid message type")}J.writeHead(200,{"Content-Type":"text/plain"}),J.end("OK")})}),this.server.listen(C)}stringify(C){try{return JSON.stringify(C)}catch{return"message"in C?C.message:C}}monitorUploads(){let{totalSizeBytes:C,totalUploadedBytes:F}=this.calculateUploadProgress();if(C>0&&!this.isolationMode){let ve=(F/C*100).toFixed(2);this.channel.event("upload-progress",ve)}let J=this.assets.filter(ve=>!ve.uploadStarted);if(J.length===0)return;let re=t(()=>this.assets.filter(ve=>ve.uploadStarted&&!ve.complete&&!ve.error).length,"getNumOfActiveUploads");if(!(re()>=this.MAX_UPLOADS))for(;J.length>0&&re()<this.MAX_UPLOADS;){let ve=J.pop();this.uploadAsset(ve)}}calculateUploadProgress(){let C=this.assets.reduce((J,{sizeBytes:re})=>J+(re??0),0),F=Math.min(C,this.assets.reduce((J,{loadedBytes:re})=>J+(re??0),0));return{totalSizeBytes:C,totalUploadedBytes:F}}getUploadLogMessage(C){switch(C.info.type){case"report":return"Uploading report";case"har":return`Uploading har file for test ${C.info.testId}`;case"trace":return`Uploading trace file for test ${C.info.testId}`;case"esra":return`Uploading metadata file for test ${C.info.testId}`;case"test-files":return`Uploading auto-healed test code for file ${C.info.path}`}}async uploadAsset(C){try{C.uploadStarted=!0;let F=this.getUploadLogMessage(C);F&&!this.isolationMode&&this.channel.event("log",F),await this.testAssetUploader.uploadAsset(C)}catch(F){C.error=!0,this.channel.debug("Error uploading asset"+this.stringify(F)),this.channel.trace("Upload Failed",{asset:C.info.fileName,error:String(F)})}}async getSignedURLForUpload(C){try{let{apiKey:F,sessionId:J,apiURL:re}=this.config,ve=C.info,Ie=await fetch(`${re}/client-api/test-runs/${J}/get-upload-url`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",ChecksumAppCode:F},body:JSON.stringify(ve)}),{url:it}=await Ie.json();C.uploadURL=it}catch(F){return this.channel.debug("Error getting signed URL for artifact"+this.stringify(F)),null}}watchAsset(C){if(this.watchAssets.some(J=>J.path===C.path)){this.channel.debug(`Already watching file ${C.path}, skipping duplicate`);return}this.channel.debug("Watching file "+C.path),this.watchAssets.push({...C,addedAt:Date.now()});let F=t(async()=>{await this.waitForFileComplete(C.path)&&(this.processAsset(C),this.watchAssets=this.watchAssets.filter(re=>re.path!==C.path))},"waitForCompletion");if((0,ed.existsSync)(C.path))F();else{let J=(0,j1.dirname)(C.path),re=(0,j1.basename)(C.path),ve=!1,Ie=(0,ed.watch)(J,async(it,Et)=>{if(!(Et!==re||ve))try{this.channel.debug("Watched file changed "+C.path),ve=!0,await F()}finally{Ie.close()}})}}waitForFileComplete(C,F=1e3,J=6e4,re=1){return new Promise(ve=>{let Ie=Date.now(),it=0,Et=t(()=>{if(!(0,ed.existsSync)(C))return this.channel.debug(`Asset required for upload doesn't exist anymore ${C}`),ve(!1);let Bt=(0,ed.statSync)(C).size;if(Bt===it){if(re>0){this.channel.debug(`File size has not changed, verifying stabilization, ${C}, size: ${Bt}, equalSizeValidationCountLeft: ${re}`),re--,setTimeout(Et,F);return}return this.channel.debug(`File size has not changed, stabilization verified, ${C}, size: ${Bt}`),ve(!0)}if(this.channel.debug(`File size changed, waiting for stabilization, ${C}, previous size: ${it}, current size: ${Bt}`),Date.now()-Ie>J)return this.channel.debug(`Asset required for upload is taking over ${J} ms to write to disk ${C}`),ve(!0);it=Bt,setTimeout(Et,F)},"checkFile");Et()})}processAsset(C){switch(C.type){case"trace":return this.processTrace(C.path,C.testId);case"har":return this.processHar(C.path,C.testId);case"rrweb-recording":case"esra":case"test-files":return this.addAsset(C)}}async processHar(C,F){}calculateSha1(C){let F=(0,BF.createHash)("sha1");return F.update(C),F.digest("hex")}async calculateFileSha1Streaming(C){let F=(0,BF.createHash)("sha1"),J=(0,ed.createReadStream)(C);return await(0,uWe.pipeline)(J,F),F.digest("hex")}async processTrace(C,F){if(this.processingPaths.has(C)){this.channel.debug(`Trace file ${C} already being processed, skipping`);return}this.processingPaths.add(C);try{this.processingInProgress=!0,await xve(1e3);let J=C;if(!this.isolationMode){this.channel.debug(`Preparing trace for upload (testId: ${F})...`),J=C.replace(".zip",".actual.zip"),(0,ed.renameSync)(C,J);let Ie="checksum-playwright-trace:"+Date.now().toString()+(0,BF.randomBytes)(1024).toString("hex");(0,ed.writeFileSync)(C,Ie)}let ve=await t(async()=>await this.calculateFileSha1Streaming(C)+(0,j1.extname)(C),"makePlaywrightHTMLReporterName")();this.channel.debug(`Trace file for test ${F} has been manipulated with file name ${ve}, sending for upload...`),this.addAsset({type:"report-data-file",path:J,testId:F,fileName:ve})}catch(J){let re=String(J);this.channel.debug("Error processing trace file"+re),this.channel.trace("Trace Processing Error",{error:re})}finally{this.processingPaths.delete(C),this.processingInProgress=!1}}addAsset(C){this.channel.debug("Adding file "+C.path);let F=this.initAsset(C);return this.assets.push(F),F}initAsset(C){return{complete:!1,error:!1,response:void 0,info:C,removeAfterUpload:C.type==="rrweb-recording"}}async acquirePortNumber(){return await new Promise((C,F)=>{let J=fWe.createServer();J.unref(),J.on("error",F),J.listen(0,()=>{let re=J.address().port;J.close(()=>{C(re)})})})}};t(Jbe,"TestRunMonitor");var gee=Jbe,dWe;try{dWe=JSON.parse(process.argv[2])}catch(E){console.log("Error starting test run monitor",E),process.exit(1)}var oWe;new gee(dWe,((oWe=process.argv)==null?void 0:oWe[3])==="isolated");0&&(module.exports={TestRunMonitor});
451
451
  /*! Bundled license information:
452
452
 
453
453
  typescript/lib/typescript.js: