xhs-mp-core 1.0.2 → 1.1.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.
- package/dist/api/baseApi.d.ts +28 -0
- package/dist/api/uploadApi.d.ts +72 -0
- package/dist/api/userApi.d.ts +40 -0
- package/dist/config/constant.config.d.ts +4 -0
- package/dist/config/dir.config.d.ts +2 -0
- package/dist/config/env.config.d.ts +4 -0
- package/dist/config/url.config.d.ts +11 -0
- package/dist/core.d.ts +71 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/login.d.ts +37 -0
- package/dist/services/baseService.d.ts +18 -0
- package/dist/services/preview/preview.d.ts +30 -0
- package/dist/services/rx-utils.d.ts +46 -0
- package/dist/services/upload/upload.d.ts +20 -0
- package/dist/utils/axios.d.ts +1 -0
- package/dist/utils/cookie.d.ts +12 -0
- package/dist/utils/qrcode.d.ts +1 -0
- package/dist/utils/storage.d.ts +13 -0
- package/dist/utils/utils.d.ts +12 -0
- package/dist/utils/uuid.d.ts +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { Core } from '../core';
|
|
4
|
+
interface IRequestOpts {
|
|
5
|
+
method: 'post' | 'get' | 'put' | 'delete';
|
|
6
|
+
url: string;
|
|
7
|
+
data?: {
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
};
|
|
10
|
+
config?: {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare class BaseApi extends EventEmitter {
|
|
15
|
+
core: Core;
|
|
16
|
+
constructor(props: any);
|
|
17
|
+
get axios(): import("axios").AxiosStatic;
|
|
18
|
+
protected getProxyConfig(): false | {
|
|
19
|
+
host: string;
|
|
20
|
+
port: string;
|
|
21
|
+
protocol: string;
|
|
22
|
+
};
|
|
23
|
+
request(opts: IRequestOpts): Promise<import("axios").AxiosResponse<any> | undefined>;
|
|
24
|
+
protected handleHttpStatus(res: any): any;
|
|
25
|
+
protected handleStatusCode(res: any): any;
|
|
26
|
+
protected handleCode(res: any): any;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { TokenRequest, TokenResponse } from 'xhs-mp-utils';
|
|
2
|
+
import { BaseApi } from './baseApi';
|
|
3
|
+
import { Project } from 'xhs-mp-project';
|
|
4
|
+
export interface IBusinessRoot<T> {
|
|
5
|
+
code: number;
|
|
6
|
+
msg: string;
|
|
7
|
+
guid: any;
|
|
8
|
+
success: boolean;
|
|
9
|
+
data: T;
|
|
10
|
+
}
|
|
11
|
+
export interface ILongTaskRoot<T> {
|
|
12
|
+
result: number;
|
|
13
|
+
success: boolean;
|
|
14
|
+
data: T;
|
|
15
|
+
error_code: number;
|
|
16
|
+
}
|
|
17
|
+
export interface IGetUploadTokenData {
|
|
18
|
+
bucket: string;
|
|
19
|
+
expired: number;
|
|
20
|
+
key_prefix: string;
|
|
21
|
+
host: string;
|
|
22
|
+
sign: string;
|
|
23
|
+
}
|
|
24
|
+
export type IGetUploadToken = IBusinessRoot<IGetUploadTokenData>;
|
|
25
|
+
export type ICreateUploadTask = IBusinessRoot<{
|
|
26
|
+
task_id: string;
|
|
27
|
+
}>;
|
|
28
|
+
export type IUploadCheckVersion = IBusinessRoot<{
|
|
29
|
+
can_upload: boolean;
|
|
30
|
+
can_upload_ext_json: boolean;
|
|
31
|
+
show_msg: string;
|
|
32
|
+
upload_app_id: string;
|
|
33
|
+
}>;
|
|
34
|
+
export type IQueryTaskDetail = ILongTaskRoot<{
|
|
35
|
+
id: string;
|
|
36
|
+
finished_count: number;
|
|
37
|
+
total_count: number;
|
|
38
|
+
progress: number;
|
|
39
|
+
result: {
|
|
40
|
+
file_url: any;
|
|
41
|
+
msg: string;
|
|
42
|
+
extra_json: string;
|
|
43
|
+
business_status: any;
|
|
44
|
+
success: boolean;
|
|
45
|
+
code: number;
|
|
46
|
+
};
|
|
47
|
+
status: number;
|
|
48
|
+
}>;
|
|
49
|
+
export interface IUploadCheckVersionParams {
|
|
50
|
+
version: 'debug' | 'develop';
|
|
51
|
+
}
|
|
52
|
+
export interface IUploadPackageParams {
|
|
53
|
+
appId: string;
|
|
54
|
+
version: 'debug' | 'develop';
|
|
55
|
+
fileUrl: string;
|
|
56
|
+
userVersion?: string;
|
|
57
|
+
userDesc?: string;
|
|
58
|
+
packageMap: {
|
|
59
|
+
[key: string]: string;
|
|
60
|
+
};
|
|
61
|
+
packageMapV2?: {
|
|
62
|
+
[key: string]: string;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export declare class UploadApi extends BaseApi {
|
|
66
|
+
project: Project;
|
|
67
|
+
constructor(props: any);
|
|
68
|
+
uploadCheckVersion({ version }: IUploadCheckVersionParams): Promise<any>;
|
|
69
|
+
getUploadToken: (params: TokenRequest) => Promise<TokenResponse>;
|
|
70
|
+
createUploadTask(opts: IUploadPackageParams): Promise<any>;
|
|
71
|
+
queryTaskDetail(taskId: string): Promise<any>;
|
|
72
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BaseApi } from './baseApi';
|
|
2
|
+
export interface IBaseRoot<T> {
|
|
3
|
+
alertMsg: string;
|
|
4
|
+
data: T;
|
|
5
|
+
errorCode: any;
|
|
6
|
+
errorMsg: any;
|
|
7
|
+
statusCode: number;
|
|
8
|
+
success: boolean;
|
|
9
|
+
traceLogId: string;
|
|
10
|
+
}
|
|
11
|
+
export type IGenerateQrCodeData = IBaseRoot<{
|
|
12
|
+
qrId: string;
|
|
13
|
+
qrUrl: string;
|
|
14
|
+
}>;
|
|
15
|
+
export interface IQueryQrCodeStatusData {
|
|
16
|
+
authToken: null | string;
|
|
17
|
+
avatar: null | string;
|
|
18
|
+
customerUserType: null | string;
|
|
19
|
+
status: number;
|
|
20
|
+
ticket: null | string;
|
|
21
|
+
userId: null | string;
|
|
22
|
+
}
|
|
23
|
+
export type IQueryQrCodeStatus = IBaseRoot<IQueryQrCodeStatusData>;
|
|
24
|
+
export type ILoginData = Omit<IQueryQrCodeStatusData, 'status'>;
|
|
25
|
+
export interface IBusinessRoot {
|
|
26
|
+
code: number;
|
|
27
|
+
msg: string;
|
|
28
|
+
guid: any;
|
|
29
|
+
success: boolean;
|
|
30
|
+
data: {
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export type IGetUserInfo = IBusinessRoot;
|
|
35
|
+
export declare class UserApi extends BaseApi {
|
|
36
|
+
generateQrCode(): Promise<any>;
|
|
37
|
+
queryQrCodeStatus(qrId: string): Promise<any>;
|
|
38
|
+
login(ticket: string): Promise<any>;
|
|
39
|
+
fetchUserInfo(): Promise<any>;
|
|
40
|
+
}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface IVerbose {
|
|
2
|
+
verbose?: boolean;
|
|
3
|
+
from?: 'cli' | 'code' | 'axios';
|
|
4
|
+
}
|
|
5
|
+
export interface IGlobalConfig {
|
|
6
|
+
proxy?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface IAppConfig {
|
|
9
|
+
appId: string;
|
|
10
|
+
config: {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface IAppConfigMap {
|
|
15
|
+
[appId: string]: IAppConfig;
|
|
16
|
+
}
|
|
17
|
+
export type ILoginConfig = IVerbose & {
|
|
18
|
+
type?: 'qrcode' | 'token';
|
|
19
|
+
data?: {
|
|
20
|
+
token?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export type ILogoutConfig = IVerbose & {};
|
|
24
|
+
export interface ILibFeatures {
|
|
25
|
+
supportV2?: boolean;
|
|
26
|
+
supportVdom?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface IBaseActionOpts {
|
|
29
|
+
project: {
|
|
30
|
+
projectPath: string;
|
|
31
|
+
watch?: boolean;
|
|
32
|
+
};
|
|
33
|
+
buildConfig?: {
|
|
34
|
+
compileDir?: string;
|
|
35
|
+
nodeJsPath?: string;
|
|
36
|
+
mpDevJsonPath?: string;
|
|
37
|
+
libFeatures?: ILibFeatures;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export type IPreivewOpts = IBaseActionOpts & IVerbose & {
|
|
41
|
+
entry?: {
|
|
42
|
+
path: string;
|
|
43
|
+
query?: string;
|
|
44
|
+
launchMode?: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export type IUploadOpts = IBaseActionOpts & IVerbose & {
|
|
48
|
+
version: string;
|
|
49
|
+
desc: string;
|
|
50
|
+
progressCallback?: any;
|
|
51
|
+
};
|
|
52
|
+
export declare class Core {
|
|
53
|
+
private globalConfig;
|
|
54
|
+
private appConfigMap;
|
|
55
|
+
private currentAppConfig;
|
|
56
|
+
private projectMap;
|
|
57
|
+
private compilerMap;
|
|
58
|
+
private logger;
|
|
59
|
+
private loginManager;
|
|
60
|
+
constructor();
|
|
61
|
+
setGlobalConfig(config?: IGlobalConfig): void;
|
|
62
|
+
getGlobalConfig(): IGlobalConfig;
|
|
63
|
+
setAppConfig(appConfig?: IAppConfig): void;
|
|
64
|
+
getAppConfig(appId: any): IAppConfig;
|
|
65
|
+
private getProject;
|
|
66
|
+
private getCompiler;
|
|
67
|
+
login(opts?: ILoginConfig): Promise<void>;
|
|
68
|
+
logout(opts: ILogoutConfig): void;
|
|
69
|
+
preview(opts: IPreivewOpts): Promise<unknown>;
|
|
70
|
+
upload(opts: IUploadOpts): Promise<unknown>;
|
|
71
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("xhs-mp-compiler"),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})}};
|
package/dist/login.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type IUserInfo = {
|
|
2
|
+
nickName: string;
|
|
3
|
+
avatar: string;
|
|
4
|
+
userId: string;
|
|
5
|
+
desc: string;
|
|
6
|
+
gender: number;
|
|
7
|
+
userInfoData?: any;
|
|
8
|
+
};
|
|
9
|
+
export interface IUserInfoData {
|
|
10
|
+
nick: string;
|
|
11
|
+
img: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class LoginManager {
|
|
14
|
+
private qrUrl;
|
|
15
|
+
private userApi;
|
|
16
|
+
private qrCodeStatusData;
|
|
17
|
+
private startPollingSub;
|
|
18
|
+
private loginPromise;
|
|
19
|
+
private logger;
|
|
20
|
+
private _isLogin;
|
|
21
|
+
private _userInfo;
|
|
22
|
+
get isLogin(): any;
|
|
23
|
+
set isLogin(isLogin: any);
|
|
24
|
+
get userInfo(): any;
|
|
25
|
+
set userInfo(info: any);
|
|
26
|
+
constructor(props: any);
|
|
27
|
+
private transformUserInfo;
|
|
28
|
+
showQrCode(): void;
|
|
29
|
+
private queryQrCodeStatus;
|
|
30
|
+
private doLogin;
|
|
31
|
+
private startPolling;
|
|
32
|
+
private stopPolling;
|
|
33
|
+
login(type: 'qrcode' | 'token', data: any): Promise<void>;
|
|
34
|
+
loginByQrcode(): Promise<unknown>;
|
|
35
|
+
loginByToken(token: any): Promise<void>;
|
|
36
|
+
logout(opts: any): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Project } from "xhs-mp-project";
|
|
3
|
+
import { Compiler } from "xhs-mp-compiler";
|
|
4
|
+
import EventEmitter from "events";
|
|
5
|
+
import { Core } from "../core";
|
|
6
|
+
export interface IBaseServiceProps {
|
|
7
|
+
core: Core;
|
|
8
|
+
project: Project;
|
|
9
|
+
compiler: Compiler;
|
|
10
|
+
logger: any;
|
|
11
|
+
}
|
|
12
|
+
export declare class BaseService extends EventEmitter {
|
|
13
|
+
core: Core;
|
|
14
|
+
project: Project;
|
|
15
|
+
compiler: Compiler;
|
|
16
|
+
logger: any;
|
|
17
|
+
constructor(props: IBaseServiceProps);
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BaseService, IBaseServiceProps } from '../baseService';
|
|
2
|
+
import { UploadApi } from '../../api/uploadApi';
|
|
3
|
+
type IPreviewProps = IBaseServiceProps & {};
|
|
4
|
+
interface IPreviewData {
|
|
5
|
+
entry?: {
|
|
6
|
+
path: string;
|
|
7
|
+
query?: string;
|
|
8
|
+
launchMode?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare class Preview extends BaseService {
|
|
12
|
+
uploadApi: UploadApi;
|
|
13
|
+
taskSubscription: any;
|
|
14
|
+
progressData: {
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
};
|
|
17
|
+
previewData: {
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
};
|
|
20
|
+
previewPromise: {
|
|
21
|
+
resolve: (value: unknown) => void;
|
|
22
|
+
reject: (reason?: any) => void;
|
|
23
|
+
};
|
|
24
|
+
constructor(props: IPreviewProps);
|
|
25
|
+
preview(opts: IPreviewData): Promise<unknown>;
|
|
26
|
+
doPreview(opts: IPreviewData): void;
|
|
27
|
+
showQrCode(qrUrl: any): void;
|
|
28
|
+
calcSize: (zipSizeInfo: any) => void;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
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 {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { UploadApi } from '../../api/uploadApi';
|
|
2
|
+
import { BaseService, IBaseServiceProps } from '../baseService';
|
|
3
|
+
type IUploaderProps = IBaseServiceProps & {};
|
|
4
|
+
interface IUploadData {
|
|
5
|
+
userVersion: string;
|
|
6
|
+
userDesc: string;
|
|
7
|
+
progressCallback?: any;
|
|
8
|
+
}
|
|
9
|
+
export declare class Uploader extends BaseService {
|
|
10
|
+
taskSubscription: any;
|
|
11
|
+
uploadApi: UploadApi;
|
|
12
|
+
uploadPromise: {
|
|
13
|
+
resolve: (value: unknown) => void;
|
|
14
|
+
reject: (reason?: any) => void;
|
|
15
|
+
};
|
|
16
|
+
constructor(props: IUploaderProps);
|
|
17
|
+
upload(uploadData: IUploadData): Promise<unknown>;
|
|
18
|
+
private doUpload;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getAxios(core: any): import("axios").AxiosStatic;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare class CookieTool {
|
|
2
|
+
cookieJar: any;
|
|
3
|
+
cookiePath: string;
|
|
4
|
+
constructor();
|
|
5
|
+
getSerializeData(): {};
|
|
6
|
+
save(): void;
|
|
7
|
+
clear(): void;
|
|
8
|
+
set(res: any): void;
|
|
9
|
+
get(url: any): any;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: CookieTool;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const genDeeplink: (project: any, entry: {} | undefined, qrcode: any, logger: any) => Promise<any>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare class Storage {
|
|
2
|
+
jsonPath: string;
|
|
3
|
+
data: {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
};
|
|
6
|
+
private timer;
|
|
7
|
+
constructor();
|
|
8
|
+
get(key: any): any;
|
|
9
|
+
set(key: any, val: any): void;
|
|
10
|
+
refresh(): void;
|
|
11
|
+
}
|
|
12
|
+
declare const _default: Storage;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const throttle: (fn: any, wait?: number) => (...args: any[]) => void;
|
|
2
|
+
export declare const debounce: (func: any, wait?: number) => (...args: any[]) => void;
|
|
3
|
+
export declare const fileSize: (size: number) => string;
|
|
4
|
+
export declare function getMd5(str: any): any;
|
|
5
|
+
export declare function getType(object: any): string;
|
|
6
|
+
export declare function normalizePath(str: any): any;
|
|
7
|
+
export declare const compareVersion: (v1Str: string, v2Str: string) => number;
|
|
8
|
+
export declare function picker<T>(obj: any, pick: string[]): T;
|
|
9
|
+
export declare const formatPath: (pathStr?: string) => string;
|
|
10
|
+
export declare const toUnixPath: (pathStr?: string) => string;
|
|
11
|
+
export declare const unixJoin: (...paths: string[]) => string;
|
|
12
|
+
export declare const unixResolve: (...paths: string[]) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function guid(): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xhs-mp-core",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"author": "",
|
|
15
15
|
"license": "ISC",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"xhs-mp-compiler": "^1.0
|
|
18
|
-
"xhs-mp-project": "^1.0
|
|
19
|
-
"xhs-mp-utils": "^1.0
|
|
17
|
+
"xhs-mp-compiler": "^1.1.0",
|
|
18
|
+
"xhs-mp-project": "^1.1.0",
|
|
19
|
+
"xhs-mp-utils": "^1.1.0",
|
|
20
20
|
"archiver": "^7.0.1",
|
|
21
21
|
"axios": "^0.21.4",
|
|
22
22
|
"debug": "^4.3.4",
|