xhs-mp-core 1.1.4 → 1.2.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,7 @@ export declare class BaseApi extends EventEmitter {
20
20
  port: string;
21
21
  protocol: string;
22
22
  };
23
- request(opts: IRequestOpts): Promise<import("axios").AxiosResponse<any> | undefined>;
23
+ request(opts: IRequestOpts): Promise<import("axios").AxiosResponse<any>>;
24
24
  protected handleHttpStatus(res: any): any;
25
25
  protected handleStatusCode(res: any): any;
26
26
  protected handleCode(res: any): any;
@@ -46,10 +46,15 @@ export type IQueryTaskDetail = ILongTaskRoot<{
46
46
  };
47
47
  status: number;
48
48
  }>;
49
- export interface IUploadCheckVersionParams {
49
+ export interface IUploadCheckVersionParamsV1 {
50
50
  version: 'debug' | 'develop';
51
51
  }
52
- export interface IUploadPackageParams {
52
+ export interface IUploadCheckVersionParamsV2 extends IUploadCheckVersionParamsV1 {
53
+ appId: string;
54
+ cliToken: string;
55
+ nonce: string;
56
+ }
57
+ export interface IUploadPackageParamsV1 {
53
58
  appId: string;
54
59
  version: 'debug' | 'develop';
55
60
  fileUrl: string;
@@ -62,11 +67,26 @@ export interface IUploadPackageParams {
62
67
  [key: string]: string;
63
68
  };
64
69
  }
70
+ export interface IUploadPackageParamsV2 extends IUploadPackageParamsV1 {
71
+ cliToken: string;
72
+ nonce: string;
73
+ }
74
+ export interface IQueryTaskDetailV1 {
75
+ taskId: string;
76
+ }
77
+ export interface IQueryTaskDetailV2 extends IQueryTaskDetailV1 {
78
+ appId: string;
79
+ cliToken: string;
80
+ nonce: string;
81
+ }
65
82
  export declare class UploadApi extends BaseApi {
66
83
  project: Project;
67
84
  constructor(props: any);
68
- uploadCheckVersion({ version }: IUploadCheckVersionParams): Promise<any>;
85
+ checkUploadAuthV1({ version }: IUploadCheckVersionParamsV1): Promise<any>;
86
+ checkUploadAuthV2(opts: IUploadCheckVersionParamsV2): Promise<any>;
69
87
  getUploadToken: (params: TokenRequest) => Promise<TokenResponse>;
70
- createUploadTask(opts: IUploadPackageParams): Promise<any>;
71
- queryTaskDetail(taskId: string): Promise<any>;
88
+ createUploadTaskV1(opts: IUploadPackageParamsV1): Promise<any>;
89
+ createUploadTaskV2(opts: IUploadPackageParamsV2): Promise<any>;
90
+ queryTaskDetailV1(opts: IQueryTaskDetailV1): Promise<any>;
91
+ queryTaskDetailV2(opts: IQueryTaskDetailV2): Promise<any>;
72
92
  }
package/dist/core.d.ts CHANGED
@@ -6,19 +6,14 @@ export interface IGlobalConfig {
6
6
  proxy?: string;
7
7
  }
8
8
  export interface IAppConfig {
9
- appId: string;
10
- config: {
11
- [key: string]: any;
12
- };
9
+ token?: string;
10
+ [key: string]: any;
13
11
  }
14
12
  export interface IAppConfigMap {
15
13
  [appId: string]: IAppConfig;
16
14
  }
17
15
  export type ILoginConfig = IVerbose & {
18
- type?: 'qrcode' | 'token';
19
- data?: {
20
- token?: string;
21
- };
16
+ type?: 'qrcode';
22
17
  };
23
18
  export type ILogoutConfig = IVerbose & {};
24
19
  export interface ILibFeatures {
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- "use strict";var e=require("xhs-mp-compiler-cli"),t=require("xhs-mp-project"),r=require("xhs-mp-utils"),s=require("events"),o=require("axios"),i=require("path"),a=require("os"),n=require("fs-extra"),l=require("fs"),c=require("rxjs"),p=require("lodash"),h=require("rxjs/operators"),u=require("qrcode-terminal"),d=require("jimp"),g=require("jsqr");function m(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var S=m(i),f=m(l);const v=()=>({isSit:"false"===process.env.XHS_IS_PROD,isProd:"true"===process.env.XHS_IS_PROD}),w=require("process").env.XHS_BUSINESS_SIT_HOST||"https://business.sit.xiaohongshu.com",y=require("process").env.XHS_CUSTOMER_SIT_HOST||"https://customer.sit.xiaohongshu.com",C={BUSINESS_HOST:v().isSit?w:"https://business.xiaohongshu.com",CUSTOMER_HOST:v().isSit?y:"https://customer.xiaohongshu.com",CUSTOMER_SERVICE_ID:v().isSit?y.replace(/https?:\/\/customer/,"file://miniapp-open"):"file://miniapp-open.xiaohongshu.com"},x={generateQrCode:`${C.CUSTOMER_HOST}/api/cas/generateQrCode`,queryQrCodeStatus:`${C.CUSTOMER_HOST}/api/cas/queryQrCodeStatus`,session:`${C.BUSINESS_HOST}/api/eros/mp/red/code/session`,getUserInfo:`${C.BUSINESS_HOST}/api/eros/mp/red/code/user/info`};require("crypto"),require("net");const b=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 k(e){return e.replace(/\\/g,"/")}const _=k(i.join(a.homedir(),".xhs-mp-cli"));n.ensureDirSync(_);const P=k(i.join(_,"xhs-storage"));n.ensureDirSync(P);const I=require("tough-cookie");var j=new class{constructor(){this.cookiePath=i.join(P,"cookie.json");const e=this.getSerializeData();Object.keys(e).length?this.cookieJar=I.CookieJar.deserializeSync(e):this.cookieJar=new I.CookieJar}getSerializeData(){let e={};return n.existsSync(this.cookiePath)&&(e=n.readJSONSync(this.cookiePath)),e}save(){const e=this.cookieJar.serializeSync();n.writeJSONSync(this.cookiePath,e)}clear(){n.removeSync(this.cookiePath)}set(e){const t=e.headers["set-cookie"]||[],r=e.config.url;t.forEach((e=>{const t=I.Cookie.parse(e);if(t.domain){const e=new I.Cookie(t);this.cookieJar.setCookieSync(e,r)}})),this.save()}get(e){return this.cookieJar.getCookieStringSync(e)}};let q;o.defaults.baseURL=C.BUSINESS_HOST,o.interceptors.request.use((e=>{const{url:t,data:r,baseURL:s=""}=e;let i=o.getUri(e);if(/^https?:/.test(i))try{const e=new URL(t);i=i.replace(e.origin,"")}catch(e){i=t}const a=j.get(t);return e.headers={...e.headers,Cookie:a},e.headers["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) @xhs/mp-ide/2.0.0 Chrome/116.0.5845.228 Electron/26.4.0 Safari/537.36 discover/2.0.0 xhsminiapp/latest",e})),o.interceptors.response.use((e=>(j.set(e),e))),o.interceptors.response.use((e=>{var t;const{config:r,data:s}=e;if((null===(t=r.url)||void 0===t?void 0:t.startsWith(`${C.BUSINESS_HOST}/api/eros/mp/red`))&&!s.success)throw new Error(`${s.msg}`);return e}),(async e=>{const{response:t={}}=e;return 401===t.status&&t.data&&-240309===t.data.code?(null==q||q.logout({from:"axios"}),Promise.reject(new Error("登陆失效,请重新登陆!"))):t.data&&t.data.msg&&401===t.status?(null==q||q.logout({from:"axios"}),Promise.reject(new Error("未登录,请先登录!"))):Promise.reject(e)}));class E extends s.EventEmitter{constructor(e){super(),this.core=e.core}get axios(){return e=this.core,q=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}}return!1}async request(e){const{method:t,url:r,data:s,config:o={}}=e;try{return await this.axios[t](r,s,{...o,proxy:this.getProxyConfig()})}catch(e){console.error(e)}}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 M=require("path"),U=require("fs-extra"),T=e=>{if(!U.existsSync(e))return"";let t="";try{t=JSON.stringify(U.readJSONSync(e))}catch(t){console.warn(`readJson error: ${e}`)}return t};class O extends E{constructor(e){super(e),this.getUploadToken=async e=>{const t=await this.request({method:"get",url:`${C.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 uploadCheckVersion({version:e}){const t=this.project,r=t.entryJsonPath,s=M.resolve(t.extJsonPath),o=T(r),i=T(s),a=t.projectAppId,n=`${C.BUSINESS_HOST}/api/eros/mp/red/code/${a}/validate/version/${e}`,l=await this.request({method:"post",url:n,data:{app_json:o,ext_json:i}});return this.handleCode(this.handleHttpStatus(l))}async createUploadTask(e){const{version:t,fileUrl:r,userVersion:s,userDesc:o,appId:i,packageMap:a,packageMapV2:n}=e,l=`${C.BUSINESS_HOST}/api/eros/mp/red/code/${i}/upload/version/${t}`,c=await this.request({method:"post",url:l,data:{file_url:r,user_version:s,user_desc:o,package_map:a,package_map_v2:n,cloud_type:4}});return this.handleCode(this.handleHttpStatus(c))}async queryTaskDetail(e){const t=await this.request({method:"get",url:`${C.BUSINESS_HOST}/api/eros/mp/red/code/task/detail`,data:{params:{task_id:e}}});return this.handleCode(this.handleHttpStatus(t))}}class D extends s{constructor(e){super(),this.core=e.core,this.project=e.project,this.compiler=e.compiler,this.logger=e.logger}}const L=(e,{zipPath:t,type:s,root:o},i,a)=>{const n=new r.Uploader({bizName:"fe",scene:"fe-platform",getToken:e.getUploadToken});return new c.Observable((e=>{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`,i=f.readFileSync(S.resolve(t)),l=f.statSync(S.resolve(t));function c(){return new Promise(((e,c)=>{setTimeout((()=>{n.post({Body:i,fileInfo:{name:r,type:"application/octet-stream",size:l.size},FilePath:S.resolve(t)}).then((r=>{var i;return 0!==r.code?c(new Error(`${t}上传失败:${r.msg}`)):(null===(i=null==r?void 0:r.data)||void 0===i?void 0:i.fileId)?(e({fileId:r.data.fileId,type:s,root:o}),void(null==a||a())):c(new Error(`${t}上传失败`))}))}),500)}))}c().catch(c).catch(c).catch(c).catch(c).then((t=>{e.next(t),e.complete()})).catch((t=>{e.error(t)}))}),500)}))},$=(e,t)=>e.reduce(((e,r)=>{let s={};return r.type===t&&(s={[r.root]:r.fileId}),{...e,...s}}),{}),z=({uploadApi:e,uploadRes:t,appId:r,version:s,userDesc:o,userVersion:i})=>{const a=t.filter((e=>"v0"===e.type))[0].fileId,n=$(t,"v1"),l=$(t,"v2");return c.from(e.createUploadTask({version:s,fileUrl:a,appId:r,packageMap:n,packageMapV2:p.isEmpty(l)?void 0:l,userDesc:o,userVersion:i})).pipe(c.switchMap((t=>{const{task_id:r}=t;return c.interval(1500).pipe(c.switchMap((()=>((e,t)=>c.from(e.queryTaskDetail(t)).pipe(c.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}))))(e,r))),c.first((e=>3===e.status)))})))};class A extends D{constructor(t){super(t),this.doUpload=t=>{const{progressCallback:r,userVersion:s,userDesc:o}=t;if(!(null==s?void 0:s.trim()))throw new Error("请填写上传版本号");if(!(null==o?void 0:o.trim()))throw new Error("请填写版本描述");const i=()=>{var t,r;this.compiler.kill(e.COMPILE_ENTRY.upload),null===(t=this.taskSubscription)||void 0===t||t.unsubscribe(),this.taskSubscription=null,null===(r=this.uploadPromise)||void 0===r||r.resolve(null),this.uploadPromise=null,this.logger.log("Upload Done!!!")},a=t=>{var s,o;null==r||r(-1),null===(s=this.taskSubscription)||void 0===s||s.unsubscribe(),this.taskSubscription=null,this.compiler.kill(e.COMPILE_ENTRY.upload),this.logger.log("Upload Error:",t.toString()),null===(o=this.uploadPromise)||void 0===o||o.reject(t),this.uploadPromise=null};try{const t=this.project.projectAppId;this.logger.log("Check appid auth..."),this.taskSubscription=c.from(this.uploadApi.uploadCheckVersion({version:"develop"})).pipe(c.switchMap((t=>{const{can_upload:o,can_upload_ext_json:i,upload_app_id:a,show_msg:n}=t;if(!o)throw new Error(n);if(!a)throw new Error("请检查是否该appid无权限");return null==r||r(5),c.from(this.compiler.compileAndZip({entryType:e.COMPILE_ENTRY.upload,can_upload_ext_json:i,upload_app_id:a,pkgInfo:{version:s}}))})),c.switchMap((e=>{null==r||r(30),this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages to cos...");const t=e.map(((t,s)=>L(this.uploadApi,{zipPath:t.zipPath,type:t.type,root:t.root},0,(()=>{null==r||r(30+45/e.length*(s+1))}))));return c.forkJoin(t)})),c.switchMap((e=>(null==r||r(80),this.logger.log("Upload packages info..."),z({uploadApi:this.uploadApi,uploadRes:e,appId:t,version:"develop",userVersion:s,userDesc:o}))))).subscribe({next:e=>{null==r||r(100),i()},error:e=>{a(e)}})}catch(e){a(e)}},this.uploadApi=new O(t)}upload(e){return new Promise(((t,r)=>{this.uploadPromise={resolve:t,reject:r},this.doUpload(e)}))}}class H extends E{async generateQrCode(){const e=await this.request({method:"post",url:x.generateQrCode,data:{subsystem:"business"}});return this.handleStatusCode(this.handleHttpStatus(e))}async queryQrCodeStatus(e){const t=await this.request({method:"get",url:x.queryQrCodeStatus,data:{params:{qrId:e,service:C.CUSTOMER_SERVICE_ID}}});return this.handleStatusCode(this.handleHttpStatus(t))}async login(e){const t=await this.request({method:"post",url:x.session,data:{ticket:e,clientId:C.CUSTOMER_SERVICE_ID}});return this.handleHttpStatus(t).data}async fetchUserInfo(){const e=await this.request({method:"get",url:x.getUserInfo});return this.handleCode(this.handleHttpStatus(e))}}var N=new class{constructor(){if(this.data={},this.jsonPath=i.join(P,"storage.json"),n.existsSync(this.jsonPath))try{this.data=n.readJSONSync(this.jsonPath)}catch(e){this.data={}}}get(e){return this.data[e]}set(e,t){this.data[e]=t,this.refresh()}refresh(){n.writeJSONSync(this.jsonPath,this.data)}};class R{get isLogin(){return this._isLogin}set isLogin(e){this._isLogin=e}get userInfo(){return this._userInfo}set userInfo(e){this._userInfo=e,N.set("userInfo",e)}constructor(e){var t;this.qrCodeStatusData={},this.startPollingSub=null,this.loginPromise={},this.transformUserInfo=e=>{const{nick:t,avatar:r,desc:s,gender:o}=(i=e,["nick","avatar","desc","gender"].reduce(((e,t)=>({...e,[t]:i[t]})),{}));var i;return{nickName:t,avatar:r,userId:"",desc:s,gender:o}},this.queryQrCodeStatus=e=>c.from(this.userApi.queryQrCodeStatus(e)),this.doLogin=async e=>{const{resolve:t,reject:r}=this.loginPromise;this.loginPromise=null;try{const s=await this.userApi.login(e);if(!s.success)return void r(new Error(s.msg));const o=await this.userApi.fetchUserInfo(),i=this.transformUserInfo(o);i.userInfoData=o,t(i)}catch(e){return void r(new Error(e.message))}},this.startPolling=()=>(this.qrCodeStatusData.isLoading=!0,this.qrCodeStatusData.expired=!1,c.from(c.defer((()=>this.userApi.generateQrCode()))).pipe(h.tap((e=>{this.qrUrl=e.qrUrl,this.qrCodeStatusData.isLoading=!1,this.showQrCode(),setTimeout((()=>{this.qrCodeStatusData.expired=!0,this.stopPolling()}),6e4)})),h.exhaustMap((({qrUrl:e,qrId:t})=>c.interval(2e3).pipe(h.switchMap((()=>this.queryQrCodeStatus(t))),h.tap((e=>{if(4===e.status)throw new Error("retry login");1===e.status&&(this.stopPolling(),this.doLogin(e.ticket))}))))),h.takeWhile((e=>1!==e.status)),h.retry(5))),this.stopPolling=()=>{this.startPollingSub&&(this.startPollingSub.unsubscribe(),this.startPollingSub=null)},this.logger=e.logger,this.userApi=new H(e),this.qrCodeStatusData={isLoading:!1,expired:!1},this._userInfo=N.get("userInfo")||{},this.isLogin=!!(null===(t=this.userInfo)||void 0===t?void 0:t.nickName)}showQrCode(){u.generate(this.qrUrl,{small:!0})}async login(e,t){if(this.isLogin)this.logger.log("Had Login!!!");else{this.isLogin=!1,this.logger.log("Login...");try{let r;r="qrcode"===e?await this.loginByQrcode():await this.loginByToken(t),this.isLogin=!0,this.userInfo=r,this.logger.log("Login success")}catch(e){throw this.logger.log("Login fail:",e.message),this.isLogin=!0,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)}}))}async loginByToken(e){}logout(e){"axios"!==e.from&&this.logger.log("Logout..."),this.isLogin=!1,this.userInfo={},j.clear(),"axios"!==e.from&&this.logger.log("Logout Success!!!")}}const B=async(e,t={},r,s)=>{let o=e.getCompileEntryPage();o={...o,...t};const{path:i,query:a,launchMode:n}=o;try{let e=await(async e=>{const t=Buffer.from(e.replace(/^data:image\/[a-z]+;base64,/,""),"base64"),r=await d.read(t),s={data:new Uint8ClampedArray(r.bitmap.data),width:r.bitmap.width,height:r.bitmap.height},o=g(s.data,s.width,s.height);if(!o)throw new Error("QR code not found in the image.");return o.data})(r);return i&&(e=e.replace("_develop",`_develop${i.startsWith("/")?"":"/"}${i}`)),a&&(e+=`&${a}`),"halfPageNativeFunctionalized"===n&&(e+="&runtime_mode=2"),e}catch(e){s.error("二维码解码失败:",e)}};class J extends D{constructor(e){super(e),this.progressData={},this.previewData={},this.calcSize=e=>{var t,r;const s=this.project,o=(null===(t=null==s?void 0:s.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===o)).sort(((e,t)=>t.zipSize-e.zipSize)))||[];this.previewData.subPkgs=i.map(((e,t)=>({key:t,path:e.root,size:b(e.zipSize)})));const a=i.reduce(((e,t)=>t.zipSize+e),0)||0;this.previewData.zipSize=b(a)},this.uploadApi=new O(e),this.progressData={},this.previewData={}}preview(e){return new Promise(((t,r)=>{this.previewPromise={resolve:t,reject:r},this.doPreview(e)}))}doPreview(t){this.progressData.previewIsLoading=!0;const r=this.project.projectAppId,s=Date.now(),o=async r=>{var o,i;const a=JSON.parse(r.result.extra_json);this.previewData.qrcodeUrl=await B(this.project,t.entry,a.qrcode,this.logger),this.showQrCode(this.previewData.qrcodeUrl),this.previewData.previewTotalTime=+((Date.now()-s)/1e3).toFixed(1),this.progressData.previewIsLoading=!1,this.compiler.kill(e.COMPILE_ENTRY.preview),null===(o=this.taskSubscription)||void 0===o||o.unsubscribe(),this.taskSubscription=null,null===(i=this.previewPromise)||void 0===i||i.resolve({qrcodeUrl:this.previewData.qrcodeUrl}),this.previewPromise=null,this.logger.log("Preview Done!!!")},i=t=>{var r,s;this.compiler.kill(e.COMPILE_ENTRY.preview),null===(r=this.taskSubscription)||void 0===r||r.unsubscribe(),this.taskSubscription=null,null===(s=this.previewPromise)||void 0===s||s.reject(t),this.previewPromise=null,this.logger.log("Preview Error:",t.toString())};this.logger.log("Check appid auth..."),this.taskSubscription=c.from(c.defer((()=>this.uploadApi.uploadCheckVersion({version:"debug"})))).pipe(c.switchMap((t=>{const{can_upload_ext_json:r,upload_app_id:s}=t;if(!s)throw new Error("请检查是否该appid无权限");return c.from(this.compiler.compileAndZip({entryType:e.COMPILE_ENTRY.preview,can_upload_ext_json:r,upload_app_id:s}))})),c.tap((e=>{this.calcSize(e)})),c.switchMap((e=>{this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages to cos...");const t=e.map(((e,t)=>L(this.uploadApi,{zipPath:e.zipPath,type:e.type,root:e.root})));return c.forkJoin(t)})),c.switchMap((e=>(this.logger.log("Upload packages info..."),z({uploadApi:this.uploadApi,uploadRes:e,appId:r,version:"debug"}))))).subscribe({next:e=>o(e),error:e=>i(e)})}showQrCode(e){u.generate(e,{small:!0})}}exports.Core=class{constructor(){this.globalConfig={},this.appConfigMap={},this.currentAppConfig={},this.projectMap={},this.compilerMap={},this.globalConfig=N.get("globalConfig")||{},this.logger=new r.Logger("[xhs-mp-cli]"),globalThis.logger=this.logger,this.loginManager=new R({core:this,logger:this.logger})}setGlobalConfig(e={}){this.logger.log("Set global config..."),this.globalConfig={...this.globalConfig||{},...e},N.set("globalConfig",e),this.logger.log("Set global config done")}getGlobalConfig(){return this.globalConfig||{}}setAppConfig(e={}){const{appId:t,config:r}=e;this.appConfigMap[t]={...this.appConfigMap[t]||{},...r},this.currentAppConfig=e}getAppConfig(e){return this.appConfigMap[e]||{}}getProject(e){const{projectPath:r}=e;if(!r)throw new Error("没有配置projectPath");return this.projectMap[r]||(this.projectMap[r]=new t.Project(e)),this.projectMap[r]}getCompiler(t,r){const{projectPath:s}=t;if(!this.compilerMap[s]){const o=this.getProject(t);this.compilerMap[s]=new e.Compiler({...r,project:o,logger:this.logger})}return this.compilerMap[s]}async login(e={}){e.verbose&&this.logger.setVerbose(!0);const{type:t="qrcode",data:r}=e;await this.loginManager.login(t,{...this.currentAppConfig||{},...r})}logout(e){this.loginManager.logout(e)}async preview(e){e.verbose&&this.logger.setVerbose(!0),this.loginManager.isLogin||await this.login({});const t=e.project||{},r=e.buildConfig||{},s=this.getProject(t),o=this.getCompiler(t,r),i=new J({core:this,project:s,compiler:o,logger:this.logger});return await i.preview({entry:e.entry})}async upload(e){e.verbose&&this.logger.setVerbose(!0),this.loginManager.isLogin||await this.login();const{project:t,buildConfig:r={},version:s,desc:o,progressCallback:i}=e,a=this.getProject(t),n=this.getCompiler(t,r),l=new A({core:this,project:a,compiler:n,logger:this.logger});return await l.upload({userVersion:s,userDesc:o,progressCallback:i})}};
1
+ "use strict";var e=require("xhs-mp-compiler-cli"),t=require("xhs-mp-project"),s=require("xhs-mp-utils"),r=require("events"),o=require("axios"),i=require("path"),a=require("os"),n=require("fs-extra"),l=require("fs"),p=require("rxjs"),c=require("lodash"),h=require("dayjs"),u=require("rxjs/operators"),d=require("qrcode-terminal"),g=require("jimp"),m=require("jsqr");function f(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var v=f(i),S=f(l);const k=()=>({isSit:"false"===process.env.XHS_IS_PROD,isProd:"true"===process.env.XHS_IS_PROD}),w=require("process").env.XHS_BUSINESS_SIT_HOST||"http://business-cli.sl.beta.xiaohongshu.com",x=require("process").env.XHS_CUSTOMER_SIT_HOST||"https://customer.sit.xiaohongshu.com",y={BUSINESS_HOST:k().isSit?w:"https://business.xiaohongshu.com",CUSTOMER_HOST:k().isSit?x:"https://customer.xiaohongshu.com",CUSTOMER_SERVICE_ID:k().isSit?x.replace(/https?:\/\/customer/,"file://miniapp-open"):"file://miniapp-open.xiaohongshu.com"},C={generateQrCode:`${y.CUSTOMER_HOST}/api/cas/generateQrCode`,queryQrCodeStatus:`${y.CUSTOMER_HOST}/api/cas/queryQrCodeStatus`,session:`${y.BUSINESS_HOST}/api/eros/mp/red/code/session`,getUserInfo:`${y.BUSINESS_HOST}/api/eros/mp/red/code/user/info`},_=require("crypto");require("net");const b=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 I(e){return e.replace(/\\/g,"/")}const P=I(i.join(a.homedir(),".xhs-mp-cli"));n.ensureDirSync(P);const T=I(i.join(P,"xhs-storage"));n.ensureDirSync(T);const j=require("tough-cookie");var q=new class{constructor(){this.cookiePath=i.join(T,"cookie.json");const e=this.getSerializeData();Object.keys(e).length?this.cookieJar=j.CookieJar.deserializeSync(e):this.cookieJar=new j.CookieJar}getSerializeData(){let e={};return n.existsSync(this.cookiePath)&&(e=n.readJSONSync(this.cookiePath)),e}save(){const e=this.cookieJar.serializeSync();n.writeJSONSync(this.cookiePath,e)}clear(){n.removeSync(this.cookiePath)}set(e){const t=e.headers["set-cookie"]||[],s=e.config.url;t.forEach((e=>{const t=j.Cookie.parse(e);if(t.domain){const e=new j.Cookie(t);this.cookieJar.setCookieSync(e,s)}})),this.save()}get(e){return this.cookieJar.getCookieStringSync(e)}};let E;o.defaults.baseURL=y.BUSINESS_HOST,o.interceptors.request.use((e=>{const{url:t,data:s,baseURL:r=""}=e;let i=o.getUri(e);if(/^https?:/.test(i))try{const e=new URL(t);i=i.replace(e.origin,"")}catch(e){i=t}const a=q.get(t);return e.headers={...e.headers,Cookie:a},e.headers["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) @xhs/mp-ide/2.0.0 Chrome/116.0.5845.228 Electron/26.4.0 Safari/537.36 discover/2.0.0 xhsminiapp/latest",e})),o.interceptors.response.use((e=>(q.set(e),e))),o.interceptors.response.use((e=>{var t;const{config:s,data:r}=e;if((null===(t=s.url)||void 0===t?void 0:t.startsWith(`${y.BUSINESS_HOST}/api/eros/mp/red`))&&!r.success)throw new Error(`${r.msg}`);return e}),(async e=>{const{response:t={}}=e;if(401===t.status){if(t.data&&-240309===t.data.code)return null==E||E.logout({from:"axios"}),Promise.reject(new Error("登陆失效,请重新登陆或采用 token 免密登陆:",t.data.msg));if(t.data&&t.data.msg)return null==E||E.logout({from:"axios"}),Promise.reject(new Error(`未登录,请先登录或采用 token 免密登陆。code:${t.data.code},msg: ${t.data.msg}`))}return Promise.reject(e)}));class U extends r.EventEmitter{constructor(e){super(),this.core=e.core}get axios(){return e=this.core,E=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}}return!1}async request(e){const{method:t,url:s,data:r,config:o={}}=e;return await this.axios[t](s,r,{...o,proxy:this.getProxyConfig()})}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 M=require("path"),D=require("fs-extra"),O=e=>{if(!D.existsSync(e))return"";let t="";try{t=JSON.stringify(D.readJSONSync(e))}catch(t){console.warn(`readJson error: ${e}`)}return t};class A extends U{constructor(e){super(e),this.getUploadToken=async e=>{const t=await this.request({method:"get",url:`${y.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 checkUploadAuthV1({version:e}){const t=this.project,s=t.entryJsonPath,r=M.resolve(t.extJsonPath),o=O(s),i=O(r),a=t.projectAppId,n=`${y.BUSINESS_HOST}/api/eros/mp/red/code/${a}/validate/version/${e}`;console.log("requestPath",n,o,i);const l=await this.request({method:"post",url:n,data:{app_json:o,ext_json:i}});return this.handleCode(this.handleHttpStatus(l))}async checkUploadAuthV2(e){const{version:t,appId:s,cliToken:r,nonce:o}=e,i=this.project,a=i.entryJsonPath,n=M.resolve(i.extJsonPath),l=O(a),p=O(n),c=`${y.BUSINESS_HOST}/api/eros/mp/red/code/v2/validate/version?app_id=${s}&cli_token=${r}&nonce=${o}&version=${t}`;console.log("requestPath",c,l,p);const h=await this.request({method:"post",url:c,data:{app_json:l,ext_json:p}});return this.handleCode(this.handleHttpStatus(h))}async createUploadTaskV1(e){const{version:t,fileUrl:s,userVersion:r,userDesc:o,appId:i,packageMap:a,packageMapV2:n}=e,l=`${y.BUSINESS_HOST}/api/eros/mp/red/code/${i}/upload/version/${t}`,p=await this.request({method:"post",url:l,data:{file_url:s,user_version:r,user_desc:o,package_map:a,package_map_v2:n,cloud_type:4}});return this.handleCode(this.handleHttpStatus(p))}async createUploadTaskV2(e){const{version:t,fileUrl:s,userVersion:r,userDesc:o,appId:i,packageMap:a,packageMapV2:n,cliToken:l,nonce:p}=e,c=`${y.BUSINESS_HOST}/api/eros/mp/red/code/v2/upload/version?app_id=${i}&cli_token=${l}&nonce=${p}&version=${t}`,h=await this.request({method:"post",url:c,data:{file_url:s,user_version:r,user_desc:o,package_map:a,package_map_v2:n,cloud_type:4}});return this.handleCode(this.handleHttpStatus(h))}async queryTaskDetailV1(e){const{taskId:t}=e,s=await this.request({method:"get",url:`${y.BUSINESS_HOST}/api/eros/mp/red/code/task/detail`,data:{params:{task_id:t}}});return this.handleCode(this.handleHttpStatus(s))}async queryTaskDetailV2(e){const{taskId:t,appId:s,cliToken:r,nonce:o}=e,i=`${y.BUSINESS_HOST}/api/eros/mp/red/code/v2/task/detail`,a=await this.request({method:"get",url:i,data:{params:{task_id:t,app_id:s,cli_token:r,nonce:o}}});return this.handleCode(this.handleHttpStatus(a))}}const $=(e,t)=>e.reduce(((e,s)=>{let r={};return s.type===t&&(r={[s.root]:s.fileId}),{...e,...r}}),{});class H extends r{constructor(e){super(),this.uploadFile=(e,t,r,o)=>{const{zipPath:i,type:a,root:n}=t,{appId:l,cliToken:c,nonce:h}=this.getTokenParams(),u=new s.Uploader({bizName:"fe",scene:"fe-platform",getToken:t=>e.getUploadToken({...t,app_id:l,nonce:h,cli_token:c})});return new p.Observable((e=>{setTimeout((()=>{const t=`${"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`,s=S.readFileSync(v.resolve(i)),r=S.statSync(v.resolve(i));function l(){return new Promise(((e,l)=>{setTimeout((()=>{u.post({Body:s,fileInfo:{name:t,type:"application/octet-stream",size:r.size},FilePath:v.resolve(i)}).then((t=>{var s;return 0!==t.code?l(new Error(`${i}上传失败:${t.msg}`)):(null===(s=null==t?void 0:t.data)||void 0===s?void 0:s.fileId)?(e({fileId:t.data.fileId,type:a,root:n}),void(null==o||o())):l(new Error(`${i}上传失败`))}))}),500)}))}l().catch(l).catch(l).catch(l).catch(l).then((t=>{e.next(t),e.complete()})).catch((t=>{e.error(t)}))}),500)}))},this.submitTask=e=>this.isTokenAuth()?this.submitTaskV2(e):this.submitTaskV1(e),this.submitTaskV1=e=>{const{uploadApi:t,uploadRes:s,appId:r,version:o,userDesc:i,userVersion:a}=e,n=s.filter((e=>"v0"===e.type))[0].fileId,l=$(s,"v1"),h=$(s,"v2");return p.from(t.createUploadTaskV1({version:o,fileUrl:n,appId:r,packageMap:l,packageMapV2:c.isEmpty(h)?void 0:h,userDesc:i,userVersion:a})).pipe(p.switchMap((e=>{const{task_id:s}=e;return p.interval(1500).pipe(p.switchMap((()=>p.from(t.queryTaskDetailV1({taskId:s})).pipe(p.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}))))),p.first((e=>3===e.status)))})))},this.submitTaskV2=e=>{const{uploadApi:t,uploadRes:s,version:r,userDesc:o,userVersion:i}=e,a=s.filter((e=>"v0"===e.type))[0].fileId,{appId:n,cliToken:l,nonce:h}=this.getTokenParams(),u=$(s,"v1"),d=$(s,"v2");return p.from(t.createUploadTaskV2({version:r,fileUrl:a,appId:n,packageMap:u,packageMapV2:c.isEmpty(d)?void 0:d,userDesc:o,userVersion:i,cliToken:l,nonce:h})).pipe(p.switchMap((e=>{const{task_id:s}=e;return p.interval(1500).pipe(p.switchMap((()=>p.from(t.queryTaskDetailV2({taskId:s,appId:n,cliToken:l,nonce:h})).pipe(p.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}))))),p.first((e=>3===e.status)))})))},this.core=e.core,this.project=e.project,this.compiler=e.compiler,this.logger=e.logger}isTokenAuth(){const e=this.project.projectAppId;return!!this.core.getAppConfig(e).token}getTokenParams(){const e=this.project.projectAppId,t=this.core.getAppConfig(e).token,s="xxxxxxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})),r=e+"#"+t+"#"+s+"#"+h().format("YYYYMMDDHHmm"),o=function(e){const t=_.createHash("md5");return t.update(e),t.digest("hex")}(r);return console.log("cliToken",r,o),{cliToken:o,nonce:s,appId:e}}getCheckUploadAuthFn(e,t){let s;const r=this.isTokenAuth();if(this.logger.log("Check appid auth...",r),r){const{appId:r,cliToken:o,nonce:i}=this.getTokenParams();s=e.checkUploadAuthV2({version:t,appId:r,cliToken:o,nonce:i})}else s=e.checkUploadAuthV1({version:t});return s}}class L extends H{constructor(t){super(t),this.doUpload=t=>{const{progressCallback:s,userVersion:r,userDesc:o}=t;if(!(null==r?void 0:r.trim()))throw new Error("请填写上传版本号");if(!(null==o?void 0:o.trim()))throw new Error("请填写版本描述");const i=()=>{var t,s;this.compiler.kill(e.COMPILE_ENTRY.upload),null===(t=this.taskSubscription)||void 0===t||t.unsubscribe(),this.taskSubscription=null,null===(s=this.uploadPromise)||void 0===s||s.resolve(null),this.uploadPromise=null,this.logger.log("Upload Done!!!")},a=t=>{var r,o;null==s||s(-1),null===(r=this.taskSubscription)||void 0===r||r.unsubscribe(),this.taskSubscription=null,this.compiler.kill(e.COMPILE_ENTRY.upload),this.logger.log("Upload Error:",t.toString()),null===(o=this.uploadPromise)||void 0===o||o.reject(t),this.uploadPromise=null};try{const t=this.project.projectAppId;this.taskSubscription=p.from(this.getCheckUploadAuthFn(this.uploadApi,"develop")).pipe(p.switchMap((t=>{let o=t.can_upload,i=t.can_upload_ext_json,a=t.upload_app_id;if(!o)throw new Error(t.show_msg);if(!a)throw new Error("请检查是否该appid无权限");return null==s||s(5),p.from(this.compiler.compileAndZip({entryType:e.COMPILE_ENTRY.upload,can_upload_ext_json:i,upload_app_id:a,pkgInfo:{version:r}}))})),p.switchMap((e=>{null==s||s(30),this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages to cos...");const t=e.map(((t,r)=>this.uploadFile(this.uploadApi,{zipPath:t.zipPath,type:t.type,root:t.root},r,(()=>{null==s||s(30+45/e.length*(r+1))}))));return p.forkJoin(t)})),p.switchMap((e=>{null==s||s(80),this.logger.log("Upload packages info...");const i={uploadApi:this.uploadApi,uploadRes:e,appId:t,version:"develop",userVersion:r,userDesc:o};return this.submitTask(i)}))).subscribe({next:e=>{null==s||s(100),i()},error:e=>{a(e)}})}catch(e){a(e)}},this.uploadApi=new A(t)}upload(e){return new Promise(((t,s)=>{this.uploadPromise={resolve:t,reject:s},this.doUpload(e)}))}}class V extends U{async generateQrCode(){const e=await this.request({method:"post",url:C.generateQrCode,data:{subsystem:"business"}});return this.handleStatusCode(this.handleHttpStatus(e))}async queryQrCodeStatus(e){const t=await this.request({method:"get",url:C.queryQrCodeStatus,data:{params:{qrId:e,service:y.CUSTOMER_SERVICE_ID}}});return this.handleStatusCode(this.handleHttpStatus(t))}async login(e){const t=await this.request({method:"post",url:C.session,data:{ticket:e,clientId:y.CUSTOMER_SERVICE_ID}});return this.handleHttpStatus(t).data}async fetchUserInfo(){const e=await this.request({method:"get",url:C.getUserInfo});return this.handleCode(this.handleHttpStatus(e))}}var z=new class{constructor(){if(this.data={},this.jsonPath=i.join(T,"storage.json"),n.existsSync(this.jsonPath))try{this.data=n.readJSONSync(this.jsonPath)}catch(e){this.data={}}}get(e){return this.data[e]}set(e,t){this.data[e]=t,this.refresh()}refresh(){n.writeJSONSync(this.jsonPath,this.data)}};class N{get isLogin(){return this._isLogin}set isLogin(e){this._isLogin=e}get userInfo(){return this._userInfo}set userInfo(e){this._userInfo=e,z.set("xhs-cli-userInfo",e)}constructor(e){var t;this.qrCodeStatusData={},this.startPollingSub=null,this.loginPromise={},this.transformUserInfo=e=>{const{nick:t,avatar:s,desc:r,gender:o}=(i=e,["nick","avatar","desc","gender"].reduce(((e,t)=>({...e,[t]:i[t]})),{}));var i;return{nickName:t,avatar:s,userId:"",desc:r,gender:o}},this.queryQrCodeStatus=e=>p.from(this.userApi.queryQrCodeStatus(e)),this.doLogin=async e=>{const{resolve:t,reject:s}=this.loginPromise;this.loginPromise=null;try{const r=await this.userApi.login(e);if(!r.success)return void s(new Error(r.msg));const o=await this.userApi.fetchUserInfo(),i=this.transformUserInfo(o);i.userInfoData=o,t(i)}catch(e){return void s(new Error(e.message))}},this.startPolling=()=>(this.qrCodeStatusData.isLoading=!0,this.qrCodeStatusData.expired=!1,p.from(p.defer((()=>this.userApi.generateQrCode()))).pipe(u.tap((e=>{this.qrUrl=e.qrUrl,this.qrCodeStatusData.isLoading=!1,this.showQrCode(),setTimeout((()=>{this.qrCodeStatusData.expired=!0,this.stopPolling()}),6e4)})),u.exhaustMap((({qrUrl:e,qrId:t})=>p.interval(2e3).pipe(u.switchMap((()=>this.queryQrCodeStatus(t))),u.tap((e=>{if(4===e.status)throw new Error("retry login");1===e.status&&(this.stopPolling(),this.doLogin(e.ticket))}))))),u.takeWhile((e=>1!==e.status)),u.retry(5))),this.stopPolling=()=>{this.startPollingSub&&(this.startPollingSub.unsubscribe(),this.startPollingSub=null)},this.logger=e.logger,this.userApi=new V(e),this.qrCodeStatusData={isLoading:!1,expired:!1},this._userInfo=z.get("userInfo")||z.get("xhs-cli-userInfo")||{},this.isLogin=!!(null===(t=this.userInfo)||void 0===t?void 0:t.nickName)}showQrCode(){d.generate(this.qrUrl,{small:!0})}async login(e,t){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={},q.clear(),"axios"!==e.from&&this.logger.log("Logout Success!!!")}}const R=async(e,t={},s,r)=>{let o=e.getCompileEntryPage();o={...o,...t};const{path:i,query:a,launchMode:n}=o;try{let e=await(async e=>{const t=Buffer.from(e.replace(/^data:image\/[a-z]+;base64,/,""),"base64"),s=await g.read(t),r={data:new Uint8ClampedArray(s.bitmap.data),width:s.bitmap.width,height:s.bitmap.height},o=m(r.data,r.width,r.height);if(!o)throw new Error("QR code not found in the image.");return o.data})(s);return i&&(e=e.replace("_develop",`_develop${i.startsWith("/")?"":"/"}${i}`)),a&&(e+=`&${a}`),"halfPageNativeFunctionalized"===n&&(e+="&runtime_mode=2"),e}catch(e){r.error("二维码解码失败:",e)}};class B extends H{constructor(e){super(e),this.progressData={},this.previewData={},this.calcSize=e=>{var t,s;const r=this.project,o=(null===(t=null==r?void 0:r.flags)||void 0===t?void 0:t.enableV2Preivew)?"v2":"v1",i=(null===(s=null==e?void 0:e.filter)||void 0===s?void 0:s.call(e,(e=>e.type===o)).sort(((e,t)=>t.zipSize-e.zipSize)))||[];this.previewData.subPkgs=i.map(((e,t)=>({key:t,path:e.root,size:b(e.zipSize)})));const a=i.reduce(((e,t)=>t.zipSize+e),0)||0;this.previewData.zipSize=b(a)},this.uploadApi=new A(e),this.progressData={},this.previewData={}}preview(e){return new Promise(((t,s)=>{this.previewPromise={resolve:t,reject:s},this.doPreview(e)}))}doPreview(t){this.progressData.previewIsLoading=!0;const s=this.project.projectAppId;this.isTokenAuth();const r=Date.now(),o=async s=>{var o,i;const a=JSON.parse(s.result.extra_json);this.previewData.qrcodeUrl=await R(this.project,t.entry,a.qrcode,this.logger),this.showQrCode(this.previewData.qrcodeUrl),this.previewData.previewTotalTime=+((Date.now()-r)/1e3).toFixed(1),this.progressData.previewIsLoading=!1,this.compiler.kill(e.COMPILE_ENTRY.preview),null===(o=this.taskSubscription)||void 0===o||o.unsubscribe(),this.taskSubscription=null,null===(i=this.previewPromise)||void 0===i||i.resolve({qrcodeUrl:this.previewData.qrcodeUrl}),this.previewPromise=null,this.logger.log("Preview Done!!!")},i=t=>{var s,r;this.compiler.kill(e.COMPILE_ENTRY.preview),null===(s=this.taskSubscription)||void 0===s||s.unsubscribe(),this.taskSubscription=null,null===(r=this.previewPromise)||void 0===r||r.reject(t),this.previewPromise=null,this.logger.log("Preview Error:",t.toString())};this.taskSubscription=p.from(p.defer(this.getCheckUploadAuthFn(this.uploadApi,"debug"))).pipe(p.switchMap((t=>{let s=t.can_upload_ext_json,r=t.upload_app_id;if(!r)throw new Error("请检查是否该appid无权限");return p.from(this.compiler.compileAndZip({entryType:e.COMPILE_ENTRY.preview,can_upload_ext_json:s,upload_app_id:r}))})),p.tap((e=>{this.calcSize(e)})),p.switchMap((e=>{this.emit("compile-and-zip-status",{status:"uploading"}),this.logger.log("Upload packages to cos...");const t=e.map(((e,t)=>this.uploadFile(this.uploadApi,{zipPath:e.zipPath,type:e.type,root:e.root},t)));return p.forkJoin(t)})),p.switchMap((e=>{this.logger.log("Upload packages info...");const t={uploadApi:this.uploadApi,uploadRes:e,appId:s,version:"debug"};return this.submitTask(t)}))).subscribe({next:e=>o(e),error:e=>i(e)})}showQrCode(e){d.generate(e,{small:!0})}}exports.Core=class{constructor(){this.globalConfig={},this.appConfigMap={},this.currentAppConfig={},this.projectMap={},this.compilerMap={},this.globalConfig=z.get("globalConfig")||{},this.logger=new s.Logger("[xhs-mp-cli]"),globalThis.logger=this.logger,this.loginManager=new N({core:this,logger:this.logger})}setGlobalConfig(e={}){this.logger.log("Set global config..."),this.globalConfig={...this.globalConfig||{},...e},z.set("globalConfig",e),this.logger.log("Set global config done")}getGlobalConfig(){return this.globalConfig||{}}setAppConfig(e={}){const{appId:t,config:s}=e;t?(this.appConfigMap[t]={...this.appConfigMap[t]||{},...s},this.currentAppConfig=this.appConfigMap[t]):this.logger.error("没有传递 appId 参数")}getAppConfig(e){return this.appConfigMap[e]||{}}getProject(e){const{projectPath:s}=e;if(!s)throw new Error("没有配置projectPath");return this.projectMap[s]||(this.projectMap[s]=new t.Project(e)),this.projectMap[s]}getCompiler(t,s){const{projectPath:r}=t;if(!this.compilerMap[r]){const o=this.getProject(t);this.compilerMap[r]=new e.Compiler({...s,project:o,logger:this.logger})}return this.compilerMap[r]}async login(e={}){e.verbose&&this.logger.setVerbose(!0);const{type:t="qrcode"}=e;await this.loginManager.login(t,{...this.currentAppConfig||{}})}logout(e){this.loginManager.logout(e)}async preview(e){var t,s;if(e.verbose&&this.logger.setVerbose(!0),!(null===(s=null===(t=this.currentAppConfig)||void 0===t?void 0:t.config)||void 0===s?void 0:s.token)&&!this.loginManager.isLogin)return void this.logger.error("请先登陆或者使用token代替登录态");const r=e.project||{},o=e.buildConfig||{},i=this.getProject(r),a=this.getCompiler(r,o),n=new B({core:this,project:i,compiler:a,logger:this.logger});return await n.preview({entry:e.entry})}async upload(e){var t,s;if(e.verbose&&this.logger.setVerbose(!0),!(null===(s=null===(t=this.currentAppConfig)||void 0===t?void 0:t.config)||void 0===s?void 0:s.token)&&!this.loginManager.isLogin)return void this.logger.error("请先登陆或者使用token代替登录态");const{project:r,buildConfig:o={},version:i,desc:a,progressCallback:n}=e,l=this.getProject(r),p=this.getCompiler(r,o),c=new L({core:this,project:l,compiler:p,logger:this.logger});return await c.upload({userVersion:i,userDesc:a,progressCallback:n})}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/config/env.config.ts","../src/config/url.config.ts","../src/utils/utils.ts","../src/config/dir.config.ts","../src/utils/cookie.ts","../src/utils/axios.ts","../src/api/baseApi.ts","../src/api/uploadApi.ts","../src/services/baseService.ts","../src/utils/uuid.ts","../src/services/upload/upload.ts","../src/api/userApi.ts","../src/utils/storage.ts","../src/login.ts","../src/utils/qrcode.ts","../src/services/preview/preview.ts","../src/core.ts"],"sourcesContent":["\n// 接口环境\nexport const getXHSAPIENV = () => ({\n isSit: process.env.XHS_IS_PROD === 'false',\n isProd: process.env.XHS_IS_PROD === 'true'\n })\n","import { getXHSAPIENV } from './env.config'\nconst BUSINESS_SIT_HOST =\n require('process').env.XHS_BUSINESS_SIT_HOST || 'http://business-cli.sl.beta.xiaohongshu.com'\n\nconst CUSTOMER_SIT_HOST =\n require('process').env.XHS_CUSTOMER_SIT_HOST || 'https://customer.sit.xiaohongshu.com'\n\n\nexport const domain = {\n BUSINESS_HOST: getXHSAPIENV().isSit ? BUSINESS_SIT_HOST : 'https://business.xiaohongshu.com',\n CUSTOMER_HOST: getXHSAPIENV().isSit ? CUSTOMER_SIT_HOST : 'https://customer.xiaohongshu.com',\n CUSTOMER_SERVICE_ID: getXHSAPIENV().isSit\n ? CUSTOMER_SIT_HOST.replace(/https?:\\/\\/customer/, 'file://miniapp-open')\n : 'file://miniapp-open.xiaohongshu.com'\n }\n\n export const api = {\n generateQrCode: `${domain.CUSTOMER_HOST}/api/cas/generateQrCode`,\n queryQrCodeStatus: `${domain.CUSTOMER_HOST}/api/cas/queryQrCodeStatus`,\n session: `${domain.BUSINESS_HOST}/api/eros/mp/red/code/session`,\n getUserInfo: `${domain.BUSINESS_HOST}/api/eros/mp/red/code/user/info`,\n }\n ","import * as path from 'path'\n\nconst crypto = require('crypto')\nconst net = require('net')\n\nexport const throttle = (fn: any, wait = 100) => {\n let time: number | null = null\n return function (...args: any[]) {\n if (!time || Date.now() - time > wait) {\n time = Date.now()\n // @ts-ignore\n fn.apply(this, args)\n }\n }\n}\n\nexport const debounce = (func: any, wait = 300) => {\n let timer: any = null\n return (...args: any[]) => {\n clearTimeout(timer)\n timer = setTimeout(() => {\n func.apply(this, args)\n }, wait)\n }\n}\n\nexport const fileSize = (size: number) => {\n if (!size) return ''\n\n const base = 1024\n\n if (size < base) {\n return `${size}B`\n } if (size < base ** 2) {\n return `${(size / base).toFixed(2)}KB`\n } if (size < base ** 3) {\n return `${(size / base ** 2).toFixed(2)}MB`\n } if (size < base ** 4) {\n return `${(size / base ** 3).toFixed(2)}GB`\n }\n return `${(size / base ** 4).toFixed(2)}T`\n\n}\n\nexport function getMd5(str) {\n const hash = crypto.createHash('md5')\n hash.update(str)\n const md5 = hash.digest('hex')\n return md5\n}\n\nexport function getType(object: any): string {\n return Object.prototype.toString.call(object).toLowerCase().split(' ')[1].replace(']', '')\n}\n\nexport function normalizePath(str) {\n return str.replace(/\\\\/g, '/')\n}\n\nexport const compareVersion = function (v1Str: string, v2Str: string): number {\n if (typeof v1Str === \"undefined\" || typeof v2Str === \"undefined\") {\n console.error('请指定要对比的两个版本号', {v1Str, v2Str})\n return 0\n }\n const v1 = v1Str.split('.')\n const v2 = v2Str.split('.')\n const maxLength = Math.max(v1.length, v2.length)\n // 补全\n while (v1.length < maxLength) {\n v1.push('0')\n }\n while (v2.length < maxLength) {\n v2.push('0')\n }\n for (let i = 0; i < maxLength; i++) {\n const num1 = parseInt(v1[i], 10)\n const num2 = parseInt(v2[i], 10)\n\n if (num1 > num2) {\n return 1\n } if (num1 < num2) {\n return -1\n }\n }\n\n return 0\n}\n\nexport function picker<T>(obj: any, pick: string[]) {\n\treturn pick.reduce(\n\t\t(pre, next) => ({ ...pre, [next]: obj[next] }),\n\t\t{}\n\t) as T\n}\n\nexport const formatPath = (pathStr: string = '') => pathStr.split(path.sep).join(path.posix.sep)\n\nexport const toUnixPath = (pathStr: string = '') => pathStr.split(path.sep).join(path.posix.sep)\n\nexport const unixJoin = (...paths: string[]) => toUnixPath(path.join(...paths))\n\nexport const unixResolve = (...paths: string[]) => toUnixPath(path.resolve(...paths))\n","import { normalizePath } from \"../utils/utils\"\nimport os from 'os'\nimport path from 'path'\nimport fse from 'fs-extra'\n\nexport const baseDirPath = normalizePath(path.join(os.homedir(), '.xhs-mp-cli'))\nfse.ensureDirSync(baseDirPath)\n\nexport const mpStoragePath = normalizePath(path.join(baseDirPath, 'xhs-storage'))\nfse.ensureDirSync(mpStoragePath)","const tough = require('tough-cookie')\nimport { mpStoragePath } from 'config/dir.config'\nimport path from 'path'\nimport fse from 'fs-extra'\n\nclass CookieTool {\n cookieJar: any\n cookiePath: string\n\n constructor() {\n this.cookiePath = path.join(mpStoragePath, 'cookie.json')\n const data = this.getSerializeData()\n if (Object.keys(data).length) {\n this.cookieJar = tough.CookieJar.deserializeSync(data)\n } else {\n this.cookieJar = new tough.CookieJar()\n }\n }\n\n getSerializeData() {\n let json = {}\n if (fse.existsSync(this.cookiePath)) {\n json = fse.readJSONSync(this.cookiePath)\n }\n return json\n }\n\n save() {\n const data = this.cookieJar.serializeSync()\n fse.writeJSONSync(this.cookiePath, data)\n }\n\n\n clear() {\n fse.removeSync(this.cookiePath)\n }\n\n set(res) {\n const cookies = res.headers['set-cookie'] || []\n const url = res.config.url\n cookies.forEach(cookieStr => {\n const cookieMap = tough.Cookie.parse(cookieStr)\n if (cookieMap.domain) {\n const cookie = new tough.Cookie(cookieMap)\n this.cookieJar.setCookieSync(cookie, url)\n }\n })\n this.save()\n }\n\n get(url) {\n const cookie = this.cookieJar.getCookieStringSync(url)\n return cookie\n }\n}\n\nexport default new CookieTool()\n","import {domain} from '../config/url.config'\nimport axios, {AxiosRequestConfig} from 'axios'\nimport cookitTook from './cookie'\n\nlet coreInstance\n\naxios.defaults.baseURL = domain.BUSINESS_HOST\n\naxios.interceptors.request.use((config: AxiosRequestConfig) => {\n const {url, data, baseURL = ''} = config\n let uri: any = axios.getUri(config)\n // uri 需要拿 path,而不是整个 url\n if (/^https?:/.test(uri)) {\n try {\n const urlObj = new URL(url as string)\n uri = uri.replace(urlObj.origin, '')\n } catch (e) {\n uri = url\n }\n }\n\n\n const cookies = cookitTook.get(url)\n config.headers = {\n ...config.headers,\n Cookie: cookies,\n }\n\n config.headers['User-Agent'] = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) @xhs/mp-ide/2.0.0 Chrome/116.0.5845.228 Electron/26.4.0 Safari/537.36 discover/2.0.0 xhsminiapp/latest`\n\n return config\n})\n\naxios.interceptors.response.use(\n response => {\n // 保存cookies\n cookitTook.set(response)\n return response\n }\n)\n\n/* 拦截错误的请求 */\naxios.interceptors.response.use(\n response => {\n // Any status code that lie within the range of 2xx cause this function to trigger\n // Do something with response data\n const {config, data} = response\n if (config.url?.startsWith(`${domain.BUSINESS_HOST}/api/eros/mp/red`) && !data.success) {\n throw new Error(`${data.msg}`)\n }\n return response\n },\n async error => {\n const {response = {}} = error\n if (response.status === 401) {\n if (response.data && response.data.code === -240309) {\n coreInstance?.logout({\n from: 'axios'\n })\n return Promise.reject(new Error('登陆失效,请重新登陆或采用 token 免密登陆:', response.data.msg))\n }\n if (response.data && response.data.msg) {\n coreInstance?.logout({\n from: 'axios'\n })\n return Promise.reject(new Error(`未登录,请先登录或采用 token 免密登陆。code:${response.data.code},msg: ${response.data.msg}`))\n }\n }\n return Promise.reject(error)\n }\n)\n\nexport function getAxios(core) {\n coreInstance = core\n return axios\n}\n","import {EventEmitter} from 'events'\nimport {getAxios} from '../utils/axios'\nimport {Core} from '../core'\n\ninterface IRequestOpts {\n method: 'post' | 'get' | 'put' | 'delete'\n url: string\n data?: {\n [key: string]: any\n }\n config?: {\n [key: string]: any\n }\n}\nexport class BaseApi extends EventEmitter {\n core: Core\n constructor(props) {\n super()\n this.core = props.core\n }\n\n get axios() {\n return getAxios(this.core)\n }\n\n protected getProxyConfig() {\n const {proxy} = this.core.getGlobalConfig()\n if (proxy) {\n const urlObj = new URL(proxy)\n const proxyConfig = {\n host: urlObj.hostname,\n port: urlObj.port,\n protocol: urlObj.protocol\n }\n return proxyConfig\n } else {\n return false\n }\n }\n\n async request(opts: IRequestOpts) {\n const {method, url, data, config = {}} = opts\n const res = await this.axios[method](url, data, {\n ...config,\n // @ts-ignore\n proxy: this.getProxyConfig()\n })\n return res\n }\n\n protected handleHttpStatus(res) {\n if (res.status !== 200) {\n throw new Error(`request fail, code: ${res.status}, errMsg: ${res.status}`)\n }\n return res\n }\n\n protected handleStatusCode(res) {\n const {data} = res\n if (data.statusCode !== 200) {\n throw new Error(`request fail, code: ${data.statusCode}, errMsg: ${data.errorMsg}`)\n }\n return data.data\n }\n\n protected handleCode(res) {\n const {data} = res\n if (data.code !== 0 && data.error_code !== 0) {\n throw new Error(`request fail, code: ${data.code || data.error_code}, errMsg: ${data.msg}`)\n }\n return data.data\n }\n}\n","import {TokenRequest, TokenResponse} from 'xhs-mp-utils'\nimport {BaseApi} from './baseApi'\nimport {Project} from 'xhs-mp-project'\nimport {domain} from '../config/url.config'\n\nconst path = require('path')\nconst fs = require('fs-extra')\n\nexport interface IBusinessRoot<T> {\n code: number\n msg: string\n guid: any\n success: boolean\n data: T\n}\n\nexport interface ILongTaskRoot<T> {\n result: number\n success: boolean\n data: T\n error_code: number\n}\n\nexport interface IGetUploadTokenData {\n bucket: string\n expired: number\n key_prefix: string\n host: string\n sign: string\n}\n\nexport type IGetUploadToken = IBusinessRoot<IGetUploadTokenData>\n\nexport type ICreateUploadTask = IBusinessRoot<{\n task_id: string\n}>\n\nexport type IUploadCheckVersion = IBusinessRoot<{\n can_upload: boolean\n can_upload_ext_json: boolean\n show_msg: string\n upload_app_id: string\n}>\n\nexport type IQueryTaskDetail = ILongTaskRoot<{\n id: string\n finished_count: number\n total_count: number\n progress: number\n result: {\n file_url: any\n msg: string\n extra_json: string\n business_status: any\n success: boolean\n code: number\n }\n status: number\n}>\n\nexport interface IUploadCheckVersionParamsV1 {\n version: 'debug' | 'develop'\n // appJson: string;\n // extJson: string;\n // projectConfigJson: string;\n}\n\nexport interface IUploadCheckVersionParamsV2 extends IUploadCheckVersionParamsV1{\n appId: string\n cliToken: string\n nonce: string\n}\n\nexport interface IUploadPackageParamsV1 {\n appId: string\n version: 'debug' | 'develop'\n fileUrl: string\n userVersion?: string\n userDesc?: string\n packageMap: {\n [key: string]: string\n }\n packageMapV2?: {\n [key: string]: string\n }\n}\n\nexport interface IUploadPackageParamsV2 extends IUploadPackageParamsV1 {\n cliToken: string\n nonce: string\n}\n\nexport interface IQueryTaskDetailV1 {\n taskId: string\n}\n\nexport interface IQueryTaskDetailV2 extends IQueryTaskDetailV1 {\n appId: string\n cliToken: string\n nonce: string\n}\n\nconst readJsonStr = (_path: string) => {\n if (!fs.existsSync(_path)) return ''\n let res = ''\n try {\n res = JSON.stringify(fs.readJSONSync(_path))\n } catch (error) {\n console.warn(`readJson error: ${_path}`)\n }\n return res\n}\n\nexport class UploadApi extends BaseApi {\n project: Project\n\n constructor(props) {\n super(props)\n this.project = props.project\n }\n\n async checkUploadAuthV1({version}: IUploadCheckVersionParamsV1) {\n const project = this.project\n const appJsonPath = project.entryJsonPath\n const extJsonPath = path.resolve(project.extJsonPath)\n const appJson = readJsonStr(appJsonPath)\n const extJson = readJsonStr(extJsonPath)\n const appId = project.projectAppId\n const requestPath = `${domain.BUSINESS_HOST}/api/eros/mp/red/code/${appId}/validate/version/${version}`\n console.log('requestPath', requestPath, appJson, extJson)\n const res = await this.request({\n method: 'post',\n url: requestPath,\n data: {\n app_json: appJson,\n ext_json: extJson\n }\n })\n return this.handleCode(this.handleHttpStatus(res))\n }\n\n async checkUploadAuthV2(opts: IUploadCheckVersionParamsV2) {\n const {version, appId, cliToken, nonce} = opts\n const project = this.project\n const appJsonPath = project.entryJsonPath\n const extJsonPath = path.resolve(project.extJsonPath)\n const appJson = readJsonStr(appJsonPath)\n const extJson = readJsonStr(extJsonPath)\n const requestPath = `${domain.BUSINESS_HOST}/api/eros/mp/red/code/v2/validate/version?app_id=${appId}&cli_token=${cliToken}&nonce=${nonce}&version=${version}`\n console.log('requestPath', requestPath, appJson, extJson)\n const res = await this.request({\n method: 'post',\n url: requestPath,\n data: {\n app_json: appJson,\n ext_json: extJson\n }\n })\n return this.handleCode(this.handleHttpStatus(res))\n }\n\n\n getUploadToken = async (params: TokenRequest): Promise<TokenResponse> => {\n const res = await this.request({\n method: 'get',\n url: `${domain.BUSINESS_HOST}/api/eros/mp/red/code/upload/permit`,\n data: {\n params,\n withCredentials: true\n }\n })\n return this.handleCode(this.handleHttpStatus(res))\n }\n\n // 扫码等登录态\n async createUploadTaskV1(opts: IUploadPackageParamsV1) {\n const {version, fileUrl, userVersion, userDesc, appId, packageMap, packageMapV2} = opts\n const requestPath = `${domain.BUSINESS_HOST}/api/eros/mp/red/code/${appId}/upload/version/${version}`\n const res = await this.request({\n method: 'post',\n url: requestPath,\n data: {\n file_url: fileUrl,\n user_version: userVersion,\n user_desc: userDesc,\n package_map: packageMap,\n package_map_v2: packageMapV2,\n cloud_type: 4\n }\n })\n const data = this.handleCode(this.handleHttpStatus(res))\n return data\n }\n\n // token鉴权\n async createUploadTaskV2(opts: IUploadPackageParamsV2) {\n const {version, fileUrl, userVersion, userDesc, appId, packageMap, packageMapV2, cliToken, nonce} = opts\n const requestPath = `${domain.BUSINESS_HOST}/api/eros/mp/red/code/v2/upload/version?app_id=${appId}&cli_token=${cliToken}&nonce=${nonce}&version=${version}`\n const res = await this.request({\n method: 'post',\n url: requestPath,\n data: {\n file_url: fileUrl,\n user_version: userVersion,\n user_desc: userDesc,\n package_map: packageMap,\n package_map_v2: packageMapV2,\n cloud_type: 4\n }\n })\n const data = this.handleCode(this.handleHttpStatus(res))\n return data\n }\n\n async queryTaskDetailV1(opts: IQueryTaskDetailV1) {\n const {taskId} = opts\n const res = await this.request({\n method: 'get',\n url: `${domain.BUSINESS_HOST}/api/eros/mp/red/code/task/detail`,\n data: {\n params: {task_id: taskId}\n }\n })\n const data = this.handleCode(this.handleHttpStatus(res))\n return data\n }\n\n async queryTaskDetailV2(opts: IQueryTaskDetailV2) {\n const {taskId, appId, cliToken, nonce} = opts\n const requestPath = `${domain.BUSINESS_HOST}/api/eros/mp/red/code/v2/task/detail`\n const res = await this.request({\n method: 'get',\n url: requestPath,\n data: {\n params: {\n task_id: taskId,\n app_id: appId,\n cli_token: cliToken,\n nonce\n }\n }\n })\n const data = this.handleCode(this.handleHttpStatus(res))\n return data\n }\n}\n","import {Project} from 'xhs-mp-project'\nimport {Compiler} from 'xhs-mp-compiler-cli'\nimport EventEmitter from 'events'\nimport {Core} from '../core'\nimport * as path from 'path'\nimport * as fs from 'fs'\nimport {Uploader as CosUploader} from 'xhs-mp-utils'\nimport {guid, getNonce} from '../utils/uuid'\nimport {first, from, interval, map, Observable, switchMap} from 'rxjs'\nimport {isEmpty} from 'lodash'\nimport {UploadApi} from 'api/uploadApi'\nimport {getMd5} from 'utils/utils'\nimport dayjs from 'dayjs'\n\nexport interface IUploadCheckVersionParams {\n version: 'debug' | 'develop'\n // appJson: string;\n // extJson: string;\n // projectConfigJson: string;\n}\n\ntype IArchType = 'v0' | 'v1' | 'v2'\n\nexport type IZipResult = {\n type: IArchType\n zipPath: string\n zipSize: number\n root: string\n originSize: number\n}\n\ninterface IUploadFileOpts {\n zipPath\n type\n root\n}\n\ntype IUploadRes = {\n cdnFileUrl?: string\n fileId: string\n type: IArchType\n root: string\n}\n\ninterface ISubmitTaskRes {\n uploadApi: UploadApi\n uploadRes: IUploadRes[]\n appId: string\n version: IUploadCheckVersionParams['version']\n userDesc?: string\n userVersion?: string\n}\n\nexport interface IBaseServiceProps {\n core: Core\n project: Project\n compiler: Compiler\n logger: any\n}\n\nexport type IFinalRes = any\n\n// 获取分包结构\nconst getSubPackages = (uploadRes: IUploadRes[], type: IArchType) =>\n uploadRes.reduce((pre, cur) => {\n let res = {}\n if (cur.type === type) {\n res = {[cur.root]: cur.fileId}\n }\n return {...pre, ...res}\n }, {})\n\nexport class BaseService extends EventEmitter {\n core: Core\n project: Project\n compiler: Compiler\n logger: any\n\n constructor(props: IBaseServiceProps) {\n super()\n this.core = props.core\n this.project = props.project\n this.compiler = props.compiler\n this.logger = props.logger\n }\n\n isTokenAuth() {\n const appId = this.project.projectAppId\n const appConfig = this.core.getAppConfig(appId)\n return !!appConfig.token\n }\n\n getTokenParams() {\n const appId = this.project.projectAppId\n // md5(appid + '#' + secret + '#' + nonce + '#' + {yyyyMMddhhmm})\n const token = this.core.getAppConfig(appId).token\n const nonce = getNonce()\n const formattedTime = dayjs().format('YYYYMMDDHHmm')\n const str = appId + '#' + token + '#' + nonce + '#' + formattedTime\n const cliToken = getMd5(str)\n console.log('cliToken', str, cliToken)\n return {cliToken, nonce, appId}\n }\n\n getCheckUploadAuthFn(uploadApi, version: string) {\n let checkFn\n const isTokenAuth = this.isTokenAuth()\n this.logger.log('Check appid auth...', isTokenAuth)\n if (isTokenAuth) {\n const {appId, cliToken, nonce} = this.getTokenParams()\n checkFn = uploadApi.checkUploadAuthV2({\n version,\n appId,\n cliToken,\n nonce\n })\n } else {\n checkFn = uploadApi.checkUploadAuthV1({version})\n }\n return checkFn\n }\n\n uploadFile = (uploadApi, opts: IUploadFileOpts, index: number, successCallback?: () => void) => {\n const {zipPath, type, root} = opts\n const {appId, cliToken, nonce} = this.getTokenParams()\n const uploader = new CosUploader({\n bizName: 'fe', // temp 后端不消费\n scene: 'fe-platform', // temp 后端不消费\n getToken: params => {\n return uploadApi.getUploadToken({\n ...params,\n app_id: appId,\n nonce,\n cli_token: cliToken\n })\n }\n })\n return new Observable<IUploadRes>(subscriber => {\n setTimeout(() => {\n const uuid = guid()\n const fileName = `${uuid}-xhs-example.zip`\n const file = fs.readFileSync(path.resolve(zipPath))\n const stats = fs.statSync(path.resolve(zipPath))\n // console.log(file, 'uploader:before:::====🚀🚀🚀🚀🚀')\n function upload() {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n uploader\n .post({\n Body: file,\n fileInfo: {\n name: fileName,\n type: 'application/octet-stream',\n size: stats.size\n },\n FilePath: path.resolve(zipPath)\n })\n .then(res => {\n if (res.code !== 0) {\n return reject(new Error(`${zipPath}上传失败:${res.msg}`))\n }\n if (!res?.data?.fileId) {\n return reject(new Error(`${zipPath}上传失败`))\n }\n // console.log(file, zipPath, 'uploader:after:::====🚀🚀🚀🚀🚀', res.data)\n resolve({fileId: res.data.fileId, type, root})\n successCallback?.()\n })\n }, 500)\n })\n }\n // 上次多个文件,可能会出现某个上传失败,624状态码。\n // 根据寤生的验证,这里要这么操作,多次catch重试。\n // 这个服务目前无人维护,暂时这么搞吧。\n upload()\n .catch(upload)\n .catch(upload)\n .catch(upload)\n .catch(upload)\n .then((res: any) => {\n subscriber.next(res)\n subscriber.complete()\n })\n .catch(err => {\n subscriber.error(err)\n })\n }, 500) // 不能乘以index 否则容易报整包解析失败\n })\n }\n\n submitTask = (data: ISubmitTaskRes) => {\n const isTokenAuth = this.isTokenAuth()\n if (isTokenAuth) {\n return this.submitTaskV2(data)\n }\n return this.submitTaskV1(data)\n }\n\n /* 创建提交的任务 */\n private submitTaskV1 = (opts: ISubmitTaskRes) => {\n const {uploadApi, uploadRes, appId, version, userDesc, userVersion} = opts\n const fullPackFileId = uploadRes.filter(item => item.type === 'v0')[0].fileId\n\n const packageMap = getSubPackages(uploadRes, 'v1')\n const packageMapV2 = getSubPackages(uploadRes, 'v2')\n return from(\n uploadApi.createUploadTaskV1({\n version,\n fileUrl: fullPackFileId,\n appId,\n packageMap,\n packageMapV2: isEmpty(packageMapV2) ? undefined : packageMapV2,\n userDesc,\n userVersion\n })\n ).pipe(\n switchMap((v: any) => {\n const {task_id} = v\n return interval(1500).pipe(\n switchMap(() =>\n from(\n uploadApi.queryTaskDetailV1({\n taskId: task_id\n })\n ).pipe(\n map((data: any) => {\n if (data.status === 5) {\n throw new Error(data?.result?.msg)\n }\n return data\n })\n )\n ),\n first(v => v.status === 3)\n )\n })\n )\n }\n\n private submitTaskV2 = (opts: ISubmitTaskRes) => {\n const {uploadApi, uploadRes, version, userDesc, userVersion} = opts\n const fullPackFileId = uploadRes.filter(item => item.type === 'v0')[0].fileId\n const {appId, cliToken, nonce} = this.getTokenParams()\n const packageMap = getSubPackages(uploadRes, 'v1')\n const packageMapV2 = getSubPackages(uploadRes, 'v2')\n return from(\n uploadApi.createUploadTaskV2({\n version,\n fileUrl: fullPackFileId,\n appId,\n packageMap,\n packageMapV2: isEmpty(packageMapV2) ? undefined : packageMapV2,\n userDesc,\n userVersion,\n cliToken,\n nonce\n })\n ).pipe(\n switchMap((v: any) => {\n const {task_id} = v\n return interval(1500).pipe(\n switchMap(() =>\n from(\n uploadApi.queryTaskDetailV2({\n taskId: task_id,\n appId,\n cliToken,\n nonce\n })\n ).pipe(\n map((data: any) => {\n if (data.status === 5) {\n throw new Error(data?.result?.msg)\n }\n return data\n })\n )\n ),\n first(v => v.status === 3)\n )\n })\n )\n }\n}\n","export function guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n // eslint-disable-next-line no-bitwise\n const r = (Math.random() * 16) | 0\n // eslint-disable-next-line no-bitwise\n const v = c === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\nexport function getNonce() {\n return 'xxxxxxxxxxxxxxxx'.replace(/[xy]/g, c => {\n // eslint-disable-next-line no-bitwise\n const r = (Math.random() * 16) | 0\n // eslint-disable-next-line no-bitwise\n const v = c === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n","import {UploadApi} from '../../api/uploadApi'\nimport {BaseService, IFinalRes, IBaseServiceProps, IZipResult} from '../baseService'\nimport {Subscription, switchMap, from, forkJoin} from 'rxjs'\nimport {COMPILE_ENTRY} from 'xhs-mp-compiler-cli'\n\ntype IUploaderProps = IBaseServiceProps & {}\n\ninterface IUploadData {\n userVersion: string\n userDesc: string\n progressCallback?: any\n}\n\nexport class Uploader extends BaseService {\n taskSubscription: any\n uploadApi: UploadApi\n uploadPromise: {resolve: (value: unknown) => void; reject: (reason?: any) => void}\n\n constructor(props: IUploaderProps) {\n super(props)\n this.uploadApi = new UploadApi(props)\n }\n\n upload(uploadData: IUploadData) {\n return new Promise((resolve, reject) => {\n this.uploadPromise = {\n resolve,\n reject\n }\n this.doUpload(uploadData)\n })\n }\n\n private doUpload = (opts: IUploadData) => {\n const {progressCallback, userVersion, userDesc} = opts\n\n if (!userVersion?.trim()) {\n throw new Error('请填写上传版本号')\n }\n if (!userDesc?.trim()) {\n throw new Error('请填写版本描述')\n }\n\n /* 上传成功 */\n const successHandle = () => {\n this.compiler.kill(COMPILE_ENTRY.upload)\n this.taskSubscription?.unsubscribe()\n this.taskSubscription = null\n this.uploadPromise?.resolve(null)\n // @ts-ignore\n this.uploadPromise = null\n this.logger.log('Upload Done!!!')\n }\n\n /* 上传出现异常 */\n const errorHandle = (err: Error) => {\n progressCallback?.(-1) // 出错时,进度设置为 -1\n this.taskSubscription?.unsubscribe()\n this.taskSubscription = null\n this.compiler.kill(COMPILE_ENTRY.upload)\n this.logger.log('Upload Error:', err.toString())\n this.uploadPromise?.reject(err)\n // @ts-ignore\n this.uploadPromise = null\n }\n try {\n const appId = this.project.projectAppId\n this.taskSubscription = from(this.getCheckUploadAuthFn(this.uploadApi, 'develop'))\n .pipe(\n switchMap((v: any) => {\n let can_upload = v.can_upload\n let can_upload_ext_json = v.can_upload_ext_json\n let upload_app_id = v.upload_app_id\n if (!can_upload) {\n throw new Error(v.show_msg)\n }\n if (!upload_app_id) {\n throw new Error('请检查是否该appid无权限')\n }\n progressCallback?.(5) // 进度更新为 15%\n return from(\n this.compiler.compileAndZip({\n entryType: COMPILE_ENTRY.upload,\n can_upload_ext_json,\n upload_app_id,\n pkgInfo: {\n // 上传用户填写的包版本信息。\n version: userVersion\n }\n })\n )\n }),\n switchMap((fileList: IZipResult[]) => {\n progressCallback?.(30) // 进度更新为 30%\n this.emit('compile-and-zip-status', {\n status: 'uploading'\n })\n this.logger.log('Upload packages to cos...')\n const list = fileList.map((item, index) =>\n this.uploadFile(\n this.uploadApi,\n {\n zipPath: item.zipPath,\n type: item.type,\n root: item.root\n },\n index,\n () => {\n progressCallback?.(30 + (45 / fileList.length) * (index + 1)) // 在每个文件上传后更新进度\n }\n )\n )\n return forkJoin(list)\n }),\n switchMap(v => {\n progressCallback?.(80) // 所有文件上传完成,进度更新为 80%\n this.logger.log('Upload packages info...')\n const data = {\n uploadApi: this.uploadApi,\n uploadRes: v,\n appId,\n version: 'develop' as any,\n userVersion,\n userDesc\n }\n return this.submitTask(data)\n })\n )\n .subscribe({\n next: (fin: IFinalRes) => {\n progressCallback?.(100) // 所有文件上传完成,进度更新为 100%\n successHandle()\n },\n error: err => {\n errorHandle(err)\n }\n })\n } catch (err) {\n errorHandle(err)\n }\n }\n}\n","import {domain, api} from '../config/url.config'\nimport { BaseApi } from './baseApi'\n\n\nexport interface IBaseRoot<T> {\n alertMsg: string\n data: T\n errorCode: any\n errorMsg: any\n statusCode: number\n success: boolean\n traceLogId: string\n}\n\nexport type IGenerateQrCodeData = IBaseRoot<{\n qrId: string\n qrUrl: string\n}>\n\nexport interface IQueryQrCodeStatusData {\n authToken: null | string\n avatar: null | string\n customerUserType: null | string\n status: number\n ticket: null | string\n userId: null | string\n}\n\nexport type IQueryQrCodeStatus = IBaseRoot<IQueryQrCodeStatusData>\n\nexport type ILoginData = Omit<IQueryQrCodeStatusData, 'status'>\n\n/* 用户的登录信息 */\nexport interface IBusinessRoot {\n code: number\n msg: string\n guid: any\n success: boolean\n data: {\n [key: string]: any\n }\n}\n\nexport type IGetUserInfo = IBusinessRoot\n\nexport class UserApi extends BaseApi {\n\n async generateQrCode() {\n const res = await this.request({\n method: 'post', \n url: api.generateQrCode, \n data: {\n subsystem: 'business'\n }\n })\n return this.handleStatusCode(this.handleHttpStatus(res))\n }\n\n async queryQrCodeStatus(qrId: string) {\n const res = await this.request({\n method: 'get', \n url: api.queryQrCodeStatus, \n data: {\n params: {\n qrId,\n service: domain.CUSTOMER_SERVICE_ID\n }\n }\n })\n return this.handleStatusCode(this.handleHttpStatus(res))\n }\n\n async login(ticket: string) {\n const res = await this.request({\n method: 'post', \n url: api.session, \n data: {\n ticket,\n clientId: domain.CUSTOMER_SERVICE_ID\n }\n })\n return this.handleHttpStatus(res).data\n }\n\n async fetchUserInfo() {\n const res = await this.request({\n method: 'get', \n url: api.getUserInfo,\n })\n return this.handleCode(this.handleHttpStatus(res))\n }\n\n}\n","import path from 'path'\nimport fse from 'fs-extra'\nimport {mpStoragePath} from '../config/dir.config'\n\nclass Storage {\n jsonPath: string\n data: {\n [key: string]: any\n } = {}\n private timer: any\n\n constructor() {\n this.jsonPath = path.join(mpStoragePath, 'storage.json')\n if (fse.existsSync(this.jsonPath)) {\n try {\n this.data = fse.readJSONSync(this.jsonPath)\n } catch (error) {\n this.data = {}\n }\n }\n }\n\n get(key) {\n return this.data[key]\n }\n\n set(key, val) {\n this.data[key] = val\n this.refresh()\n }\n\n refresh() {\n // this.timer && clearTimeout(this.timer)\n // this.timer = setTimeout(() => {\n fse.writeJSONSync(this.jsonPath, this.data)\n // }, 0)\n }\n}\n\nexport default new Storage()\n","import {picker} from './utils/utils'\nimport {UserApi} from './api/userApi'\nimport {from, interval, defer} from 'rxjs'\nimport {switchMap, map, tap, takeWhile, retry, exhaustMap} from 'rxjs/operators'\nimport qrcode from 'qrcode-terminal'\nimport storage from './utils/storage'\nimport cookie from './utils/cookie'\n\nexport type IUserInfo = {\n nickName: string\n avatar: string\n userId: string\n desc: string\n gender: number\n userInfoData?: any\n}\n\nexport interface IUserInfoData {\n nick: string\n img: string\n}\n\nexport class LoginManager {\n private qrUrl: string\n private userApi: UserApi\n private qrCodeStatusData: {isLoading: boolean; expired: boolean} = {} as any\n private startPollingSub: any = null\n private loginPromise: any = {}\n private logger: any\n private _isLogin: any\n private _userInfo: any\n\n get isLogin() {\n return this._isLogin\n }\n\n set isLogin(isLogin) {\n this._isLogin = isLogin\n }\n\n\n get userInfo() {\n return this._userInfo\n }\n\n set userInfo(info) {\n this._userInfo = info\n storage.set('xhs-cli-userInfo', info)\n }\n\n constructor(props) {\n this.logger = props.logger\n this.userApi = new UserApi(props)\n\n this.qrCodeStatusData = {\n isLoading: false,\n expired: false\n }\n this._userInfo = storage.get('userInfo') || storage.get('xhs-cli-userInfo') || {}\n this.isLogin = !!this.userInfo?.nickName\n }\n\n private transformUserInfo = (data: IUserInfoData): IUserInfo => {\n const {nick, avatar, desc, gender} = picker<any>(data, ['nick', 'avatar', 'desc', 'gender'])\n return {nickName: nick, avatar, userId: '', desc, gender}\n }\n\n private showQrCode() {\n qrcode.generate(this.qrUrl, {\n small: true\n })\n }\n\n private queryQrCodeStatus = (qrId: string) => {\n return from(this.userApi.queryQrCodeStatus(qrId))\n }\n\n private doLogin = async (ticket: string) => {\n const {resolve, reject} = this.loginPromise\n this.loginPromise = null\n try {\n const data = await this.userApi.login(ticket)\n if (!data.success) {\n reject(new Error(data.msg))\n return\n }\n const userInfoData = await this.userApi.fetchUserInfo()\n const userInfo: IUserInfo = this.transformUserInfo(userInfoData)\n userInfo.userInfoData = userInfoData\n resolve(userInfo)\n } catch (error) {\n reject(new Error(error.message))\n return\n }\n }\n\n private startPolling = () => {\n this.qrCodeStatusData.isLoading = true\n this.qrCodeStatusData.expired = false\n return from(defer(() => this.userApi.generateQrCode())).pipe(\n tap((data: any) => {\n this.qrUrl = data.qrUrl\n this.qrCodeStatusData.isLoading = false\n this.showQrCode()\n setTimeout(() => {\n this.qrCodeStatusData.expired = true\n // 二维码过期是也需要停止轮询\n this.stopPolling()\n }, 60 * 1000)\n }),\n exhaustMap(({qrUrl, qrId}) =>\n interval(2000).pipe(\n switchMap(() => this.queryQrCodeStatus(qrId)),\n tap((data: any) => {\n if (data.status === 4) {\n throw new Error('retry login')\n }\n if (data.status === 1) {\n this.stopPolling()\n this.doLogin(data.ticket)\n }\n })\n )\n ),\n takeWhile(data => data.status !== 1),\n retry(5)\n )\n }\n\n private stopPolling = () => {\n if (this.startPollingSub) {\n this.startPollingSub.unsubscribe()\n this.startPollingSub = null\n }\n }\n\n async login(type: 'qrcode', data) {\n if (this.isLogin) {\n this.logger.log('Had Login!!!')\n return\n }\n this.isLogin = false\n this.logger.log('Login...')\n try {\n if (type === 'qrcode') {\n const userInfo = await this.loginByQrcode()\n this.userInfo = userInfo\n } else {\n throw new Error('暂不支持扫码之外的其他登陆方式')\n }\n this.isLogin = true\n this.logger.log('Login success')\n } catch (error) {\n this.logger.log('Login fail:', error.message)\n this.isLogin = false\n this.userInfo = null\n throw error\n }\n }\n\n loginByQrcode() {\n return new Promise((resolve, reject) => {\n this.loginPromise = {\n resolve,\n reject\n }\n try {\n this.startPollingSub = this.startPolling().subscribe()\n } catch (error) {\n console.error(error)\n }\n })\n }\n\n\n logout(opts) {\n if (opts.from !== 'axios') {\n this.logger.log('Logout...')\n }\n this.isLogin = false\n this.userInfo = {}\n cookie.clear()\n if (opts.from !== 'axios') {\n this.logger.log('Logout Success!!!')\n }\n }\n}\n","import Jimp from 'jimp'\nimport jsQR from 'jsqr'\n\nconst decodeQRBase64 = async (base64): Promise<string | undefined> => {\n const qrBuffer = Buffer.from(base64.replace(/^data:image\\/[a-z]+;base64,/, ''), 'base64')\n const image = await Jimp.read(qrBuffer)\n\n // Get the image data\n const imageData = {\n data: new Uint8ClampedArray(image.bitmap.data),\n width: image.bitmap.width,\n height: image.bitmap.height\n }\n\n // Use jsQR to decode the QR code\n const decodedQR = jsQR(imageData.data, imageData.width, imageData.height)\n\n if (!decodedQR) {\n throw new Error('QR code not found in the image.')\n }\n\n return decodedQR.data\n}\n\n/* 前端生成深度链接二维码 */\nexport const genDeeplink = async (project, entry = {}, qrcode, logger) => {\n let entryData = project.getCompileEntryPage()\n entryData = {\n ...entryData,\n ...entry\n }\n const {path, query, launchMode} = entryData\n\n try {\n let deepLink = (await decodeQRBase64(qrcode)) as any\n if (path) {\n deepLink = deepLink.replace('_develop', `_develop${path.startsWith('/') ? '' : '/'}${path}`)\n }\n\n if (query) {\n deepLink += `&${query}`\n }\n\n if (launchMode === 'halfPageNativeFunctionalized') {\n deepLink += '&runtime_mode=2'\n }\n return deepLink\n } catch (error) {\n logger.error('二维码解码失败:', error)\n }\n}\n","import {genDeeplink} from '../../utils/qrcode'\nimport {BaseService, IFinalRes, IBaseServiceProps} from '../baseService'\nimport {from, defer, map, Observable, switchMap, tap, forkJoin} from 'rxjs'\nimport {COMPILE_ENTRY} from 'xhs-mp-compiler-cli'\nimport {UploadApi} from '../../api/uploadApi'\nimport {fileSize} from '../../utils/utils'\nimport qrcode from 'qrcode-terminal'\n\ntype IPreviewProps = IBaseServiceProps & {}\n\ninterface IPreviewData {\n entry?: {\n path: string\n query?: string\n launchMode?: string\n }\n}\n\nexport class Preview extends BaseService {\n uploadApi: UploadApi\n taskSubscription: any\n progressData: {\n [key: string]: any\n } = {}\n previewData: {\n [key: string]: any\n } = {}\n previewPromise: {resolve: (value: unknown) => void; reject: (reason?: any) => void}\n\n constructor(props: IPreviewProps) {\n super(props)\n this.uploadApi = new UploadApi(props)\n this.progressData = {}\n this.previewData = {}\n }\n\n preview(opts: IPreviewData) {\n return new Promise((resolve, reject) => {\n this.previewPromise = {\n resolve,\n reject\n }\n this.doPreview(opts)\n })\n }\n\n doPreview(opts: IPreviewData) {\n this.progressData.previewIsLoading = true\n const appId = this.project.projectAppId\n const isTokenAuth = this.isTokenAuth()\n\n const _startTime = Date.now()\n\n const successHandle = async (fin: IFinalRes) => {\n const extra_json = JSON.parse(fin.result.extra_json)\n this.previewData.qrcodeUrl = await genDeeplink(this.project, opts.entry, extra_json.qrcode, this.logger)\n this.showQrCode(this.previewData.qrcodeUrl)\n\n this.previewData.previewTotalTime = +((Date.now() - _startTime) / 1000).toFixed(1)\n this.progressData.previewIsLoading = false\n\n this.compiler.kill(COMPILE_ENTRY.preview)\n\n this.taskSubscription?.unsubscribe()\n this.taskSubscription = null\n this.previewPromise?.resolve({\n qrcodeUrl: this.previewData.qrcodeUrl\n })\n // @ts-ignore\n this.previewPromise = null\n\n this.logger.log('Preview Done!!!')\n }\n\n const errorHandle = err => {\n this.compiler.kill(COMPILE_ENTRY.preview)\n\n this.taskSubscription?.unsubscribe()\n this.taskSubscription = null\n this.previewPromise?.reject(err)\n // @ts-ignore\n this.previewPromise = null\n\n this.logger.log('Preview Error:', err.toString())\n }\n\n this.taskSubscription = from(defer(this.getCheckUploadAuthFn(this.uploadApi, 'debug')))\n .pipe(\n switchMap((v: any) => {\n let can_upload_ext_json = v.can_upload_ext_json\n let upload_app_id = v.upload_app_id\n if (!upload_app_id) {\n throw new Error('请检查是否该appid无权限')\n }\n return from(\n this.compiler.compileAndZip({\n entryType: COMPILE_ENTRY.preview,\n can_upload_ext_json,\n upload_app_id\n })\n )\n }),\n tap(res => {\n /* 记录下zip包的信息 */\n this.calcSize(res)\n }),\n switchMap(fileList => {\n this.emit('compile-and-zip-status', {status: 'uploading'})\n this.logger.log('Upload packages to cos...')\n const list = fileList.map((item, index) =>\n this.uploadFile(\n this.uploadApi,\n {\n zipPath: item.zipPath,\n type: item.type,\n root: item.root\n },\n index\n )\n )\n return forkJoin(list)\n }),\n switchMap((v: any) => {\n this.logger.log('Upload packages info...')\n const data = {\n uploadApi: this.uploadApi,\n uploadRes: v,\n appId,\n version: 'debug' as any\n }\n return this.submitTask(data)\n })\n )\n .subscribe({\n next: (fin: IFinalRes) => {\n return successHandle(fin)\n },\n error: err => {\n return errorHandle(err)\n }\n })\n }\n\n showQrCode(qrUrl) {\n qrcode.generate(qrUrl, {\n small: true\n })\n }\n\n calcSize = zipSizeInfo => {\n const project = this.project\n // @ts-ignore\n const type = project?.flags?.enableV2Preivew ? 'v2' : 'v1'\n const rowList = zipSizeInfo?.filter?.(i => i.type === type).sort((a, b) => b.zipSize - a.zipSize) || []\n this.previewData.subPkgs = rowList.map((item, key) => ({\n key,\n path: item.root,\n size: fileSize(item.zipSize)\n }))\n const allZipSize = rowList.reduce((ac, i) => i.zipSize + ac, 0) || 0\n this.previewData.zipSize = fileSize(allZipSize)\n }\n}\n","import {Compiler, ICompileOpts} from 'xhs-mp-compiler-cli'\nimport {Project} from 'xhs-mp-project'\nimport {Logger} from 'xhs-mp-utils'\nimport {Uploader} from './services/upload/upload'\nimport {LoginManager} from './login'\nimport {Preview} from './services/preview/preview'\nimport type {IProjectOptions} from 'xhs-mp-project'\nimport storage from './utils/storage'\n\nexport interface IVerbose {\n verbose?: boolean\n from?: 'cli' | 'code' | 'axios'\n}\nexport interface IGlobalConfig {\n proxy?: string\n}\n\nexport interface IAppConfig {\n token?: string\n [key: string]: any\n}\n\nexport interface IAppConfigMap {\n [appId: string]: IAppConfig\n}\n\nexport type ILoginConfig = IVerbose & {\n type?: 'qrcode'\n}\n\nexport type ILogoutConfig = IVerbose & {}\n\nexport interface ILibFeatures {\n supportV2?: boolean\n supportVdom?: boolean\n}\n\nexport interface IBaseActionOpts {\n project: {\n projectPath: string\n watch?: boolean\n }\n buildConfig?: {\n compileDir?: string\n nodeJsPath?: string\n mpDevJsonPath?: string\n libFeatures?: ILibFeatures\n }\n}\n\nexport type IPreivewOpts = IBaseActionOpts &\n IVerbose & {\n entry?: {\n path: string\n query?: string\n launchMode?: string\n }\n }\n\nexport type IUploadOpts = IBaseActionOpts &\n IVerbose & {\n version: string\n desc: string\n progressCallback?: any\n }\n\nexport class Core {\n private globalConfig: IGlobalConfig = {}\n private appConfigMap: IAppConfigMap = {}\n private currentAppConfig: IAppConfig = {} as IAppConfig\n private projectMap: {\n [key: string]: Project\n } = {} as any\n private compilerMap: {\n [key: string]: Compiler\n } = {} as any\n private logger: Logger\n private loginManager: LoginManager\n\n constructor() {\n this.globalConfig = storage.get('globalConfig') || {}\n this.logger = new Logger('[xhs-mp-cli]')\n globalThis.logger = this.logger\n this.loginManager = new LoginManager({\n core: this,\n logger: this.logger\n })\n }\n\n setGlobalConfig(config: IGlobalConfig = {}) {\n this.logger.log('Set global config...')\n this.globalConfig = {\n ...(this.globalConfig || {}),\n ...config\n }\n storage.set('globalConfig', config)\n this.logger.log('Set global config done')\n }\n\n getGlobalConfig() {\n return this.globalConfig || {}\n }\n\n setAppConfig(appConfig: IAppConfig = {} as IAppConfig) {\n const {appId, config} = appConfig\n if (!appId) {\n this.logger.error('没有传递 appId 参数')\n return\n }\n this.appConfigMap[appId] = {\n ...(this.appConfigMap[appId] || {}),\n ...config\n }\n this.currentAppConfig = this.appConfigMap[appId]\n }\n\n getAppConfig(appId) {\n return this.appConfigMap[appId] || {}\n }\n\n private getProject(props: IProjectOptions) {\n const {projectPath} = props\n if (!projectPath) {\n throw new Error('没有配置projectPath')\n }\n if (!this.projectMap[projectPath]) {\n this.projectMap[projectPath] = new Project(props)\n }\n return this.projectMap[projectPath]\n }\n\n private getCompiler(props: IProjectOptions, config: ICompileOpts) {\n const {projectPath} = props\n if (!this.compilerMap[projectPath]) {\n const project = this.getProject(props)\n this.compilerMap[projectPath] = new Compiler({\n ...config,\n project,\n logger: this.logger\n })\n }\n return this.compilerMap[projectPath]\n }\n\n async login(opts: ILoginConfig = {}) {\n if (opts.verbose) {\n this.logger.setVerbose(true)\n }\n const {type = 'qrcode'} = opts\n await this.loginManager.login(type, {\n ...(this.currentAppConfig || {})\n })\n }\n\n logout(opts: ILogoutConfig) {\n this.loginManager.logout(opts)\n }\n\n async preview(opts: IPreivewOpts) {\n if (opts.verbose) {\n this.logger.setVerbose(true)\n }\n if (!this.currentAppConfig?.config?.token) {\n if (!this.loginManager.isLogin) {\n this.logger.error('请先登陆或者使用token代替登录态')\n return\n }\n }\n const projectInfo = opts.project || {}\n const buildConfig = opts.buildConfig || {}\n const project = this.getProject(projectInfo)\n const compiler = this.getCompiler(projectInfo, buildConfig)\n const previewService = new Preview({\n core: this,\n project,\n compiler,\n logger: this.logger\n })\n return await previewService.preview({\n entry: opts.entry\n })\n }\n\n async upload(opts: IUploadOpts) {\n if (opts.verbose) {\n this.logger.setVerbose(true)\n }\n if (!this.currentAppConfig?.config?.token) {\n if (!this.loginManager.isLogin) {\n this.logger.error('请先登陆或者使用token代替登录态')\n return\n }\n }\n const {project: _project, buildConfig = {}, version, desc, progressCallback} = opts\n const project = this.getProject(_project)\n const compiler = this.getCompiler(_project, buildConfig)\n const uploadService = new Uploader({\n core: this,\n project,\n compiler,\n logger: this.logger\n })\n return await uploadService.upload({\n userVersion: version,\n userDesc: desc,\n progressCallback\n })\n }\n}\n"],"names":["getXHSAPIENV","isSit","process","env","XHS_IS_PROD","isProd","BUSINESS_SIT_HOST","require","XHS_BUSINESS_SIT_HOST","CUSTOMER_SIT_HOST","XHS_CUSTOMER_SIT_HOST","domain","BUSINESS_HOST","CUSTOMER_HOST","CUSTOMER_SERVICE_ID","replace","api","generateQrCode","queryQrCodeStatus","session","getUserInfo","crypto","fileSize","size","base","toFixed","normalizePath","str","baseDirPath","path","join","os","homedir","fse","ensureDirSync","mpStoragePath","tough","cookie","constructor","this","cookiePath","data","getSerializeData","Object","keys","length","cookieJar","CookieJar","deserializeSync","json","existsSync","readJSONSync","save","serializeSync","writeJSONSync","clear","removeSync","set","res","cookies","headers","url","config","forEach","cookieStr","cookieMap","Cookie","parse","setCookieSync","get","getCookieStringSync","coreInstance","axios","defaults","baseURL","interceptors","request","use","uri","getUri","test","urlObj","URL","origin","e","cookitTook","response","_a","startsWith","success","Error","msg","async","error","status","code","logout","from","Promise","reject","BaseApi","EventEmitter","props","super","core","getProxyConfig","proxy","getGlobalConfig","host","hostname","port","protocol","opts","method","handleHttpStatus","handleStatusCode","statusCode","errorMsg","handleCode","error_code","fs","readJsonStr","_path","JSON","stringify","console","warn","UploadApi","getUploadToken","params","withCredentials","project","checkUploadAuthV1","version","appJsonPath","entryJsonPath","extJsonPath","resolve","appJson","extJson","appId","projectAppId","requestPath","log","app_json","ext_json","checkUploadAuthV2","cliToken","nonce","createUploadTaskV1","fileUrl","userVersion","userDesc","packageMap","packageMapV2","file_url","user_version","user_desc","package_map","package_map_v2","cloud_type","createUploadTaskV2","queryTaskDetailV1","taskId","task_id","queryTaskDetailV2","app_id","cli_token","getSubPackages","uploadRes","type","reduce","pre","cur","root","fileId","BaseService","uploadFile","uploadApi","index","successCallback","zipPath","getTokenParams","uploader","CosUploader","bizName","scene","getToken","Observable","subscriber","setTimeout","fileName","c","r","Math","random","toString","file","readFileSync","stats","statSync","upload","post","Body","fileInfo","name","FilePath","then","catch","next","complete","err","submitTask","isTokenAuth","submitTaskV2","submitTaskV1","fullPackFileId","filter","item","isEmpty","undefined","pipe","switchMap","v","interval","map","result","first","compiler","logger","getAppConfig","token","dayjs","format","hash","createHash","update","digest","getMd5","getCheckUploadAuthFn","checkFn","Uploader","doUpload","progressCallback","trim","successHandle","kill","COMPILE_ENTRY","taskSubscription","unsubscribe","_b","uploadPromise","errorHandle","can_upload","can_upload_ext_json","upload_app_id","show_msg","compileAndZip","entryType","pkgInfo","fileList","emit","list","forkJoin","subscribe","fin","uploadData","UserApi","subsystem","qrId","service","login","ticket","clientId","fetchUserInfo","storage","jsonPath","key","val","refresh","LoginManager","isLogin","_isLogin","userInfo","_userInfo","info","qrCodeStatusData","startPollingSub","loginPromise","transformUserInfo","nick","avatar","desc","gender","obj","nickName","userId","userApi","doLogin","userInfoData","message","startPolling","isLoading","expired","defer","tap","qrUrl","showQrCode","stopPolling","exhaustMap","takeWhile","retry","qrcode","generate","small","loginByQrcode","genDeeplink","entry","entryData","getCompileEntryPage","query","launchMode","deepLink","base64","qrBuffer","Buffer","image","Jimp","read","imageData","Uint8ClampedArray","bitmap","width","height","decodedQR","jsQR","decodeQRBase64","Preview","progressData","previewData","calcSize","zipSizeInfo","flags","enableV2Preivew","rowList","i","sort","a","b","zipSize","subPkgs","allZipSize","ac","preview","previewPromise","doPreview","previewIsLoading","_startTime","Date","now","extra_json","qrcodeUrl","previewTotalTime","globalConfig","appConfigMap","currentAppConfig","projectMap","compilerMap","Logger","globalThis","loginManager","setGlobalConfig","setAppConfig","appConfig","getProject","projectPath","Project","getCompiler","Compiler","verbose","setVerbose","projectInfo","buildConfig","previewService","_project","uploadService"],"mappings":"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"}
package/dist/login.d.ts CHANGED
@@ -25,13 +25,12 @@ export declare class LoginManager {
25
25
  set userInfo(info: any);
26
26
  constructor(props: any);
27
27
  private transformUserInfo;
28
- showQrCode(): void;
28
+ private showQrCode;
29
29
  private queryQrCodeStatus;
30
30
  private doLogin;
31
31
  private startPolling;
32
32
  private stopPolling;
33
- login(type: 'qrcode' | 'token', data: any): Promise<void>;
33
+ login(type: 'qrcode', data: any): Promise<void>;
34
34
  loginByQrcode(): Promise<unknown>;
35
- loginByToken(token: any): Promise<void>;
36
35
  logout(opts: any): void;
37
36
  }
@@ -1,18 +1,63 @@
1
1
  /// <reference types="node/events" />
2
- import { Project } from "xhs-mp-project";
3
- import { Compiler } from "xhs-mp-compiler-cli";
4
- import EventEmitter from "events";
5
- import { Core } from "../core";
2
+ import { Project } from 'xhs-mp-project';
3
+ import { Compiler } from 'xhs-mp-compiler-cli';
4
+ import EventEmitter from 'events';
5
+ import { Core } from '../core';
6
+ import { Observable } from 'rxjs';
7
+ import { UploadApi } from 'api/uploadApi';
8
+ export interface IUploadCheckVersionParams {
9
+ version: 'debug' | 'develop';
10
+ }
11
+ type IArchType = 'v0' | 'v1' | 'v2';
12
+ export type IZipResult = {
13
+ type: IArchType;
14
+ zipPath: string;
15
+ zipSize: number;
16
+ root: string;
17
+ originSize: number;
18
+ };
19
+ interface IUploadFileOpts {
20
+ zipPath: any;
21
+ type: any;
22
+ root: any;
23
+ }
24
+ type IUploadRes = {
25
+ cdnFileUrl?: string;
26
+ fileId: string;
27
+ type: IArchType;
28
+ root: string;
29
+ };
30
+ interface ISubmitTaskRes {
31
+ uploadApi: UploadApi;
32
+ uploadRes: IUploadRes[];
33
+ appId: string;
34
+ version: IUploadCheckVersionParams['version'];
35
+ userDesc?: string;
36
+ userVersion?: string;
37
+ }
6
38
  export interface IBaseServiceProps {
7
39
  core: Core;
8
40
  project: Project;
9
41
  compiler: Compiler;
10
42
  logger: any;
11
43
  }
44
+ export type IFinalRes = any;
12
45
  export declare class BaseService extends EventEmitter {
13
46
  core: Core;
14
47
  project: Project;
15
48
  compiler: Compiler;
16
49
  logger: any;
17
50
  constructor(props: IBaseServiceProps);
51
+ isTokenAuth(): boolean;
52
+ getTokenParams(): {
53
+ cliToken: any;
54
+ nonce: string;
55
+ appId: string;
56
+ };
57
+ getCheckUploadAuthFn(uploadApi: any, version: string): any;
58
+ uploadFile: (uploadApi: any, opts: IUploadFileOpts, index: number, successCallback?: () => void) => Observable<IUploadRes>;
59
+ submitTask: (data: ISubmitTaskRes) => Observable<any>;
60
+ private submitTaskV1;
61
+ private submitTaskV2;
18
62
  }
63
+ export {};
@@ -1 +1,2 @@
1
1
  export declare function guid(): string;
2
+ export declare function getNonce(): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xhs-mp-core",
3
- "version": "1.1.4",
3
+ "version": "1.2.0-beta.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -14,11 +14,9 @@
14
14
  "author": "",
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
- "xhs-mp-compiler-cli": "^1.1.6",
18
- "xhs-mp-project": "^1.1.4",
19
- "xhs-mp-utils": "^1.1.3",
20
17
  "archiver": "^7.0.1",
21
18
  "axios": "^0.21.4",
19
+ "dayjs": "^1.11.11",
22
20
  "debug": "^4.3.4",
23
21
  "fs-extra": "^11.2.0",
24
22
  "globby": "^14.0.1",
@@ -29,7 +27,10 @@
29
27
  "query-string": "^8.1.0",
30
28
  "querystring": "^0.2.1",
31
29
  "rxjs": "^7.8.1",
32
- "tough-cookie": "^4.1.3"
30
+ "tough-cookie": "^4.1.3",
31
+ "xhs-mp-compiler-cli": "^1.2.0-beta.0",
32
+ "xhs-mp-project": "^1.2.0-beta.0",
33
+ "xhs-mp-utils": "^1.2.0-beta.0"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@rollup/plugin-commonjs": "^25.0.7",
@@ -1,46 +0,0 @@
1
- import { Observable } from 'rxjs';
2
- export interface IUploadCheckVersionParams {
3
- version: 'debug' | 'develop';
4
- }
5
- export type ArchType = 'v0' | 'v1' | 'v2';
6
- export type IZipResult = {
7
- type: ArchType;
8
- zipPath: string;
9
- zipSize: number;
10
- root: string;
11
- originSize: number;
12
- };
13
- export type UploadRes = {
14
- cdnFileUrl?: string;
15
- fileId: string;
16
- type: ArchType;
17
- root: string;
18
- };
19
- export declare const uploadFile2: (uploadApi: any, { zipPath, type, root }: {
20
- zipPath: any;
21
- type: any;
22
- root: any;
23
- }, index: number, successCallback?: () => void) => Observable<UploadRes>;
24
- export declare const createUploadTask$: ({ uploadApi, fullPackFileId, packageMap, packageMapV2, appId, version, userDesc, userVersion }: {
25
- uploadApi: any;
26
- fullPackFileId: any;
27
- packageMap: any;
28
- packageMapV2: any;
29
- appId: any;
30
- version: any;
31
- userDesc: any;
32
- userVersion: any;
33
- }) => Observable<unknown>;
34
- export declare const queryTaskDetail$: (uploadApi: any, taskId: string) => Observable<any>;
35
- export declare const submitTask: ({ uploadApi, uploadRes, appId, version, userDesc, userVersion }: {
36
- uploadApi: any;
37
- uploadRes: UploadRes[];
38
- appId: string;
39
- version: IUploadCheckVersionParams['version'];
40
- userDesc?: string | undefined;
41
- userVersion?: string | undefined;
42
- }) => Observable<any>;
43
- type Res = ReturnType<typeof submitTask>;
44
- type GetP<T> = T extends Observable<infer P> ? P : never;
45
- export type FinalRes = GetP<Res>;
46
- export {};