require("source-map-support").install(),(()=>{"use strict";var e={n:t=>{var s=t&&t.__esModule?()=>t.default:()=>t;return e.d(s,{a:s}),s},d:(t,s)=>{for(var r in s)e.o(s,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:s[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>v});const s=require("mz"),r=require("fs");var i=e.n(r);const o=require("url");var n=e.n(o);const a=require("path");var u=e.n(a);const l=require("deepcopy");var h=e.n(l);const d=require("jsonwebtoken");var c=e.n(d);const p=require("request");var g=e.n(p);const f=require("common-tags");function w(e,t={}){const s={_stringifyToJson:JSON.stringify,maxLength:500,...t};let r=e;const i=s._stringifyToJson||JSON.stringify;if("object"==typeof r)try{r=i(r)}catch(e){}return"string"==typeof r&&r.length>s.maxLength&&(r=`${r.substring(0,s.maxLength)}...`),r.toString()}class m{constructor({apiKey:e,apiSecret:t,apiUrlPrefix:s,apiJwtExpiresIn:r=300,debugLogging:o=!1,statusCheckInterval:n=1e3,statusCheckTimeout:a=9e5,logger:u=console,downloadDir:l=process.cwd(),fs:h=i(),request:d=g(),proxyServer:c,requestConfig:p,progressBar:f}){this.apiKey=e,this.apiSecret=t,this.apiUrlPrefix=s,this.apiJwtExpiresIn=r,this.statusCheckInterval=n,this.statusCheckTimeout=a,this.debugLogging=o,this.logger=u,this.downloadDir=l,this.proxyServer=c,this.requestConfig=p||{},this._progressBar=f||new class{constructor({_clearInterval:e=clearInterval,_setInterval:t=setInterval,preamble:s="",stdout:r=process.stdout}={}){this.interval=null,this.motionCounter=1,this.setInterval=t,this.clearInterval=e,this.stdout=r,this.bucket=[],this.emptyBucketPointers=[],this.setPreamble(s)}setPreamble(e){this.preamble=`${e} [`,this.addendum="]";let t=80;this.stdout.isTTY&&(t=Number(this.stdout.columns)),this.emptyBucketPointers=[],this.bucket=[];const s=t-this.preamble.length-this.addendum.length;for(let e=0;e<s;e++)this.bucket.push(" "),this.emptyBucketPointers.push(e)}animate(e){const t={speed:100,...e};let s=!1;this.interval=this.setInterval((()=>{s?this.moveBucket():s=this.randomlyFillBucket()}),t.speed)}finish(){this.interval&&this.clearInterval(this.interval),this.fillBucket(),this.stdout.write("\n")}randomlyFillBucket(){const e=Math.floor(Math.random()*this.emptyBucketPointers.length);this.bucket[this.emptyBucketPointers[e]]=".",this.showBucket();let t=!0;const s=[];return this.emptyBucketPointers.forEach((e=>{" "===this.bucket[e]&&(t=!1,s.push(e))})),this.emptyBucketPointers=s,t}fillBucket(){this.bucket=this.bucket.map((function(){return"."})),this.showBucket()}moveBucket(){for(let e=0;e<this.bucket.length;e++)this.bucket[e]=(e-this.motionCounter)%3?" ":".";this.showBucket(),this.motionCounter++}showBucket(){this.stdout.write(`\r${this.preamble}${this.bucket.join("")}${this.addendum}`)}}({preamble:"Validating add-on"}),this._fs=h,this._request=d}sign({guid:e,version:t,channel:s,xpiPath:r}){const i={upload:this._fs.createReadStream(r)};let o="/addons/",n=this.put;return e?(o+=`${encodeURIComponent(e)}/versions/${encodeURIComponent(t)}/`,s&&(i.channel=s)):(this.debug("Signing add-on without an ID"),n=this.post,i.version=t,s&&this.logger.warn("Specifying a channel for a new add-on is unsupported. New add-ons are always in the unlisted channel.")),n.bind(this)({url:o,formData:i},{throwOnBadResponse:!1}).then((([e,t])=>{const s=t,r=!!s.error;if(-1===[200,201,202].indexOf(e.statusCode)||r){if(s.error)return this.logger.error(`Server response: ${s.error}`,`(status: ${e.statusCode})`),Promise.resolve({success:!1,id:null,downloadedFiles:null,errorCode:"SERVER_FAILURE",errorDetails:s.error});throw new Error(`Received bad response from the server while requesting ${this.absoluteURL(o)}\n\nstatus: ${e.statusCode}\nresponse: ${w(s)}\nheaders: ${JSON.stringify(e.headers||{})}\n`)}return this.waitForSignedAddon(s.url)}))}waitForSignedAddon(e,{_clearTimeout:t=clearTimeout,_setAbortTimeout:s=setTimeout,_setStatusCheckTimeout:r=setTimeout}={}){let i;return new Promise(((o,n)=>{let a;const u=s((()=>{this._progressBar.finish(),t(a),n(new Error(f.oneLine`Signing took too long to complete; last status:
            ${w(i||"[null]")}`))}),this.statusCheckTimeout),l=async()=>{try{const[s,n]=await this.get({url:e});i=n;const h=n.automated_signing,d=n.valid&&n.active&&n.reviewed&&n.files&&n.files.length>0,c=n.valid&&!h;if(d||c){if(this._progressBar.finish(),t(u),c)return this.logger.log(f.oneLine`Your add-on has been submitted for review.
              It passed validation but could not be automatically signed
              because this is a listed add-on.`),void o({success:!1,id:null,downloadedFiles:null,errorCode:"ADDON_NOT_AUTO_SIGNED",errorDetails:null});if(d){const e=await this.downloadSignedFiles(n.files);o({...e,id:n.guid})}}else a=r(l,this.statusCheckInterval)}catch(e){t(u),n(e)}},h=async()=>{try{const[s,n]=await this.get({url:e});i=n,n.processed?(this._progressBar.finish(),this.logger.log("Validation results:",n.validation_url),this._progressBar.setPreamble("Signing add-on"),this._progressBar.animate(),n.valid?l():(this.logger.log("Your add-on failed validation and could not be signed"),t(u),o({success:!1,id:null,downloadedFiles:null,errorCode:"VALIDATION_FAILED",errorDetails:n.validation_url}))):a=r(h,this.statusCheckInterval)}catch(e){t(u),n(e)}};this._progressBar.animate(),h()}))}async downloadSignedFiles(e,{createWriteStream:t=i().createWriteStream,request:s=this._request,stdout:r=process.stdout}={}){const o=[];let a=null,l=0;function h(){let e="...";if(null!==a){const t=(l/a*100).toFixed();let s="";try{s=Array(4-t.length).join(" ")}catch(e){}e=`${s+t}% `}r.write(`\rDownloading signed files: ${e}`)}const d=e=>new Promise(((i,o)=>{const d=u().join(this.downloadDir,(c=e,u().basename(n().parse(c).path).split("?")[0]));var c;const p=t(d);s(this.configureRequest({method:"GET",url:e,followRedirect:!0})).on("error",o).on("response",(t=>{if(t.statusCode<200||t.statusCode>=300)throw new Error(`Got a ${t.statusCode} response when downloading ${e}`);const s=t.headers["content-length"];s&&(null!==a?a+=parseInt(s,10):a=parseInt(s,10))})).on("data",(e=>{l+=e.length,h()})).pipe(p).on("error",o),p.on("finish",(function(){r.write("\n"),i(d)}))}));let c,p=!1;if(e.forEach((e=>{e.signed?o.push(d(e.download_url)):(this.debug("This file was not signed:",e),p=!0)})),!o.length)throw new Error(f.oneLine`The XPI was processed but no signed files were
      found. Check your manifest and make sure it targets Firefox as an
      application.`);return p&&this.logger.log(f.oneLine`Some files were not signed. Re-run with
        --verbose for details.`),h(),c=await Promise.all(o),this.logger.log("Downloaded:"),c.forEach((e=>{this.logger.log(`    ${e.replace(process.cwd(),".")}`)})),{success:!0,id:null,downloadedFiles:c,errorCode:null,errorDetails:null}}get(e,t){return this.request("get",e,t)}post(e,t){return this.request("post",e,t)}put(e,t){return this.request("put",e,t)}patch(e,t){return this.request("patch",e,t)}delete(e,t){return this.request("delete",e,t)}absoluteURL(e){return e.match(/^http/i)?e:this.apiUrlPrefix+e}configureRequest(e,{jwt:t=c()}={}){const s={...this.requestConfig,...e};if(!s.url)throw new Error("request URL was not specified");s.url=this.absoluteURL(String(s.url)),this.proxyServer&&(s.proxy=this.proxyServer);const r=t.sign({iss:this.apiKey},this.apiSecret,{algorithm:"HS256",expiresIn:this.apiJwtExpiresIn});return s.timeout=1e3*this.apiJwtExpiresIn+500,s.headers={Authorization:`JWT ${r}`,Accept:"application/json",...s.headers},s}async request(e,t,{throwOnBadResponse:s=!0}={}){const r=e.toLowerCase(),i=this.configureRequest(t);let[o,n]=await new Promise(((e,t)=>{this.debug(`[API] ${r.toUpperCase()} request:\n`,i),this._request[r].bind(this._request)(i,((s,r,i)=>{s?t(s):e([r,i])}))}));if(s&&(o.statusCode>299||o.statusCode<200))throw new Error(`Received bad response from ${this.absoluteURL(String(i.url))}; status: ${o.statusCode}; response: ${w(n)}`);if(o.headers&&"application/json"===o.headers["content-type"]&&"string"==typeof n)try{n=JSON.parse(n)}catch(e){this.logger.log("Failed to parse JSON response from server:",e)}return this.debug(`[API] ${r.toUpperCase()} response:\n`,`Status: ${o.statusCode}\n`,{headers:o.headers,response:n}),[o,n]}debug(){if(!this.debugLogging)return;function e(t){return"object"==typeof t&&t?(t.headers&&["Authorization","cookie","set-cookie"].forEach((function(e){t.headers[e]&&(t.headers[e]="<REDACTED>")})),Object.keys(t).forEach((function(s){t[s]=e(t[s])})),t):t}const t=Array.prototype.map.call(arguments,(function(t){let s=t;return"object"==typeof s&&(s=h()(s),s=e(s)),s}));this.logger.log("[sign-addon]",...t)}}const y=async({xpiPath:e,id:t,version:r,apiKey:i,apiSecret:o,apiUrlPrefix:n="https://addons.mozilla.org/api/v4",apiJwtExpiresIn:a,verbose:u=!1,channel:l,timeout:h,downloadDir:d,apiProxy:c,apiRequestConfig:p,AMOClient:g=m})=>{function f(e){throw new Error(`required argument was empty: ${e}`)}e||f("xpiPath"),r||f("version"),o||f("apiSecret"),i||f("apiKey");try{if(!(await s.fs.stat(e)).isFile)throw new Error(`not a file: ${e}`)}catch(t){throw new Error(`error with ${e}: ${t}`)}return new g({apiKey:i,apiSecret:o,apiUrlPrefix:n,apiJwtExpiresIn:a,downloadDir:d,debugLogging:u,statusCheckTimeout:h,proxyServer:c,requestConfig:p}).sign({xpiPath:e,guid:t,version:r,channel:l})},v={signAddon:y,signAddonAndExit:async(e,{systemProcess:t=process,throwError:s=!1,logger:r=console})=>{try{const s=await y(e);r.log(s.success?"SUCCESS":"FAIL"),t.exit(s.success?0:1)}catch(e){if(r.error("FAIL"),s)throw e;r.error(e.stack),t.exit(1)}}};module.exports=t.default})();
//# sourceMappingURL=sign-addon.js.map