xhs-mp-core 1.1.4 → 1.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/baseApi.d.ts +1 -1
- package/dist/api/uploadApi.d.ts +25 -5
- package/dist/core.d.ts +3 -9
- package/dist/index.js +1 -1
- package/dist/login.d.ts +2 -3
- package/dist/services/baseService.d.ts +49 -4
- package/dist/utils/uuid.d.ts +1 -0
- package/package.json +6 -5
- package/dist/services/rx-utils.d.ts +0 -46
package/dist/api/baseApi.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/dist/api/uploadApi.d.ts
CHANGED
|
@@ -46,10 +46,15 @@ export type IQueryTaskDetail = ILongTaskRoot<{
|
|
|
46
46
|
};
|
|
47
47
|
status: number;
|
|
48
48
|
}>;
|
|
49
|
-
export interface
|
|
49
|
+
export interface IUploadCheckVersionParamsV1 {
|
|
50
50
|
version: 'debug' | 'develop';
|
|
51
51
|
}
|
|
52
|
-
export interface
|
|
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
|
-
|
|
85
|
+
checkUploadAuthV1({ version }: IUploadCheckVersionParamsV1): Promise<any>;
|
|
86
|
+
checkUploadAuthV2(opts: IUploadCheckVersionParamsV2): Promise<any>;
|
|
69
87
|
getUploadToken: (params: TokenRequest) => Promise<TokenResponse>;
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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'
|
|
19
|
-
data?: {
|
|
20
|
-
token?: string;
|
|
21
|
-
};
|
|
16
|
+
type?: 'qrcode';
|
|
22
17
|
};
|
|
23
18
|
export type ILogoutConfig = IVerbose & {};
|
|
24
19
|
export interface ILibFeatures {
|
|
@@ -52,7 +47,6 @@ export type IUploadOpts = IBaseActionOpts & IVerbose & {
|
|
|
52
47
|
export declare class Core {
|
|
53
48
|
private globalConfig;
|
|
54
49
|
private appConfigMap;
|
|
55
|
-
private currentAppConfig;
|
|
56
50
|
private projectMap;
|
|
57
51
|
private compilerMap;
|
|
58
52
|
private logger;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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 S=f(i),v=f(l);const w=()=>({isSit:"false"===process.env.XHS_IS_PROD,isProd:"true"===process.env.XHS_IS_PROD}),k=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:w().isSit?k:"https://business.xiaohongshu.com",CUSTOMER_HOST:w().isSit?x:"https://customer.xiaohongshu.com",CUSTOMER_SERVICE_ID:w().isSit?x.replace(/https?:\/\/customer/,"file://miniapp-open"):"file://miniapp-open.xiaohongshu.com"},_={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`},C=require("crypto");require("net");const I=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 b(e){return e.replace(/\\/g,"/")}const P=b(i.join(a.homedir(),".xhs-mp-cli"));n.ensureDirSync(P);const T=b(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 M 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 U=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 $ extends M{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=U.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}`,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=U.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}`,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 A=(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=v.readFileSync(S.resolve(i)),r=v.statSync(S.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:S.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=A(s,"v1"),h=A(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=A(s,"v1"),d=A(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=function(e){const t=C.createHash("md5");return t.update(e),t.digest("hex")}(e+"#"+t+"#"+s+"#"+h().format("YYYYMMDDHHmm"));return{cliToken:r,nonce:s,appId:e}}getCheckUploadAuthFn(e,t){let s;const r=this.isTokenAuth();if(this.logger.log("Check appid auth..."),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 $(t)}upload(e){return new Promise(((t,s)=>{this.uploadPromise={resolve:t,reject:s},this.doUpload(e)}))}}class V extends M{async generateQrCode(){const e=await this.request({method:"post",url:_.generateQrCode,data:{subsystem:"business"}});return this.handleStatusCode(this.handleHttpStatus(e))}async queryQrCodeStatus(e){const t=await this.request({method:"get",url:_.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:_.session,data:{ticket:e,clientId:y.CUSTOMER_SERVICE_ID}});return this.handleHttpStatus(t).data}async fetchUserInfo(){const e=await this.request({method:"get",url:_.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="qrcode"){if(this.isLogin)this.logger.log("Had Login!!!");else{this.isLogin=!1,this.logger.log("Login...");try{if("qrcode"!==e)throw new Error("暂不支持扫码之外的其他登陆方式");{const e=await this.loginByQrcode();this.userInfo=e}this.isLogin=!0,this.logger.log("Login success")}catch(e){throw this.logger.log("Login fail:",e.message),this.isLogin=!1,this.userInfo=null,e}}}loginByQrcode(){return new Promise(((e,t)=>{this.loginPromise={resolve:e,reject:t};try{this.startPollingSub=this.startPolling().subscribe()}catch(e){console.error(e)}}))}logout(e){"axios"!==e.from&&this.logger.log("Logout..."),this.isLogin=!1,this.userInfo={},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:I(e.zipSize)})));const a=i.reduce(((e,t)=>t.zipSize+e),0)||0;this.previewData.zipSize=I(a)},this.uploadApi=new $(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.projectMap={},this.compilerMap={},this.logger=new s.Logger("[xhs-mp-cli]"),this.globalConfig=z.get("xhs-cli-global-config")||{},this.appConfigMap=z.get("xhs-cli-app-config")||{},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("xhs-cli-global-config",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},z.set("xhs-cli-app-config",this.appConfigMap),this.logger.log("Set app config done",this.appConfigMap)):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)}logout(e){this.loginManager.logout(e)}async preview(e){e.verbose&&this.logger.setVerbose(!0);const t=e.project||{},s=e.buildConfig||{},r=this.getProject(t),o=this.appConfigMap[r.projectAppId];(null==o?void 0:o.token)||this.loginManager.isLogin||await this.login();const i=this.getCompiler(t,s),a=new B({core:this,project:r,compiler:i,logger:this.logger});return await a.preview({entry:e.entry})}async upload(e){e.verbose&&this.logger.setVerbose(!0);const{project:t,buildConfig:s={},version:r,desc:o,progressCallback:i}=e,a=this.getProject(t),n=this.appConfigMap[a.projectAppId];(null==n?void 0:n.token)||this.loginManager.isLogin||await this.login();const l=this.getCompiler(t,s),p=new L({core:this,project:a,compiler:l,logger:this.logger});return await p.upload({userVersion:r,userDesc:o,progressCallback:i})}};
|
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
|
|
28
|
+
private showQrCode;
|
|
29
29
|
private queryQrCodeStatus;
|
|
30
30
|
private doLogin;
|
|
31
31
|
private startPolling;
|
|
32
32
|
private stopPolling;
|
|
33
|
-
login(type
|
|
33
|
+
login(type?: 'qrcode'): 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
|
|
3
|
-
import { Compiler } from
|
|
4
|
-
import EventEmitter from
|
|
5
|
-
import { Core } from
|
|
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 {};
|
package/dist/utils/uuid.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xhs-mp-core",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.0-beta.1",
|
|
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.1",
|
|
32
|
+
"xhs-mp-project": "^1.2.0-beta.1",
|
|
33
|
+
"xhs-mp-utils": "^1.2.0-beta.1"
|
|
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 {};
|