xhs-mp-core 2.0.28 → 2.0.29
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.
- package/dist/index.js +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("xhs-mp-project"),t=require("xhs-mp-shared"),r=require("events"),o=require("axios"),s=require("path"),i=require("os"),a=require("fs-extra"),n=require("dayjs"),p=require("dayjs/plugin/utc"),c=require("dayjs/plugin/timezone"),l=require("https-proxy-agent"),h=require("querystring"),u=require("fs"),d=require("rxjs"),g=require("lodash"),m=require("rxjs/operators"),f=require("qrcode-terminal"),S=require("jimp"),v=require("jsqr"),k=require("process"),w=require("xhs-mp-compiler-cli");function x(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var y=x(s),C=x(u);const b=()=>({isSit:"false"===process.env.XHS_IS_PROD,isProd:"true"===process.env.XHS_IS_PROD}),_=require("process").env.XHS_BUSINESS_SIT_HOST||"http://business-cli.sl.beta.xiaohongshu.com",I=require("process").env.XHS_CUSTOMER_SIT_HOST||"https://customer.sit.xiaohongshu.com",P={BUSINESS_HOST:b().isSit?_:"https://business.xiaohongshu.com",CUSTOMER_HOST:b().isSit?I:"https://customer.xiaohongshu.com",CUSTOMER_SERVICE_ID:b().isSit?I.replace(/https?:\/\/customer/,"file://miniapp-open"):"file://miniapp-open.xiaohongshu.com"},j={generateQrCode:`${P.CUSTOMER_HOST}/api/cas/generateQrCode`,queryQrCodeStatus:`${P.CUSTOMER_HOST}/api/cas/queryQrCodeStatus`,session:`${P.BUSINESS_HOST}/api/eros/mp/red/code/session`,getUserInfo:`${P.BUSINESS_HOST}/api/eros/mp/red/code/user/info`},M=require("crypto");require("net");const q=e=>{if(!e)return"";const t=1024;return e<t?`${e}B`:e<1048576?`${(e/t).toFixed(2)}KB`:e<t**3?`${(e/1048576).toFixed(2)}MB`:e<t**4?`${(e/t**3).toFixed(2)}GB`:`${(e/t**4).toFixed(2)}T`};function T(e){const t=M.createHash("md5");t.update(e);return t.digest("hex")}function U(e){return e.replace(/\\/g,"/")}const A=U(s.join(i.homedir(),".xhs-mp-cli"));a.ensureDirSync(A);const E=U(s.join(A,"xhs-storage"));a.ensureDirSync(E);const $=require("tough-cookie");var O=new class{constructor(){this.cookiePath=s.join(E,"cookie.json");const e=this.getSerializeData();Object.keys(e).length?this.cookieJar=$.CookieJar.deserializeSync(e):this.cookieJar=new $.CookieJar}getSerializeData(){let e={};return a.existsSync(this.cookiePath)&&(e=a.readJSONSync(this.cookiePath)),e}save(){const e=this.cookieJar.serializeSync();a.writeJSONSync(this.cookiePath,e)}clear(){a.removeSync(this.cookiePath)}set(e){const t=e.headers["set-cookie"]||[],r=e.config.url;t.forEach((e=>{const t=$.Cookie.parse(e);if(t.domain){const e=new $.Cookie(t);this.cookieJar.setCookieSync(e,r)}})),this.save()}get(e){return this.cookieJar.getCookieStringSync(e)}};n.extend(p),n.extend(c),n.tz.setDefault("Asia/Shanghai");let D=0;const H=e=>n.tz().add(D,"millisecond").format(e);let z;o.defaults.baseURL=P.BUSINESS_HOST,o.interceptors.request.use((e=>{const{url:r,data:s,baseURL:i=""}=e;let a=o.getUri(e);if(/^https?:/.test(a))try{const e=new URL(r);a=a.replace(e.origin,"")}catch(e){a=r}const n=O.get(r);return e.headers={...e.headers,Cookie:n},e.headers["User-Agent"]=`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ${t.getLegacyBundleVersion()} Chrome/116.0.5845.228 Electron/26.4.0 Safari/537.36 discover/2.0.0 xhsminiapp/latest`,e})),o.interceptors.response.use((e=>(O.set(e),e))),o.interceptors.response.use((e=>{var t;const{config:r,data:o}=e;if((null===(t=r.url)||void 0===t?void 0:t.startsWith(`${P.BUSINESS_HOST}/api/eros/mp/red`))&&!o.success)throw new Error(`${o.msg}`);return e}),(async e=>{var t,r,s;const{response:i={},config:a}=e;if(401===i.status){if(-240309===(null===(t=i.data)||void 0===t?void 0:t.code))return null==z||z.logout({from:"axios"}),Promise.reject(new Error(i.data.msg||"请求失败,请重新登陆或采用 token 免密登陆"));if(-240099===(null===(r=i.data)||void 0===r?void 0:r.code)){const e=i.headers.date,t=n(e).format("YYYYMMDDHHmm"),r=H("YYYYMMDDHHmm");return r!==t?(((e,t)=>{const r=n(e).diff(n(t));D=r})(t,r),console.log("请求失败:客户端与服务端时间不一致,即将重试",t,r),(p=1e3,new Promise((e=>{setTimeout((()=>{e(null)}),p)}))).then((function(){let e=a;return a.fixConfigWhenRetry&&(e=a.fixConfigWhenRetry(a)),o(e)}))):(null==z||z.logout({from:"axios"}),Promise.reject(new Error(i.data.msg||"请求失败,cli token不匹配")))}if(null===(s=i.data)||void 0===s?void 0:s.msg)return null==z||z.logout({from:"axios"}),Promise.reject(new Error(`code:${i.data.code},msg: ${i.data.msg}`))}var p;return Promise.reject(e)}));class V extends r.EventEmitter{constructor(e){super(),this.core=e.core}get axios(){return e=this.core,z=e,o;var e}getProxyConfig(){const{proxy:e}=this.core.getGlobalConfig();if(e){const t=new URL(e);return{host:t.hostname,port:t.port,protocol:t.protocol,auth:{username:t.username,password:t.password}}}return!1}async request(e){const{method:t,url:r,data:o,config:s={}}=e,{proxy:i}=this.core.getGlobalConfig();i&&(s.proxy=!1,s.httpsAgent=new l.HttpsProxyAgent(i));return await this.axios[t](r,o,{...s})}handleHttpStatus(e){if(200!==e.status)throw new Error(`request fail, code: ${e.status}, errMsg: ${e.status}`);return e}handleStatusCode(e){const{data:t}=e;if(200!==t.statusCode)throw new Error(`request fail, code: ${t.statusCode}, errMsg: ${t.errorMsg}`);return t.data}handleCode(e){const{data:t}=e;if(0!==t.code&&0!==t.error_code)throw new Error(`request fail, code: ${t.code||t.error_code}, errMsg: ${t.msg}`);return t.data}}const L=require("path"),N=require("fs-extra"),R=e=>{if(!N.existsSync(e))return"";let t="";try{t=JSON.stringify(N.readJSONSync(e))}catch(t){console.warn(`readJson error: ${e}`)}return t};class B extends V{constructor(e){super(e),this.getUploadToken=async e=>{const t=await this.request({method:"get",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/upload/permit`,data:{params:e,withCredentials:!0}});return this.handleCode(this.handleHttpStatus(t))},this.project=e.project}async request(e){const{method:t,url:r,data:o,config:s={},fixConfigWhenRetry:i}=e,a=await this.axios[t](r,o,{...s,proxy:this.getProxyConfig(),fixConfigWhenRetry:e=>{let{url:t}=e;if(t.includes("cli_token")){const[r,o=""]=t.split("?"),s=h.parse(o),{cliToken:i,nonce:a,appId:n}=this.core.getTokenParams(this.project.projectAppId),p=r+"?"+h.stringify({...s,cli_token:i,nonce:a,appId:n});e.url=p}return e}});return a}async checkUploadAuthV1({version:e}){const t=this.project,r=t.entryJsonPath,o=L.resolve(t.extJsonPath),s=R(r),i=R(o),a=t.projectAppId,n=`${P.BUSINESS_HOST}/api/eros/mp/red/code/${a}/validate/version/${e}`,p=await this.request({method:"post",url:n,data:{app_json:s,ext_json:i}});return this.handleCode(this.handleHttpStatus(p))}async checkUploadAuthV2(e){const{version:t,appId:r,cliToken:o,nonce:s}=e,i=this.project,a=i.entryJsonPath,n=L.resolve(i.extJsonPath),p=R(a),c=R(n),l=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/validate/version?app_id=${r}&cli_token=${o}&nonce=${s}&version=${t}`,h=await this.request({method:"post",url:l,data:{app_json:p,ext_json:c}});return this.handleCode(this.handleHttpStatus(h))}async createUploadTaskV1(e){const{version:t,userVersion:r,userDesc:o,appId:s,packageMap:i,packageMapSourceMap:a,packageMapV2:n,packageMapV2SourceMap:p}=e,c={method:"post",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/${s}/upload/version/${t}`,data:{user_version:r,user_desc:o,package_map:i,package_map_v2:n,sourcemap:{package_v1:a,package_v2:p},cloud_type:4}};let l=await this.request(c);return l=this.handleCode(this.handleHttpStatus(l)),l}async createUploadTaskV2(e){const{version:t,userVersion:r,userDesc:o,appId:s,packageMap:i,packageMapSourceMap:a,packageMapV2:n,packageMapV2SourceMap:p,cliToken:c,nonce:l}=e,h=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/upload/version?app_id=${s}&cli_token=${c}&nonce=${l}&version=${t}`,u=await this.request({method:"post",url:h,data:{user_version:r,user_desc:o,package_map:i,package_map_v2:n,sourcemap:{package_v1:a,package_v2:p},cloud_type:4}});return this.handleCode(this.handleHttpStatus(u))}async queryTaskDetailV1(e){const{taskId:t}=e;let r=await this.request({method:"get",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/task/detail`,data:{params:{task_id:t}}});return r=this.handleCode(this.handleHttpStatus(r)),r}async queryTaskDetailV2(e){const{taskId:t,appId:r,cliToken:o,nonce:s}=e,i=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/task/detail`;let a=await this.request({method:"get",url:i,data:{params:{task_id:t,app_id:r,cli_token:o,nonce:s}}});return a=this.handleCode(this.handleHttpStatus(a)),a}}const J=(e,t)=>e.reduce(((e,r)=>{let o={};return r.type!==t||r.isSourcemap||(o={[r.root]:r.fileId}),{...e,...o}}),{}),Q=(e,t)=>{var r;const o=null===(r=e.filter((e=>e.type===t&&e.isSourcemap)))||void 0===r?void 0:r[0];return JSON.stringify({md5:null==o?void 0:o.md5,cdnFileUrl:null==o?void 0:o.cdnFileUrl})};class F extends r{constructor(e){super(),this.uploadPkgZipOrSourcemap=(e,t,r,o)=>new d.Observable((s=>{setTimeout((()=>{const{zipPath:i,type:a,root:n}=t,p=i.endsWith("-sourcemap.zip");let c;c=p?this.uploadPkgSourcemap(t):this.uploadPkgZip(e,t,r),c.then((e=>{s.next({...e,type:a,root:n,isSourcemap:p}),s.complete(),null==o||o()})).catch((e=>{s.error(e)}))}),500)})),this.uploadPkgSourcemap=async e=>{const{appId:r,version:o,zipPath:s}=e,i=y.basename(s).split("-")[0],a=T(`${r}_${o}_${i}`),n=(await t.publicCos.upload2Qcloud(s,`${r}/${o}/${i}/${a}`)).files[0];if(200!==n.data.statusCode)throw new Error(`${s}上传失败:${n.error||"unknown error"}`);return{md5:T(C.readFileSync(s)),fileId:n.data.ETag,cdnFileUrl:`https://${n.data.Location}`}},this.uploadPkgZip=(e,r,o,s)=>{const{zipPath:i,type:a,root:n}=r,{appId:p,cliToken:c,nonce:l}=this.core.getTokenParams(this.project.projectAppId),h=new t.Uploader({bizName:"fe",scene:"fe-platform",getToken:t=>{let r=t;return this.core.isTokenAuth(this.project.projectAppId)&&(r={...t,app_id:p,nonce:l,cli_token:c}),e.getUploadToken(r)}});return new Promise(((e,t)=>{setTimeout((()=>{const r=`${"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}-xhs-example.zip`,o=C.readFileSync(y.resolve(i)),p=C.statSync(y.resolve(i));function c(){return new Promise(((e,t)=>{setTimeout((()=>{h.post({Body:o,fileInfo:{name:r,type:"application/octet-stream",size:p.size},FilePath:y.resolve(i)}).then((r=>{var o;return 0!==r.code?t(new Error(`${i}上传失败:${r.msg}`)):(null===(o=null==r?void 0:r.data)||void 0===o?void 0:o.fileId)?(e({fileId:r.data.fileId,type:a,root:n,cdnFileUrl:r.data.previewUrl}),void(null==s||s())):t(new Error(`${i}上传失败`))}))}),500)}))}c().catch(c).catch(c).catch(c).catch(c).then((t=>{e(t)})).catch((e=>{t(e)}))}),500)}))},this.submitTask=e=>this.core.isTokenAuth(this.project.projectAppId)?this.submitTaskV2(e):this.submitTaskV1(e),this.submitTaskV1=e=>{const{uploadApi:t}=e,r=this.getCommonSubmitOptions(e);return d.from(t.createUploadTaskV1(r)).pipe(d.switchMap((e=>{const{task_id:r}=e;return d.interval(1500).pipe(d.switchMap((()=>d.from(t.queryTaskDetailV1({taskId:r})).pipe(d.map((e=>{var t;if(5===e.status)throw new Error(null===(t=null==e?void 0:e.result)||void 0===t?void 0:t.msg);return e}))))),d.first((e=>3===e.status)))})))},this.submitTaskV2=e=>{const{uploadApi:t}=e,{appId:r,cliToken:o,nonce:s}=this.core.getTokenParams(this.project.projectAppId),i=this.getCommonSubmitOptions(e);return d.from(t.createUploadTaskV2({...i,cliToken:o,nonce:s})).pipe(d.switchMap((e=>{const{task_id:i}=e;return d.interval(1500).pipe(d.switchMap((()=>d.from(t.queryTaskDetailV2({taskId:i,appId:r,cliToken:o,nonce:s})).pipe(d.map((e=>{var t;if(5===e.status)throw new Error(null===(t=null==e?void 0:e.result)||void 0===t?void 0:t.msg);return e}))))),d.first((e=>3===e.status)))})))},this.core=e.core,this.project=e.project,this.compilerManager=e.compilerManager,this.logger=e.logger}getCheckUploadAuthFn(e,t){let r;const o=this.core.isTokenAuth(this.project.projectAppId);if(this.logger.debug("Check appid auth..."),o){const{appId:o,cliToken:s,nonce:i}=this.core.getTokenParams(this.project.projectAppId);r=e.checkUploadAuthV2({version:t,appId:o,cliToken:s,nonce:i})}else r=e.checkUploadAuthV1({version:t});return r}getCommonSubmitOptions(e){const{uploadRes:t,appId:r,version:o,userDesc:s,userVersion:i}=e,a=J(t,"v1"),n=Q(t,"v1"),p=J(t,"v2"),c=Q(t,"v2");return{version:o,appId:r,packageMap:a,packageMapSourceMap:n,packageMapV2:g.isEmpty(p)?void 0:p,packageMapV2SourceMap:c,userDesc:s,userVersion:i}}}const{COMPILE_ENTRY:Y}=require("xhs-mp-compiler-cli");class G extends F{constructor(e){super(e),this.doUpload=e=>{const{progressCallback:t,userVersion:r,userDesc:o}=e;if(!(null==r?void 0:r.trim()))throw new Error("请填写上传版本号");if(!(null==o?void 0:o.trim()))throw new Error("请填写版本描述");const s=()=>{var e,t;this.compilerManager.killCompiler(Y.upload),null===(e=this.taskSubscription)||void 0===e||e.unsubscribe(),this.taskSubscription=null,null===(t=this.uploadPromise)||void 0===t||t.resolve(null),this.uploadPromise=null,this.logger.log("Upload Done!!!")},i=e=>{var r,o;null==t||t(-1),null===(r=this.taskSubscription)||void 0===r||r.unsubscribe(),this.taskSubscription=null,this.compilerManager.killCompiler(Y.upload),this.logger.log("Upload Error:",e.message),null===(o=this.uploadPromise)||void 0===o||o.reject(e),this.uploadPromise=null};try{const e=this.project.projectAppId;this.taskSubscription=d.from(this.getCheckUploadAuthFn(this.uploadApi,"develop")).pipe(d.switchMap((e=>{let o=e.can_upload,s=e.can_upload_ext_json,i=e.upload_app_id;if(!o)throw new Error(e.show_msg);if(!i)throw new Error("请检查是否该appid无权限");return null==t||t(5),d.from(this.compilerManager.compileAndZip({entryType:Y.upload,can_upload_ext_json:s,upload_app_id:i,pkgInfo:{version:r}}))})),d.switchMap((r=>{null==t||t(30),this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages...");const o=r.map(((o,s)=>this.uploadPkgZipOrSourcemap(this.uploadApi,{appId:e,zipPath:o.zipPath,type:o.type,root:o.root},s,(()=>{null==t||t(30+45/r.length*(s+1))}))));return d.forkJoin(o)})),d.switchMap((s=>{null==t||t(80),this.logger.log("Upload packages info...");const i={uploadApi:this.uploadApi,uploadRes:s,appId:e,version:"develop",userVersion:r,userDesc:o};return this.submitTask(i)}))).subscribe({next:e=>{null==t||t(100),s()},error:e=>{i(e)}})}catch(e){i(e)}},this.uploadApi=new B(e)}upload(e){return new Promise(((t,r)=>{this.uploadPromise={resolve:t,reject:r},this.doUpload(e)}))}}class W extends V{async generateQrCode(){const e=await this.request({method:"post",url:j.generateQrCode,data:{subsystem:"business"}});return this.handleStatusCode(this.handleHttpStatus(e))}async queryQrCodeStatus(e){const t=await this.request({method:"get",url:j.queryQrCodeStatus,data:{params:{qrId:e,service:P.CUSTOMER_SERVICE_ID}}});return this.handleStatusCode(this.handleHttpStatus(t))}async login(e){const t=await this.request({method:"post",url:j.session,data:{ticket:e,clientId:P.CUSTOMER_SERVICE_ID}});return this.handleHttpStatus(t).data}async fetchUserInfo(){const e=await this.request({method:"get",url:j.getUserInfo});return this.handleCode(this.handleHttpStatus(e))}}class Z{get isLogin(){return this._isLogin}set isLogin(e){this._isLogin=e}get userInfo(){return this._userInfo}set userInfo(e){this._userInfo=e,this.storage.set("xhs-cli-userInfo",e)}constructor(e){var t;this.qrCodeStatusData={},this.startPollingSub=null,this.loginPromise={},this.transformUserInfo=e=>{const{nick:t,avatar:r,desc:o,gender:s}=(i=e,["nick","avatar","desc","gender"].reduce(((e,t)=>({...e,[t]:i[t]})),{}));var i;return{nickName:t,avatar:r,userId:"",desc:o,gender:s}},this.queryQrCodeStatus=e=>d.from(this.userApi.queryQrCodeStatus(e)),this.doLogin=async e=>{const{resolve:t,reject:r}=this.loginPromise;this.loginPromise=null;try{const o=await this.userApi.login(e);if(!o.success)return void r(new Error(o.msg));const s=await this.userApi.fetchUserInfo(),i=this.transformUserInfo(s);i.userInfoData=s,t(i)}catch(e){return void r(new Error(e.message))}},this.startPolling=()=>(this.qrCodeStatusData.isLoading=!0,this.qrCodeStatusData.expired=!1,d.from(d.defer((()=>this.userApi.generateQrCode()))).pipe(m.tap((e=>{this.qrUrl=e.qrUrl,this.qrCodeStatusData.isLoading=!1,this.showQrCode(),setTimeout((()=>{this.qrCodeStatusData.expired=!0,this.stopPolling()}),6e4)})),m.exhaustMap((({qrUrl:e,qrId:t})=>d.interval(2e3).pipe(m.switchMap((()=>this.queryQrCodeStatus(t))),m.tap((e=>{if(4===e.status)throw new Error("retry login");1===e.status&&(this.stopPolling(),this.doLogin(e.ticket))}))))),m.takeWhile((e=>1!==e.status)),m.retry(5))),this.stopPolling=()=>{this.startPollingSub&&(this.startPollingSub.unsubscribe(),this.startPollingSub=null)};const{storage:r,logger:o}=e;this.storage=r,this.logger=o,this.userApi=new W(e),this.qrCodeStatusData={isLoading:!1,expired:!1},this._userInfo=r.get("userInfo")||r.get("xhs-cli-userInfo")||{},this.isLogin=!!(null===(t=this.userInfo)||void 0===t?void 0:t.nickName)}showQrCode(){f.generate(this.qrUrl,{small:!0})}async login(e="qrcode"){if(this.isLogin)this.logger.log("Had Login!!!");else{this.isLogin=!1,this.logger.log("Login...");try{if("qrcode"!==e)throw new Error("暂不支持扫码之外的其他登陆方式");{const e=await this.loginByQrcode();this.userInfo=e}this.isLogin=!0,this.logger.log("Login success")}catch(e){throw this.logger.log("Login fail:",e.message),this.isLogin=!1,this.userInfo=null,e}}}loginByQrcode(){return new Promise(((e,t)=>{this.loginPromise={resolve:e,reject:t};try{this.startPollingSub=this.startPolling().subscribe()}catch(e){console.error(e)}}))}logout(e){"axios"!==e.from&&this.logger.log("Logout..."),this.isLogin=!1,this.userInfo={},O.clear(),"axios"!==e.from&&this.logger.log("Logout Success!!!")}}const X=async(e,t={},r,o)=>{let s=e.getCompileEntryPage();s={...s,...t};const{path:i,query:a,launchMode:n}=s;try{let e=await(async e=>{const t=Buffer.from(e.replace(/^data:image\/[a-z]+;base64,/,""),"base64"),r=await S.read(t),o={data:new Uint8ClampedArray(r.bitmap.data),width:r.bitmap.width,height:r.bitmap.height},s=v(o.data,o.width,o.height);if(!s)throw new Error("QR code not found in the image.");return s.data})(r);return i&&(e=e.replace("_develop",`_develop${i.startsWith("/")?"":"/"}${i}`)),a&&(e+=`&${a}`),"halfPageNativeFunctionalized"===n&&(e+="&runtime_mode=2"),e}catch(e){o.error("二维码解码失败:",e)}},{COMPILE_ENTRY:K}=require("xhs-mp-compiler-cli");class ee extends F{constructor(e){super(e),this.progressData={},this.previewData={},this.calcSize=e=>{var t,r;const o=this.project,s=(null===(t=null==o?void 0:o.flags)||void 0===t?void 0:t.enableV2Preivew)?"v2":"v1",i=(null===(r=null==e?void 0:e.filter)||void 0===r?void 0:r.call(e,(e=>e.type===s)).sort(((e,t)=>t.zipSize-e.zipSize)))||[];this.previewData.subPkgs=i.map(((e,t)=>({key:t,path:e.root,size:q(e.zipSize)})));const a=i.reduce(((e,t)=>t.zipSize+e),0)||0;this.previewData.zipSize=q(a)},this.uploadApi=new B(e),this.progressData={},this.previewData={}}preview(e){return new Promise(((t,r)=>{this.previewPromise={resolve:t,reject:r},this.doPreview(e)}))}doPreview(e){this.progressData.previewIsLoading=!0;const t=this.project.projectAppId,r=Date.now(),o=async t=>{var o,s;const i=JSON.parse(t.result.extra_json);this.previewData.qrcodeUrl=await X(this.project,e.entry,i.qrcode,this.logger),this.showQrCode(this.previewData.qrcodeUrl),this.previewData.previewTotalTime=+((Date.now()-r)/1e3).toFixed(1),this.progressData.previewIsLoading=!1,this.compilerManager.killCompiler(K.preview),null===(o=this.taskSubscription)||void 0===o||o.unsubscribe(),this.taskSubscription=null,null===(s=this.previewPromise)||void 0===s||s.resolve({qrcodeUrl:this.previewData.qrcodeUrl}),this.previewPromise=null,this.logger.log("Preview Done!!!")},s=e=>{var t,r;this.compilerManager.killCompiler(K.preview),null===(t=this.taskSubscription)||void 0===t||t.unsubscribe(),this.taskSubscription=null,null===(r=this.previewPromise)||void 0===r||r.reject(e),this.previewPromise=null,this.logger.log("Preview Error:",e.toString())};this.taskSubscription=d.from(this.getCheckUploadAuthFn(this.uploadApi,"debug")).pipe(d.switchMap((e=>{let t=e.can_upload_ext_json,r=e.upload_app_id;if(!r)throw new Error("请检查是否该appid无权限");return d.from(this.compilerManager.compileAndZip({entryType:K.preview,can_upload_ext_json:t,upload_app_id:r}))})),d.tap((e=>{this.calcSize(e)})),d.switchMap((e=>{this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages...");const r=e.map(((e,r)=>this.uploadPkgZipOrSourcemap(this.uploadApi,{appId:t,zipPath:e.zipPath,type:e.type,root:e.root},r)));return d.forkJoin(r)})),d.switchMap((e=>(this.logger.log("Upload packages info..."),this.submitTask({uploadApi:this.uploadApi,uploadRes:e,appId:t,version:"debug"}))))).subscribe({next:e=>o(e),error:e=>s(e)})}showQrCode(e){f.generate(e,{small:!0})}}const te={code:"code",cli:"cli"};class re{constructor({core:e}){this.data={},this.core=e,this.extract()}extract(){if(this.core.scene===te.cli){if(this.jsonPath=s.join(E,"storage.json"),a.existsSync(this.jsonPath))try{this.data=a.readJSONSync(this.jsonPath)}catch(e){this.data={}}}else this.data={}}store(){this.core.scene===te.cli&&a.writeJSONSync(this.jsonPath,this.data)}get(e){return this.data[e]}set(e,t){this.data[e]=t,this.refresh()}refresh(){this.store()}}exports.Core=class{constructor(e){this.globalConfig={},this.appConfigMap={},this.projectMap={},this.compilerManagerMap={},this.scene=te.code;const{scene:r=te.code}=e;this.scene=r,this.logger=new t.Logger("[xhs-mp-cli]"),this.storage=new re({core:this}),this.globalConfig=this.storage.get("xhs-cli-global-config")||{},this.appConfigMap=this.storage.get("xhs-cli-app-config")||{},this.logger.debug("get initial config:",this.globalConfig,this.appConfigMap),globalThis.logger=this.logger,this.loginManager=new Z({core:this,storage:this.storage,logger:this.logger})}setGlobalConfig(e={}){this.globalConfig={...this.globalConfig||{},...e},this.storage.set("xhs-cli-global-config",e),this.logger.log("Set global config done")}getGlobalConfig(){return this.globalConfig||{}}setAppConfig(e={}){const{appId:t,config:r}=e;t?(this.appConfigMap[t]={...this.appConfigMap[t]||{},...r},this.storage.set("xhs-cli-app-config",this.appConfigMap),this.logger.log("Set app config done")):this.logger.error("没有传递 appid 参数")}getAppConfig(e){return this.appConfigMap[e]||{}}createOrGetProject(t){let r=t.projectPath;if(!r)throw new Error("没有配置projectPath");return s.isAbsolute(r)||(r=s.join(k.cwd(),r)),this.projectMap[r]||(this.projectMap[r]=new e.Project(t)),this.projectMap[r]}getCompilerManager(e,t){let r=e.projectPath;if(s.isAbsolute(r)||(r=s.join(k.cwd(),r)),!this.compilerManagerMap[r]){const o=this.createOrGetProject(e);this.compilerManagerMap[r]=new w.ProjectCompilerManager({...t,project:o,logger:this.logger})}return this.compilerManagerMap[r]}async login(e={}){e.verbose&&this.logger.setVerbose(!0);const{type:t="qrcode"}=e;await this.loginManager.login(t)}logout(e){this.loginManager.logout(e)}isTokenAuth(e){return!!this.getAppConfig(e).token}getTokenParams(e){const t=this.getAppConfig(e).token,r="xxxxxxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})),o=e+"#"+t+"#"+r+"#"+H("YYYYMMDDHHmm"),s=T(o);return this.logger.debug("cliToken",o,s),{cliToken:s,nonce:r,appId:e}}checkAppId(e){if(!this.appConfigMap[e])throw new Error(`找不到项目内appId(${e})对应的配置,请先确认appId是否保持一致`)}async preview(e){e.verbose&&this.logger.setVerbose(!0);const t=e.project||{},r=e.buildConfig||{},o=this.createOrGetProject(t);this.checkAppId(o.projectAppId),this.logger.log("Project:",o.projectPath),this.logger.debug("Preview options:",e);const s=this.appConfigMap[o.projectAppId];(null==s?void 0:s.token)?this.logger.debug("Auth by token"):(this.logger.debug("Auth by qrCode"),this.loginManager.isLogin||await this.login());const i=this.getCompilerManager(t,r),a=new ee({core:this,project:o,compilerManager:i,logger:this.logger});try{return await a.preview({entry:e.entry})}finally{i.killAll()}}async upload(e){const{project:t,buildConfig:r={},version:o,desc:s,progressCallback:i}=e;e.verbose&&this.logger.setVerbose(!0);const a=this.createOrGetProject(t);this.checkAppId(a.projectAppId),this.logger.log("ProjectPath:",a.projectPath),this.logger.debug("Upload options:",e);const n=this.appConfigMap[a.projectAppId];(null==n?void 0:n.token)?this.logger.debug("Auth by token"):(this.logger.debug("Auth by login"),this.loginManager.isLogin||await this.login());const p=this.getCompilerManager(t,r),c=new G({core:this,project:a,compilerManager:p,logger:this.logger});try{return await c.upload({userVersion:o,userDesc:s,progressCallback:i})}finally{p.killAll()}}};
|
|
1
|
+
"use strict";var e=require("xhs-mp-project"),t=require("xhs-mp-shared"),r=require("events"),o=require("axios"),s=require("path"),i=require("os"),a=require("fs-extra"),n=require("dayjs"),p=require("dayjs/plugin/utc"),c=require("dayjs/plugin/timezone"),l=require("https-proxy-agent"),h=require("querystring"),u=require("fs"),d=require("rxjs"),g=require("lodash"),m=require("rxjs/operators"),f=require("qrcode-terminal"),S=require("jimp"),v=require("jsqr"),k=require("process"),w=require("xhs-mp-compiler-cli");function x(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var y=x(s),C=x(u);const b=()=>({isSit:"false"===process.env.XHS_IS_PROD,isProd:"true"===process.env.XHS_IS_PROD}),_=require("process").env.XHS_BUSINESS_SIT_HOST||"http://business-cli.sl.beta.xiaohongshu.com",I=require("process").env.XHS_CUSTOMER_SIT_HOST||"https://customer.sit.xiaohongshu.com",P={BUSINESS_HOST:b().isSit?_:"https://business.xiaohongshu.com",CUSTOMER_HOST:b().isSit?I:"https://customer.xiaohongshu.com",CUSTOMER_SERVICE_ID:b().isSit?I.replace(/https?:\/\/customer/,"file://miniapp-open"):"file://miniapp-open.xiaohongshu.com"},j={generateQrCode:`${P.CUSTOMER_HOST}/api/cas/generateQrCode`,queryQrCodeStatus:`${P.CUSTOMER_HOST}/api/cas/queryQrCodeStatus`,session:`${P.BUSINESS_HOST}/api/eros/mp/red/code/session`,getUserInfo:`${P.BUSINESS_HOST}/api/eros/mp/red/code/user/info`},M=require("crypto");require("net");const q=e=>{if(!e)return"";const t=1024;return e<t?`${e}B`:e<1048576?`${(e/t).toFixed(2)}KB`:e<t**3?`${(e/1048576).toFixed(2)}MB`:e<t**4?`${(e/t**3).toFixed(2)}GB`:`${(e/t**4).toFixed(2)}T`};function T(e){const t=M.createHash("md5");t.update(e);return t.digest("hex")}function U(e){return e.replace(/\\/g,"/")}const A=U(s.join(i.homedir(),".xhs-mp-cli"));a.ensureDirSync(A);const E=U(s.join(A,"xhs-storage"));a.ensureDirSync(E);const $=require("tough-cookie");var O=new class{constructor(){this.cookiePath=s.join(E,"cookie.json");const e=this.getSerializeData();Object.keys(e).length?this.cookieJar=$.CookieJar.deserializeSync(e):this.cookieJar=new $.CookieJar}getSerializeData(){let e={};return a.existsSync(this.cookiePath)&&(e=a.readJSONSync(this.cookiePath)),e}save(){const e=this.cookieJar.serializeSync();a.writeJSONSync(this.cookiePath,e)}clear(){a.removeSync(this.cookiePath)}set(e){const t=e.headers["set-cookie"]||[],r=e.config.url;t.forEach((e=>{const t=$.Cookie.parse(e);if(t.domain){const e=new $.Cookie(t);this.cookieJar.setCookieSync(e,r)}})),this.save()}get(e){return this.cookieJar.getCookieStringSync(e)}};n.extend(p),n.extend(c),n.tz.setDefault("Asia/Shanghai");let D=0;const H=e=>n.tz().add(D,"millisecond").format(e);let z;o.defaults.baseURL=P.BUSINESS_HOST,o.interceptors.request.use((e=>{const{url:r,data:s,baseURL:i=""}=e;let a=o.getUri(e);if(/^https?:/.test(a))try{const e=new URL(r);a=a.replace(e.origin,"")}catch(e){a=r}const n=O.get(r);return e.headers={...e.headers,Cookie:n},e.headers["User-Agent"]=`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ${t.getLegacyBundleVersion()} Chrome/116.0.5845.228 Electron/26.4.0 Safari/537.36 discover/2.0.0 xhsminiapp/latest`,e})),o.interceptors.response.use((e=>(O.set(e),e))),o.interceptors.response.use((e=>{var t;const{config:r,data:o}=e;if((null===(t=r.url)||void 0===t?void 0:t.startsWith(`${P.BUSINESS_HOST}/api/eros/mp/red`))&&!o.success)throw new Error(`${o.msg}`);return e}),(async e=>{var t,r,s;const{response:i={},config:a}=e;if(401===i.status){if(-240309===(null===(t=i.data)||void 0===t?void 0:t.code))return null==z||z.logout({from:"axios"}),Promise.reject(new Error(i.data.msg||"请求失败,请重新登陆或采用 token 免密登陆"));if(-240099===(null===(r=i.data)||void 0===r?void 0:r.code)){const e=i.headers.date,t=n(e).format("YYYYMMDDHHmm"),r=H("YYYYMMDDHHmm");return r!==t?(((e,t)=>{const r=n(e).diff(n(t));D=r})(t,r),console.log("请求失败:客户端与服务端时间不一致,即将重试",t,r),(p=1e3,new Promise((e=>{setTimeout((()=>{e(null)}),p)}))).then((function(){let e=a;return a.fixConfigWhenRetry&&(e=a.fixConfigWhenRetry(a)),o(e)}))):(null==z||z.logout({from:"axios"}),Promise.reject(new Error(i.data.msg||"请求失败,cli token不匹配")))}if(null===(s=i.data)||void 0===s?void 0:s.msg)return null==z||z.logout({from:"axios"}),Promise.reject(new Error(`code:${i.data.code},msg: ${i.data.msg}`))}var p;return Promise.reject(e)}));class V extends r.EventEmitter{constructor(e){super(),this.core=e.core}get axios(){return e=this.core,z=e,o;var e}getProxyConfig(){const{proxy:e}=this.core.getGlobalConfig();if(e){const t=new URL(e);return{host:t.hostname,port:t.port,protocol:t.protocol,auth:{username:t.username,password:t.password}}}return!1}async request(e){const{method:t,url:r,data:o,config:s={}}=e,{proxy:i}=this.core.getGlobalConfig();i&&(s.proxy=!1,s.httpsAgent=new l.HttpsProxyAgent(i));return await this.axios[t](r,o,{...s})}handleHttpStatus(e){if(200!==e.status)throw new Error(`request fail, code: ${e.status}, errMsg: ${e.status}`);return e}handleStatusCode(e){const{data:t}=e;if(200!==t.statusCode)throw new Error(`request fail, code: ${t.statusCode}, errMsg: ${t.errorMsg}`);return t.data}handleCode(e){const{data:t}=e;if(0!==t.code&&0!==t.error_code)throw new Error(`request fail, code: ${t.code||t.error_code}, errMsg: ${t.msg}`);return t.data}}const L=require("path"),N=require("fs-extra"),R=e=>{if(!N.existsSync(e))return"";let t="";try{t=JSON.stringify(N.readJSONSync(e))}catch(t){console.warn(`readJson error: ${e}`)}return t};class B extends V{constructor(e){super(e),this.getUploadToken=async e=>{const t=await this.request({method:"get",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/upload/permit`,data:{params:e,withCredentials:!0}});return this.handleCode(this.handleHttpStatus(t))},this.project=e.project}async request(e){const{method:t,url:r,data:o,config:s={},fixConfigWhenRetry:i}=e,{proxy:a}=this.core.getGlobalConfig();a&&(s.proxy=!1,s.httpsAgent=new l.HttpsProxyAgent(a));const n=await this.axios[t](r,o,{...s,fixConfigWhenRetry:e=>{let{url:t}=e;if(t.includes("cli_token")){const[r,o=""]=t.split("?"),s=h.parse(o),{cliToken:i,nonce:a,appId:n}=this.core.getTokenParams(this.project.projectAppId),p=r+"?"+h.stringify({...s,cli_token:i,nonce:a,appId:n});e.url=p}return e}});return n}async checkUploadAuthV1({version:e}){const t=this.project,r=t.entryJsonPath,o=L.resolve(t.extJsonPath),s=R(r),i=R(o),a=t.projectAppId,n=`${P.BUSINESS_HOST}/api/eros/mp/red/code/${a}/validate/version/${e}`,p=await this.request({method:"post",url:n,data:{app_json:s,ext_json:i}});return this.handleCode(this.handleHttpStatus(p))}async checkUploadAuthV2(e){const{version:t,appId:r,cliToken:o,nonce:s}=e,i=this.project,a=i.entryJsonPath,n=L.resolve(i.extJsonPath),p=R(a),c=R(n),l=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/validate/version?app_id=${r}&cli_token=${o}&nonce=${s}&version=${t}`,h=await this.request({method:"post",url:l,data:{app_json:p,ext_json:c}});return this.handleCode(this.handleHttpStatus(h))}async createUploadTaskV1(e){const{version:t,userVersion:r,userDesc:o,appId:s,packageMap:i,packageMapSourceMap:a,packageMapV2:n,packageMapV2SourceMap:p}=e,c={method:"post",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/${s}/upload/version/${t}`,data:{user_version:r,user_desc:o,package_map:i,package_map_v2:n,sourcemap:{package_v1:a,package_v2:p},cloud_type:4}};let l=await this.request(c);return l=this.handleCode(this.handleHttpStatus(l)),l}async createUploadTaskV2(e){const{version:t,userVersion:r,userDesc:o,appId:s,packageMap:i,packageMapSourceMap:a,packageMapV2:n,packageMapV2SourceMap:p,cliToken:c,nonce:l}=e,h=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/upload/version?app_id=${s}&cli_token=${c}&nonce=${l}&version=${t}`,u=await this.request({method:"post",url:h,data:{user_version:r,user_desc:o,package_map:i,package_map_v2:n,sourcemap:{package_v1:a,package_v2:p},cloud_type:4}});return this.handleCode(this.handleHttpStatus(u))}async queryTaskDetailV1(e){const{taskId:t}=e;let r=await this.request({method:"get",url:`${P.BUSINESS_HOST}/api/eros/mp/red/code/task/detail`,data:{params:{task_id:t}}});return r=this.handleCode(this.handleHttpStatus(r)),r}async queryTaskDetailV2(e){const{taskId:t,appId:r,cliToken:o,nonce:s}=e,i=`${P.BUSINESS_HOST}/api/eros/mp/red/code/v2/task/detail`;let a=await this.request({method:"get",url:i,data:{params:{task_id:t,app_id:r,cli_token:o,nonce:s}}});return a=this.handleCode(this.handleHttpStatus(a)),a}}const J=(e,t)=>e.reduce(((e,r)=>{let o={};return r.type!==t||r.isSourcemap||(o={[r.root]:r.fileId}),{...e,...o}}),{}),Q=(e,t)=>{var r;const o=null===(r=e.filter((e=>e.type===t&&e.isSourcemap)))||void 0===r?void 0:r[0];return JSON.stringify({md5:null==o?void 0:o.md5,cdnFileUrl:null==o?void 0:o.cdnFileUrl})};class F extends r{constructor(e){super(),this.uploadPkgZipOrSourcemap=(e,t,r,o)=>new d.Observable((s=>{setTimeout((()=>{const{zipPath:i,type:a,root:n}=t,p=i.endsWith("-sourcemap.zip");let c;c=p?this.uploadPkgSourcemap(t):this.uploadPkgZip(e,t,r),c.then((e=>{s.next({...e,type:a,root:n,isSourcemap:p}),s.complete(),null==o||o()})).catch((e=>{s.error(e)}))}),500)})),this.uploadPkgSourcemap=async e=>{const{appId:r,version:o,zipPath:s}=e,i=y.basename(s).split("-")[0],a=T(`${r}_${o}_${i}`),n=(await t.publicCos.upload2Qcloud(s,`${r}/${o}/${i}/${a}`)).files[0];if(200!==n.data.statusCode)throw new Error(`${s}上传失败:${n.error||"unknown error"}`);return{md5:T(C.readFileSync(s)),fileId:n.data.ETag,cdnFileUrl:`https://${n.data.Location}`}},this.uploadPkgZip=(e,r,o,s)=>{const{zipPath:i,type:a,root:n}=r,{appId:p,cliToken:c,nonce:l}=this.core.getTokenParams(this.project.projectAppId),h=new t.Uploader({bizName:"fe",scene:"fe-platform",getToken:t=>{let r=t;return this.core.isTokenAuth(this.project.projectAppId)&&(r={...t,app_id:p,nonce:l,cli_token:c}),e.getUploadToken(r)}});return new Promise(((e,t)=>{setTimeout((()=>{const r=`${"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}-xhs-example.zip`,o=C.readFileSync(y.resolve(i)),p=C.statSync(y.resolve(i));function c(){return new Promise(((e,t)=>{setTimeout((()=>{h.post({Body:o,fileInfo:{name:r,type:"application/octet-stream",size:p.size},FilePath:y.resolve(i)}).then((r=>{var o;return 0!==r.code?t(new Error(`${i}上传失败:${r.msg}`)):(null===(o=null==r?void 0:r.data)||void 0===o?void 0:o.fileId)?(e({fileId:r.data.fileId,type:a,root:n,cdnFileUrl:r.data.previewUrl}),void(null==s||s())):t(new Error(`${i}上传失败`))}))}),500)}))}c().catch(c).catch(c).catch(c).catch(c).then((t=>{e(t)})).catch((e=>{t(e)}))}),500)}))},this.submitTask=e=>this.core.isTokenAuth(this.project.projectAppId)?this.submitTaskV2(e):this.submitTaskV1(e),this.submitTaskV1=e=>{const{uploadApi:t}=e,r=this.getCommonSubmitOptions(e);return d.from(t.createUploadTaskV1(r)).pipe(d.switchMap((e=>{const{task_id:r}=e;return d.interval(1500).pipe(d.switchMap((()=>d.from(t.queryTaskDetailV1({taskId:r})).pipe(d.map((e=>{var t;if(5===e.status)throw new Error(null===(t=null==e?void 0:e.result)||void 0===t?void 0:t.msg);return e}))))),d.first((e=>3===e.status)))})))},this.submitTaskV2=e=>{const{uploadApi:t}=e,{appId:r,cliToken:o,nonce:s}=this.core.getTokenParams(this.project.projectAppId),i=this.getCommonSubmitOptions(e);return d.from(t.createUploadTaskV2({...i,cliToken:o,nonce:s})).pipe(d.switchMap((e=>{const{task_id:i}=e;return d.interval(1500).pipe(d.switchMap((()=>d.from(t.queryTaskDetailV2({taskId:i,appId:r,cliToken:o,nonce:s})).pipe(d.map((e=>{var t;if(5===e.status)throw new Error(null===(t=null==e?void 0:e.result)||void 0===t?void 0:t.msg);return e}))))),d.first((e=>3===e.status)))})))},this.core=e.core,this.project=e.project,this.compilerManager=e.compilerManager,this.logger=e.logger}getCheckUploadAuthFn(e,t){let r;const o=this.core.isTokenAuth(this.project.projectAppId);if(this.logger.debug("Check appid auth..."),o){const{appId:o,cliToken:s,nonce:i}=this.core.getTokenParams(this.project.projectAppId);r=e.checkUploadAuthV2({version:t,appId:o,cliToken:s,nonce:i})}else r=e.checkUploadAuthV1({version:t});return r}getCommonSubmitOptions(e){const{uploadRes:t,appId:r,version:o,userDesc:s,userVersion:i}=e,a=J(t,"v1"),n=Q(t,"v1"),p=J(t,"v2"),c=Q(t,"v2");return{version:o,appId:r,packageMap:a,packageMapSourceMap:n,packageMapV2:g.isEmpty(p)?void 0:p,packageMapV2SourceMap:c,userDesc:s,userVersion:i}}}const{COMPILE_ENTRY:Y}=require("xhs-mp-compiler-cli");class G extends F{constructor(e){super(e),this.doUpload=e=>{const{progressCallback:t,userVersion:r,userDesc:o}=e;if(!(null==r?void 0:r.trim()))throw new Error("请填写上传版本号");if(!(null==o?void 0:o.trim()))throw new Error("请填写版本描述");const s=()=>{var e,t;this.compilerManager.killCompiler(Y.upload),null===(e=this.taskSubscription)||void 0===e||e.unsubscribe(),this.taskSubscription=null,null===(t=this.uploadPromise)||void 0===t||t.resolve(null),this.uploadPromise=null,this.logger.log("Upload Done!!!")},i=e=>{var r,o;null==t||t(-1),null===(r=this.taskSubscription)||void 0===r||r.unsubscribe(),this.taskSubscription=null,this.compilerManager.killCompiler(Y.upload),this.logger.log("Upload Error:",e.message),null===(o=this.uploadPromise)||void 0===o||o.reject(e),this.uploadPromise=null};try{const e=this.project.projectAppId;this.taskSubscription=d.from(this.getCheckUploadAuthFn(this.uploadApi,"develop")).pipe(d.switchMap((e=>{let o=e.can_upload,s=e.can_upload_ext_json,i=e.upload_app_id;if(!o)throw new Error(e.show_msg);if(!i)throw new Error("请检查是否该appid无权限");return null==t||t(5),d.from(this.compilerManager.compileAndZip({entryType:Y.upload,can_upload_ext_json:s,upload_app_id:i,pkgInfo:{version:r}}))})),d.switchMap((r=>{null==t||t(30),this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages...");const o=r.map(((o,s)=>this.uploadPkgZipOrSourcemap(this.uploadApi,{appId:e,zipPath:o.zipPath,type:o.type,root:o.root},s,(()=>{null==t||t(30+45/r.length*(s+1))}))));return d.forkJoin(o)})),d.switchMap((s=>{null==t||t(80),this.logger.log("Upload packages info...");const i={uploadApi:this.uploadApi,uploadRes:s,appId:e,version:"develop",userVersion:r,userDesc:o};return this.submitTask(i)}))).subscribe({next:e=>{null==t||t(100),s()},error:e=>{i(e)}})}catch(e){i(e)}},this.uploadApi=new B(e)}upload(e){return new Promise(((t,r)=>{this.uploadPromise={resolve:t,reject:r},this.doUpload(e)}))}}class W extends V{async generateQrCode(){const e=await this.request({method:"post",url:j.generateQrCode,data:{subsystem:"business"}});return this.handleStatusCode(this.handleHttpStatus(e))}async queryQrCodeStatus(e){const t=await this.request({method:"get",url:j.queryQrCodeStatus,data:{params:{qrId:e,service:P.CUSTOMER_SERVICE_ID}}});return this.handleStatusCode(this.handleHttpStatus(t))}async login(e){const t=await this.request({method:"post",url:j.session,data:{ticket:e,clientId:P.CUSTOMER_SERVICE_ID}});return this.handleHttpStatus(t).data}async fetchUserInfo(){const e=await this.request({method:"get",url:j.getUserInfo});return this.handleCode(this.handleHttpStatus(e))}}class Z{get isLogin(){return this._isLogin}set isLogin(e){this._isLogin=e}get userInfo(){return this._userInfo}set userInfo(e){this._userInfo=e,this.storage.set("xhs-cli-userInfo",e)}constructor(e){var t;this.qrCodeStatusData={},this.startPollingSub=null,this.loginPromise={},this.transformUserInfo=e=>{const{nick:t,avatar:r,desc:o,gender:s}=(i=e,["nick","avatar","desc","gender"].reduce(((e,t)=>({...e,[t]:i[t]})),{}));var i;return{nickName:t,avatar:r,userId:"",desc:o,gender:s}},this.queryQrCodeStatus=e=>d.from(this.userApi.queryQrCodeStatus(e)),this.doLogin=async e=>{const{resolve:t,reject:r}=this.loginPromise;this.loginPromise=null;try{const o=await this.userApi.login(e);if(!o.success)return void r(new Error(o.msg));const s=await this.userApi.fetchUserInfo(),i=this.transformUserInfo(s);i.userInfoData=s,t(i)}catch(e){return void r(new Error(e.message))}},this.startPolling=()=>(this.qrCodeStatusData.isLoading=!0,this.qrCodeStatusData.expired=!1,d.from(d.defer((()=>this.userApi.generateQrCode()))).pipe(m.tap((e=>{this.qrUrl=e.qrUrl,this.qrCodeStatusData.isLoading=!1,this.showQrCode(),setTimeout((()=>{this.qrCodeStatusData.expired=!0,this.stopPolling()}),6e4)})),m.exhaustMap((({qrUrl:e,qrId:t})=>d.interval(2e3).pipe(m.switchMap((()=>this.queryQrCodeStatus(t))),m.tap((e=>{if(4===e.status)throw new Error("retry login");1===e.status&&(this.stopPolling(),this.doLogin(e.ticket))}))))),m.takeWhile((e=>1!==e.status)),m.retry(5))),this.stopPolling=()=>{this.startPollingSub&&(this.startPollingSub.unsubscribe(),this.startPollingSub=null)};const{storage:r,logger:o}=e;this.storage=r,this.logger=o,this.userApi=new W(e),this.qrCodeStatusData={isLoading:!1,expired:!1},this._userInfo=r.get("userInfo")||r.get("xhs-cli-userInfo")||{},this.isLogin=!!(null===(t=this.userInfo)||void 0===t?void 0:t.nickName)}showQrCode(){f.generate(this.qrUrl,{small:!0})}async login(e="qrcode"){if(this.isLogin)this.logger.log("Had Login!!!");else{this.isLogin=!1,this.logger.log("Login...");try{if("qrcode"!==e)throw new Error("暂不支持扫码之外的其他登陆方式");{const e=await this.loginByQrcode();this.userInfo=e}this.isLogin=!0,this.logger.log("Login success")}catch(e){throw this.logger.log("Login fail:",e.message),this.isLogin=!1,this.userInfo=null,e}}}loginByQrcode(){return new Promise(((e,t)=>{this.loginPromise={resolve:e,reject:t};try{this.startPollingSub=this.startPolling().subscribe()}catch(e){console.error(e)}}))}logout(e){"axios"!==e.from&&this.logger.log("Logout..."),this.isLogin=!1,this.userInfo={},O.clear(),"axios"!==e.from&&this.logger.log("Logout Success!!!")}}const X=async(e,t={},r,o)=>{let s=e.getCompileEntryPage();s={...s,...t};const{path:i,query:a,launchMode:n}=s;try{let e=await(async e=>{const t=Buffer.from(e.replace(/^data:image\/[a-z]+;base64,/,""),"base64"),r=await S.read(t),o={data:new Uint8ClampedArray(r.bitmap.data),width:r.bitmap.width,height:r.bitmap.height},s=v(o.data,o.width,o.height);if(!s)throw new Error("QR code not found in the image.");return s.data})(r);return i&&(e=e.replace("_develop",`_develop${i.startsWith("/")?"":"/"}${i}`)),a&&(e+=`&${a}`),"halfPageNativeFunctionalized"===n&&(e+="&runtime_mode=2"),e}catch(e){o.error("二维码解码失败:",e)}},{COMPILE_ENTRY:K}=require("xhs-mp-compiler-cli");class ee extends F{constructor(e){super(e),this.progressData={},this.previewData={},this.calcSize=e=>{var t,r;const o=this.project,s=(null===(t=null==o?void 0:o.flags)||void 0===t?void 0:t.enableV2Preivew)?"v2":"v1",i=(null===(r=null==e?void 0:e.filter)||void 0===r?void 0:r.call(e,(e=>e.type===s)).sort(((e,t)=>t.zipSize-e.zipSize)))||[];this.previewData.subPkgs=i.map(((e,t)=>({key:t,path:e.root,size:q(e.zipSize)})));const a=i.reduce(((e,t)=>t.zipSize+e),0)||0;this.previewData.zipSize=q(a)},this.uploadApi=new B(e),this.progressData={},this.previewData={}}preview(e){return new Promise(((t,r)=>{this.previewPromise={resolve:t,reject:r},this.doPreview(e)}))}doPreview(e){this.progressData.previewIsLoading=!0;const t=this.project.projectAppId,r=Date.now(),o=async t=>{var o,s;const i=JSON.parse(t.result.extra_json);this.previewData.qrcodeUrl=await X(this.project,e.entry,i.qrcode,this.logger),this.showQrCode(this.previewData.qrcodeUrl),this.previewData.previewTotalTime=+((Date.now()-r)/1e3).toFixed(1),this.progressData.previewIsLoading=!1,this.compilerManager.killCompiler(K.preview),null===(o=this.taskSubscription)||void 0===o||o.unsubscribe(),this.taskSubscription=null,null===(s=this.previewPromise)||void 0===s||s.resolve({qrcodeUrl:this.previewData.qrcodeUrl}),this.previewPromise=null,this.logger.log("Preview Done!!!")},s=e=>{var t,r;this.compilerManager.killCompiler(K.preview),null===(t=this.taskSubscription)||void 0===t||t.unsubscribe(),this.taskSubscription=null,null===(r=this.previewPromise)||void 0===r||r.reject(e),this.previewPromise=null,this.logger.log("Preview Error:",e.toString())};this.taskSubscription=d.from(this.getCheckUploadAuthFn(this.uploadApi,"debug")).pipe(d.switchMap((e=>{let t=e.can_upload_ext_json,r=e.upload_app_id;if(!r)throw new Error("请检查是否该appid无权限");return d.from(this.compilerManager.compileAndZip({entryType:K.preview,can_upload_ext_json:t,upload_app_id:r}))})),d.tap((e=>{this.calcSize(e)})),d.switchMap((e=>{this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages...");const r=e.map(((e,r)=>this.uploadPkgZipOrSourcemap(this.uploadApi,{appId:t,zipPath:e.zipPath,type:e.type,root:e.root},r)));return d.forkJoin(r)})),d.switchMap((e=>(this.logger.log("Upload packages info..."),this.submitTask({uploadApi:this.uploadApi,uploadRes:e,appId:t,version:"debug"}))))).subscribe({next:e=>o(e),error:e=>s(e)})}showQrCode(e){f.generate(e,{small:!0})}}const te={code:"code",cli:"cli"};class re{constructor({core:e}){this.data={},this.core=e,this.extract()}extract(){if(this.core.scene===te.cli){if(this.jsonPath=s.join(E,"storage.json"),a.existsSync(this.jsonPath))try{this.data=a.readJSONSync(this.jsonPath)}catch(e){this.data={}}}else this.data={}}store(){this.core.scene===te.cli&&a.writeJSONSync(this.jsonPath,this.data)}get(e){return this.data[e]}set(e,t){this.data[e]=t,this.refresh()}refresh(){this.store()}}exports.Core=class{constructor(e){this.globalConfig={},this.appConfigMap={},this.projectMap={},this.compilerManagerMap={},this.scene=te.code;const{scene:r=te.code}=e;this.scene=r,this.logger=new t.Logger("[xhs-mp-cli]"),this.storage=new re({core:this}),this.globalConfig=this.storage.get("xhs-cli-global-config")||{},this.appConfigMap=this.storage.get("xhs-cli-app-config")||{},this.logger.debug("get initial config:",this.globalConfig,this.appConfigMap),globalThis.logger=this.logger,this.loginManager=new Z({core:this,storage:this.storage,logger:this.logger})}setGlobalConfig(e={}){this.globalConfig={...this.globalConfig||{},...e},this.storage.set("xhs-cli-global-config",e),this.logger.log("Set global config done")}getGlobalConfig(){return this.globalConfig||{}}setAppConfig(e={}){const{appId:t,config:r}=e;t?(this.appConfigMap[t]={...this.appConfigMap[t]||{},...r},this.storage.set("xhs-cli-app-config",this.appConfigMap),this.logger.log("Set app config done")):this.logger.error("没有传递 appid 参数")}getAppConfig(e){return this.appConfigMap[e]||{}}createOrGetProject(t){let r=t.projectPath;if(!r)throw new Error("没有配置projectPath");return s.isAbsolute(r)||(r=s.join(k.cwd(),r)),this.projectMap[r]||(this.projectMap[r]=new e.Project(t)),this.projectMap[r]}getCompilerManager(e,t){let r=e.projectPath;if(s.isAbsolute(r)||(r=s.join(k.cwd(),r)),!this.compilerManagerMap[r]){const o=this.createOrGetProject(e);this.compilerManagerMap[r]=new w.ProjectCompilerManager({...t,project:o,logger:this.logger})}return this.compilerManagerMap[r]}async login(e={}){e.verbose&&this.logger.setVerbose(!0);const{type:t="qrcode"}=e;await this.loginManager.login(t)}logout(e){this.loginManager.logout(e)}isTokenAuth(e){return!!this.getAppConfig(e).token}getTokenParams(e){const t=this.getAppConfig(e).token,r="xxxxxxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})),o=e+"#"+t+"#"+r+"#"+H("YYYYMMDDHHmm"),s=T(o);return this.logger.debug("cliToken",o,s),{cliToken:s,nonce:r,appId:e}}checkAppId(e){if(!this.appConfigMap[e])throw new Error(`找不到项目内appId(${e})对应的配置,请先确认appId是否保持一致`)}async preview(e){e.verbose&&this.logger.setVerbose(!0);const t=e.project||{},r=e.buildConfig||{},o=this.createOrGetProject(t);this.checkAppId(o.projectAppId),this.logger.log("Project:",o.projectPath),this.logger.debug("Preview options:",e);const s=this.appConfigMap[o.projectAppId];(null==s?void 0:s.token)?this.logger.debug("Auth by token"):(this.logger.debug("Auth by qrCode"),this.loginManager.isLogin||await this.login());const i=this.getCompilerManager(t,r),a=new ee({core:this,project:o,compilerManager:i,logger:this.logger});try{return await a.preview({entry:e.entry})}finally{i.killAll()}}async upload(e){const{project:t,buildConfig:r={},version:o,desc:s,progressCallback:i}=e;e.verbose&&this.logger.setVerbose(!0);const a=this.createOrGetProject(t);this.checkAppId(a.projectAppId),this.logger.log("ProjectPath:",a.projectPath),this.logger.debug("Upload options:",e);const n=this.appConfigMap[a.projectAppId];(null==n?void 0:n.token)?this.logger.debug("Auth by token"):(this.logger.debug("Auth by login"),this.loginManager.isLogin||await this.login());const p=this.getCompilerManager(t,r),c=new G({core:this,project:a,compilerManager:p,logger:this.logger});try{return await c.upload({userVersion:o,userDesc:s,progressCallback:i})}finally{p.killAll()}}};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xhs-mp-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.29",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"querystring": "^0.2.1",
|
|
30
30
|
"rxjs": "^7.8.1",
|
|
31
31
|
"tough-cookie": "^4.1.3",
|
|
32
|
-
"xhs-mp-compiler-cli": "2.0.
|
|
33
|
-
"xhs-mp-project": "2.0.
|
|
34
|
-
"xhs-mp-shared": "2.0.
|
|
32
|
+
"xhs-mp-compiler-cli": "2.0.29",
|
|
33
|
+
"xhs-mp-project": "2.0.29",
|
|
34
|
+
"xhs-mp-shared": "2.0.29"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@rollup/plugin-commonjs": "^25.0.7",
|