@ningboyz/wxmp 1.0.2 → 1.0.3
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/es/client/wxClient.d.ts +15 -0
- package/es/client/wxClient.js +20 -0
- package/es/index.d.ts +4 -0
- package/es/index.js +9 -0
- package/es/request/wxRequest.d.ts +26 -0
- package/es/request/wxRequest.js +108 -0
- package/es/types.d.ts +73 -0
- package/es/types.js +23 -0
- package/package.json +15 -2
- package/.prettierrc +0 -15
- package/src/client/wxClient.ts +0 -30
- package/src/index.ts +0 -19
- package/src/request/wxRequest.ts +0 -205
- package/src/types.ts +0 -83
- package/tsconfig.json +0 -22
- package/vite.config.ts +0 -32
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TCore } from '@ningboyz/types';
|
|
2
|
+
import { IWxConfig, IWxLoginParams } from '../types';
|
|
3
|
+
declare class WxClient {
|
|
4
|
+
private wxRequest;
|
|
5
|
+
private constructor();
|
|
6
|
+
static create: (config: IWxConfig) => WxClient;
|
|
7
|
+
/**
|
|
8
|
+
* 微信登录
|
|
9
|
+
* @param params
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
login(params: IWxLoginParams): Promise<import('@ningboyz/types/src/response').IResponse<TCore.IUserResponse[]>>;
|
|
13
|
+
}
|
|
14
|
+
declare const createWxClient: (config: IWxConfig) => WxClient;
|
|
15
|
+
export { type WxClient, createWxClient };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createWxRequest as s } from "../request/wxRequest.js";
|
|
2
|
+
class t {
|
|
3
|
+
wxRequest;
|
|
4
|
+
constructor(e) {
|
|
5
|
+
this.wxRequest = s(e);
|
|
6
|
+
}
|
|
7
|
+
static create = (e) => new t(e);
|
|
8
|
+
/**
|
|
9
|
+
* 微信登录
|
|
10
|
+
* @param params
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
login(e) {
|
|
14
|
+
return this.wxRequest.post("/gapi/core/tuser/verifyd2/weixin", void 0, e);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const c = (r) => t.create(r);
|
|
18
|
+
export {
|
|
19
|
+
c as createWxClient
|
|
20
|
+
};
|
package/es/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { WxClient, createWxClient } from './client/wxClient';
|
|
2
|
+
import { WxRequest, createWxRequest } from './request/wxRequest';
|
|
3
|
+
import { IWxConfig, IWxInternalRequestConfig, IWxLoginParams, IWxQueryParams, IWxResponse, TWxConfig, TWxInterceptorsRequest, TWxInterceptorsResponse, TWxLoginParams } from './types';
|
|
4
|
+
export { type WxClient, createWxClient, type WxRequest, createWxRequest, type IWxConfig, type IWxInternalRequestConfig, type IWxLoginParams, type IWxQueryParams, type IWxResponse, type TWxInterceptorsRequest, type TWxInterceptorsResponse, TWxConfig, TWxLoginParams };
|
package/es/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createWxClient as o } from "./client/wxClient.js";
|
|
2
|
+
import { createWxRequest as x } from "./request/wxRequest.js";
|
|
3
|
+
import { TWxConfig as f, TWxLoginParams as m } from "./types.js";
|
|
4
|
+
export {
|
|
5
|
+
f as TWxConfig,
|
|
6
|
+
m as TWxLoginParams,
|
|
7
|
+
o as createWxClient,
|
|
8
|
+
x as createWxRequest
|
|
9
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TResp } from '@ningboyz/types';
|
|
2
|
+
import { IWxConfig, IWxQueryParams } from '../types';
|
|
3
|
+
declare class WxRequest {
|
|
4
|
+
private config;
|
|
5
|
+
private constructor();
|
|
6
|
+
static create(config: IWxConfig): WxRequest;
|
|
7
|
+
/**
|
|
8
|
+
* 表单提交。body 字段名 params,值是 JSON 字符串,对应 apis 里的 post。
|
|
9
|
+
*/
|
|
10
|
+
post<T>(url: string, querys?: IWxQueryParams, params?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
|
|
11
|
+
/**
|
|
12
|
+
* JSON 提交,对应 apis 里的 postJson。国密加密接口请走此方法。
|
|
13
|
+
*/
|
|
14
|
+
postJson<T>(url: string, querys?: IWxQueryParams, params?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
|
|
15
|
+
get<T>(url: string, querys?: IWxQueryParams, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
|
|
16
|
+
private send;
|
|
17
|
+
private handleSuccess;
|
|
18
|
+
private tryHandleSessionExpired;
|
|
19
|
+
private getMiniProgramWx;
|
|
20
|
+
private createRequestUrl;
|
|
21
|
+
private createAuthQuerys;
|
|
22
|
+
private createHeader;
|
|
23
|
+
private toLowerCase;
|
|
24
|
+
}
|
|
25
|
+
declare const createWxRequest: (config: IWxConfig) => WxRequest;
|
|
26
|
+
export { type WxRequest, createWxRequest };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { TResp as f } from "@ningboyz/types";
|
|
2
|
+
import s from "lodash";
|
|
3
|
+
import { REQUEST_TIMEOUT_MILLISECONDS as p } from "../types.js";
|
|
4
|
+
const T = 200, N = 300, m = "application/json", E = "application/x-www-form-urlencoded";
|
|
5
|
+
class u {
|
|
6
|
+
config;
|
|
7
|
+
constructor(e) {
|
|
8
|
+
this.config = e;
|
|
9
|
+
}
|
|
10
|
+
static create(e) {
|
|
11
|
+
return new u(e);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 表单提交。body 字段名 params,值是 JSON 字符串,对应 apis 里的 post。
|
|
15
|
+
*/
|
|
16
|
+
post(e, i, t, r) {
|
|
17
|
+
const n = s.isNil(t) ? void 0 : { params: JSON.stringify(t) }, o = this.createHeader(s.isNil(t) ? void 0 : E, r);
|
|
18
|
+
return this.send("POST", e, i, n, o);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* JSON 提交,对应 apis 里的 postJson。国密加密接口请走此方法。
|
|
22
|
+
*/
|
|
23
|
+
postJson(e, i, t, r) {
|
|
24
|
+
const n = this.createHeader(m, r);
|
|
25
|
+
return this.send("POST", e, i, t, n);
|
|
26
|
+
}
|
|
27
|
+
get(e, i, t) {
|
|
28
|
+
const r = this.createHeader(void 0, t);
|
|
29
|
+
return this.send("GET", e, i, void 0, r);
|
|
30
|
+
}
|
|
31
|
+
send(e, i, t, r, n) {
|
|
32
|
+
return (async () => {
|
|
33
|
+
let o = {
|
|
34
|
+
url: i,
|
|
35
|
+
method: e,
|
|
36
|
+
querys: t,
|
|
37
|
+
data: r,
|
|
38
|
+
header: n
|
|
39
|
+
};
|
|
40
|
+
s.isNil(this.config.interceptorsRequest) || (o = await this.config.interceptorsRequest(o));
|
|
41
|
+
const a = this.createRequestUrl(o.url, o.querys), h = this.config.timeout ?? p;
|
|
42
|
+
return await new Promise((d) => {
|
|
43
|
+
try {
|
|
44
|
+
this.getMiniProgramWx().request({
|
|
45
|
+
url: a,
|
|
46
|
+
method: o.method,
|
|
47
|
+
data: o.data,
|
|
48
|
+
header: o.header,
|
|
49
|
+
timeout: h,
|
|
50
|
+
success: (c) => {
|
|
51
|
+
this.handleSuccess(c, o).then(d);
|
|
52
|
+
},
|
|
53
|
+
fail: (c) => {
|
|
54
|
+
d(f.TResponse.toError(c.errMsg));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
} catch (c) {
|
|
58
|
+
const l = c instanceof Error ? c.message : "请求失败";
|
|
59
|
+
d(f.TResponse.toError(l));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
})();
|
|
63
|
+
}
|
|
64
|
+
async handleSuccess(e, i) {
|
|
65
|
+
if (e.statusCode < T || e.statusCode >= N)
|
|
66
|
+
return f.TResponse.toError(`请求失败,状态码 ${e.statusCode}`);
|
|
67
|
+
let t = {
|
|
68
|
+
data: e.data,
|
|
69
|
+
statusCode: e.statusCode,
|
|
70
|
+
config: i
|
|
71
|
+
};
|
|
72
|
+
return s.isNil(this.config.interceptorsResponse) || (t = await this.config.interceptorsResponse(t)), this.tryHandleSessionExpired(t.data), t.data;
|
|
73
|
+
}
|
|
74
|
+
tryHandleSessionExpired(e) {
|
|
75
|
+
if (s.isNil(this.config.loseTokenState) || s.isNil(this.config.sessionExpiredErrorKey) || s.isNil(e) || typeof e != "object")
|
|
76
|
+
return;
|
|
77
|
+
e.ERRORKEY === this.config.sessionExpiredErrorKey && this.config.loseTokenState();
|
|
78
|
+
}
|
|
79
|
+
getMiniProgramWx() {
|
|
80
|
+
const e = globalThis.wx;
|
|
81
|
+
if (s.isNil(e))
|
|
82
|
+
throw new Error("当前环境不存在微信小程序 wx");
|
|
83
|
+
return e;
|
|
84
|
+
}
|
|
85
|
+
createRequestUrl(e, i) {
|
|
86
|
+
const t = this.config.baseURL.endsWith("/") ? this.config.baseURL.slice(0, -1) : this.config.baseURL, r = e.startsWith("/") ? e : `/${e}`, n = {
|
|
87
|
+
r: Date.now(),
|
|
88
|
+
...this.createAuthQuerys(),
|
|
89
|
+
...this.toLowerCase(i)
|
|
90
|
+
}, o = Object.entries(n).filter(([, a]) => !s.isNil(a)).map(([a, h]) => `${encodeURIComponent(a)}=${encodeURIComponent(String(h))}`).join("&");
|
|
91
|
+
return o.length === 0 ? `${t}${r}` : `${t}${r}?${o}`;
|
|
92
|
+
}
|
|
93
|
+
createAuthQuerys() {
|
|
94
|
+
const e = {};
|
|
95
|
+
return !s.isNil(this.config.whobuild) && this.config.whobuild !== 0 && (e.whobuild = this.config.whobuild), !s.isNil(this.config.userIndx) && this.config.userIndx !== 0 && (e.userindx = this.config.userIndx), e;
|
|
96
|
+
}
|
|
97
|
+
createHeader(e, i) {
|
|
98
|
+
const t = {};
|
|
99
|
+
return s.isNil(e) || (t["content-type"] = e), !s.isNil(this.config.usrtoken) && this.config.usrtoken !== "" && (t.usrtoken = this.config.usrtoken), !s.isNil(this.config.dbConfig) && this.config.dbConfig !== "" && (t.dbconfig = this.config.dbConfig), s.isNil(i) || Object.assign(t, i), t;
|
|
100
|
+
}
|
|
101
|
+
toLowerCase(e) {
|
|
102
|
+
return s.isNil(e) ? {} : s.mapKeys(e, (i, t) => t.toLowerCase());
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const C = (g) => u.create(g);
|
|
106
|
+
export {
|
|
107
|
+
C as createWxRequest
|
|
108
|
+
};
|
package/es/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
declare const REQUEST_TIMEOUT_MILLISECONDS = 60000;
|
|
2
|
+
export interface IWxQueryParams {
|
|
3
|
+
[key: string]: string | number | boolean | null | undefined;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 请求拦截入参/出参(对应 Web axios InternalAxiosRequestConfig)。
|
|
7
|
+
* 国密等可在此改 data、header,并挂 gmSm4KeyHex。
|
|
8
|
+
*/
|
|
9
|
+
export interface IWxInternalRequestConfig {
|
|
10
|
+
/** 业务 path,不含 baseURL / query */
|
|
11
|
+
url: string;
|
|
12
|
+
method: "GET" | "POST";
|
|
13
|
+
querys?: IWxQueryParams;
|
|
14
|
+
data?: object;
|
|
15
|
+
header: Record<string, string>;
|
|
16
|
+
/** 国密会话 SM4,供响应拦截解密 */
|
|
17
|
+
gmSm4KeyHex?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 响应拦截入参/出参(对应 Web axios AxiosResponse)。
|
|
21
|
+
*/
|
|
22
|
+
export interface IWxResponse<T = unknown> {
|
|
23
|
+
data: T;
|
|
24
|
+
statusCode: number;
|
|
25
|
+
config: IWxInternalRequestConfig;
|
|
26
|
+
}
|
|
27
|
+
export type TWxInterceptorsRequest = (request: IWxInternalRequestConfig) => IWxInternalRequestConfig | Promise<IWxInternalRequestConfig>;
|
|
28
|
+
export type TWxInterceptorsResponse = (response: IWxResponse) => IWxResponse | Promise<IWxResponse>;
|
|
29
|
+
export interface IWxConfig {
|
|
30
|
+
baseURL: string;
|
|
31
|
+
timeout?: number;
|
|
32
|
+
whobuild?: number;
|
|
33
|
+
userIndx?: number;
|
|
34
|
+
usrtoken?: string;
|
|
35
|
+
dbConfig?: string;
|
|
36
|
+
/**
|
|
37
|
+
* 请求拦截(对齐 Web createRequest 的 interceptorsRequest)。
|
|
38
|
+
* 在内置鉴权 query/header 组装之后、真正 wx.request 之前调用。
|
|
39
|
+
*/
|
|
40
|
+
interceptorsRequest?: TWxInterceptorsRequest;
|
|
41
|
+
/**
|
|
42
|
+
* 响应拦截(对齐 Web createRequest 的 interceptorsResponse)。
|
|
43
|
+
* 在 HTTP 成功拿到 body 之后、返回给业务之前调用。
|
|
44
|
+
*/
|
|
45
|
+
interceptorsResponse?: TWxInterceptorsResponse;
|
|
46
|
+
/** 会话过期时回调(对齐 Web loseTokenState,按 ERRORKEY 判断) */
|
|
47
|
+
loseTokenState?: () => void;
|
|
48
|
+
/** 与 loseTokenState 配合;不传则不根据 ERRORKEY 踢登录 */
|
|
49
|
+
sessionExpiredErrorKey?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare class TWxConfig implements IWxConfig {
|
|
52
|
+
baseURL: string;
|
|
53
|
+
timeout: number;
|
|
54
|
+
whobuild: number;
|
|
55
|
+
userIndx: number;
|
|
56
|
+
usrtoken: string;
|
|
57
|
+
dbConfig: string;
|
|
58
|
+
interceptorsRequest?: TWxInterceptorsRequest;
|
|
59
|
+
interceptorsResponse?: TWxInterceptorsResponse;
|
|
60
|
+
loseTokenState?: () => void;
|
|
61
|
+
sessionExpiredErrorKey?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface IWxLoginParams {
|
|
64
|
+
code: string;
|
|
65
|
+
encryptedData: string;
|
|
66
|
+
iv: string;
|
|
67
|
+
}
|
|
68
|
+
export declare class TWxLoginParams implements IWxLoginParams {
|
|
69
|
+
code: string;
|
|
70
|
+
encryptedData: string;
|
|
71
|
+
iv: string;
|
|
72
|
+
}
|
|
73
|
+
export { REQUEST_TIMEOUT_MILLISECONDS };
|
package/es/types.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const o = 6e4;
|
|
2
|
+
class s {
|
|
3
|
+
baseURL = "";
|
|
4
|
+
timeout = 6e4;
|
|
5
|
+
whobuild = 0;
|
|
6
|
+
userIndx = 0;
|
|
7
|
+
usrtoken = "";
|
|
8
|
+
dbConfig = "";
|
|
9
|
+
interceptorsRequest = void 0;
|
|
10
|
+
interceptorsResponse = void 0;
|
|
11
|
+
loseTokenState = void 0;
|
|
12
|
+
sessionExpiredErrorKey = void 0;
|
|
13
|
+
}
|
|
14
|
+
class i {
|
|
15
|
+
code = "";
|
|
16
|
+
encryptedData = "";
|
|
17
|
+
iv = "";
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
o as REQUEST_TIMEOUT_MILLISECONDS,
|
|
21
|
+
s as TWxConfig,
|
|
22
|
+
i as TWxLoginParams
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ningboyz/wxmp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "宁波甬政微信小程序库",
|
|
6
6
|
"author": "nbyt-syq",
|
|
7
7
|
"license": "ISC",
|
|
8
8
|
"keywords": [],
|
|
9
|
-
"
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./es/index.d.ts",
|
|
12
|
+
"import": "./es/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./es/*": "./es/*",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"main": "es/index.js",
|
|
18
|
+
"types": "es/index.d.ts",
|
|
19
|
+
"miniprogram": "es",
|
|
20
|
+
"files": [
|
|
21
|
+
"es"
|
|
22
|
+
],
|
|
10
23
|
"scripts": {
|
|
11
24
|
"build": "vite build",
|
|
12
25
|
"prettier": "prettier --config ./.prettierrc --write \"./**/*.{ts,tsx}\" "
|
package/.prettierrc
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"printWidth": 200,
|
|
3
|
-
"tabWidth": 2,
|
|
4
|
-
"useTabs": false,
|
|
5
|
-
"semi": true,
|
|
6
|
-
"singleQuote": false,
|
|
7
|
-
"trailingComma": "none",
|
|
8
|
-
"bracketSpacing": true,
|
|
9
|
-
"bracketSameLine": true,
|
|
10
|
-
"arrowParens": "always",
|
|
11
|
-
"htmlWhitespaceSensitivity": "ignore",
|
|
12
|
-
"vueIndentScriptAndStyle": false,
|
|
13
|
-
"endOfLine": "auto",
|
|
14
|
-
"singleAttributePerLine": false
|
|
15
|
-
}
|
package/src/client/wxClient.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { TCore } from "@ningboyz/types";
|
|
2
|
-
import { WxRequest, createWxRequest } from "../request/wxRequest";
|
|
3
|
-
import { IWxConfig, IWxLoginParams } from "../types";
|
|
4
|
-
|
|
5
|
-
class WxClient {
|
|
6
|
-
private wxRequest: WxRequest;
|
|
7
|
-
|
|
8
|
-
private constructor(config: IWxConfig) {
|
|
9
|
-
this.wxRequest = createWxRequest(config);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
public static create = (config: IWxConfig): WxClient => {
|
|
13
|
-
return new WxClient(config);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 微信登录
|
|
18
|
-
* @param params
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
public login(params: IWxLoginParams) {
|
|
22
|
-
return this.wxRequest.post<TCore.IUserResponse[]>("/gapi/core/tuser/verifyd2/weixin", undefined, params);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const createWxClient = (config: IWxConfig): WxClient => {
|
|
27
|
-
return WxClient.create(config);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export { type WxClient, createWxClient };
|
package/src/index.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { WxClient, createWxClient } from "./client/wxClient";
|
|
2
|
-
import { WxRequest, createWxRequest } from "./request/wxRequest";
|
|
3
|
-
import { IWxConfig, IWxInternalRequestConfig, IWxLoginParams, IWxQueryParams, IWxResponse, TWxConfig, TWxInterceptorsRequest, TWxInterceptorsResponse, TWxLoginParams } from "./types";
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
type WxClient,
|
|
7
|
-
createWxClient,
|
|
8
|
-
type WxRequest,
|
|
9
|
-
createWxRequest,
|
|
10
|
-
type IWxConfig,
|
|
11
|
-
type IWxInternalRequestConfig,
|
|
12
|
-
type IWxLoginParams,
|
|
13
|
-
type IWxQueryParams,
|
|
14
|
-
type IWxResponse,
|
|
15
|
-
type TWxInterceptorsRequest,
|
|
16
|
-
type TWxInterceptorsResponse,
|
|
17
|
-
TWxConfig,
|
|
18
|
-
TWxLoginParams
|
|
19
|
-
};
|
package/src/request/wxRequest.ts
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { TResp } from "@ningboyz/types";
|
|
2
|
-
import _ from "lodash";
|
|
3
|
-
import { IWxConfig, IWxInternalRequestConfig, IWxQueryParams, IWxResponse, REQUEST_TIMEOUT_MILLISECONDS } from "../types";
|
|
4
|
-
|
|
5
|
-
const HTTP_STATUS_MIN = 200;
|
|
6
|
-
const HTTP_STATUS_MAX = 300;
|
|
7
|
-
const CONTENT_TYPE_JSON = "application/json";
|
|
8
|
-
const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
|
|
9
|
-
|
|
10
|
-
interface IWxRequestFail {
|
|
11
|
-
errMsg: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface IWxRequestSuccess<T> {
|
|
15
|
-
data: T;
|
|
16
|
-
statusCode: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface IWxRequestOption<T> {
|
|
20
|
-
url: string;
|
|
21
|
-
method: "GET" | "POST";
|
|
22
|
-
data?: object | string;
|
|
23
|
-
header: Record<string, string>;
|
|
24
|
-
timeout: number;
|
|
25
|
-
success: (result: IWxRequestSuccess<T>) => void;
|
|
26
|
-
fail: (error: IWxRequestFail) => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface IMiniProgramWx {
|
|
30
|
-
request: <T>(option: IWxRequestOption<T>) => void;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class WxRequest {
|
|
34
|
-
private config: IWxConfig;
|
|
35
|
-
|
|
36
|
-
private constructor(config: IWxConfig) {
|
|
37
|
-
this.config = config;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public static create(config: IWxConfig): WxRequest {
|
|
41
|
-
return new WxRequest(config);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 表单提交。body 字段名 params,值是 JSON 字符串,对应 apis 里的 post。
|
|
46
|
-
*/
|
|
47
|
-
public post<T>(url: string, querys?: IWxQueryParams, params?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>> {
|
|
48
|
-
const data = _.isNil(params) ? void 0 : { params: JSON.stringify(params) };
|
|
49
|
-
const header = this.createHeader(_.isNil(params) ? void 0 : CONTENT_TYPE_FORM, headers);
|
|
50
|
-
return this.send<T>("POST", url, querys, data, header);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* JSON 提交,对应 apis 里的 postJson。国密加密接口请走此方法。
|
|
55
|
-
*/
|
|
56
|
-
public postJson<T>(url: string, querys?: IWxQueryParams, params?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>> {
|
|
57
|
-
const header = this.createHeader(CONTENT_TYPE_JSON, headers);
|
|
58
|
-
return this.send<T>("POST", url, querys, params, header);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public get<T>(url: string, querys?: IWxQueryParams, headers?: Record<string, string>): Promise<TResp.IResponse<T>> {
|
|
62
|
-
const header = this.createHeader(void 0, headers);
|
|
63
|
-
return this.send<T>("GET", url, querys, void 0, header);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private send<T>(method: "GET" | "POST", url: string, querys: IWxQueryParams | undefined, data: object | undefined, header: Record<string, string>): Promise<TResp.IResponse<T>> {
|
|
67
|
-
return (async () => {
|
|
68
|
-
let requestConfig: IWxInternalRequestConfig = {
|
|
69
|
-
url,
|
|
70
|
-
method,
|
|
71
|
-
querys,
|
|
72
|
-
data,
|
|
73
|
-
header
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
if (!_.isNil(this.config.interceptorsRequest)) {
|
|
77
|
-
requestConfig = await this.config.interceptorsRequest(requestConfig);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const requestUrl = this.createRequestUrl(requestConfig.url, requestConfig.querys);
|
|
81
|
-
const timeout = this.config.timeout ?? REQUEST_TIMEOUT_MILLISECONDS;
|
|
82
|
-
|
|
83
|
-
return await new Promise<TResp.IResponse<T>>((resolve) => {
|
|
84
|
-
try {
|
|
85
|
-
this.getMiniProgramWx().request<TResp.IResponse<T>>({
|
|
86
|
-
url: requestUrl,
|
|
87
|
-
method: requestConfig.method,
|
|
88
|
-
data: requestConfig.data,
|
|
89
|
-
header: requestConfig.header,
|
|
90
|
-
timeout,
|
|
91
|
-
success: (result) => {
|
|
92
|
-
void this.handleSuccess<T>(result, requestConfig).then(resolve);
|
|
93
|
-
},
|
|
94
|
-
fail: (error) => {
|
|
95
|
-
resolve(TResp.TResponse.toError(error.errMsg));
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
} catch (error) {
|
|
99
|
-
const message = error instanceof Error ? error.message : "请求失败";
|
|
100
|
-
resolve(TResp.TResponse.toError(message));
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
})();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private async handleSuccess<T>(result: IWxRequestSuccess<TResp.IResponse<T>>, requestConfig: IWxInternalRequestConfig): Promise<TResp.IResponse<T>> {
|
|
107
|
-
if (result.statusCode < HTTP_STATUS_MIN || result.statusCode >= HTTP_STATUS_MAX) {
|
|
108
|
-
return TResp.TResponse.toError(`请求失败,状态码 ${result.statusCode}`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let response: IWxResponse = {
|
|
112
|
-
data: result.data,
|
|
113
|
-
statusCode: result.statusCode,
|
|
114
|
-
config: requestConfig
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
if (!_.isNil(this.config.interceptorsResponse)) {
|
|
118
|
-
response = await this.config.interceptorsResponse(response);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
this.tryHandleSessionExpired(response.data);
|
|
122
|
-
|
|
123
|
-
return response.data as TResp.IResponse<T>;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private tryHandleSessionExpired(data: unknown): void {
|
|
127
|
-
if (_.isNil(this.config.loseTokenState) || _.isNil(this.config.sessionExpiredErrorKey)) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (_.isNil(data) || typeof data !== "object") {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const resp = data as TResp.IResponse<unknown>;
|
|
134
|
-
if (resp.ERRORKEY === this.config.sessionExpiredErrorKey) {
|
|
135
|
-
this.config.loseTokenState();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private getMiniProgramWx(): IMiniProgramWx {
|
|
140
|
-
const miniProgramWx = (globalThis as { wx?: IMiniProgramWx }).wx;
|
|
141
|
-
if (_.isNil(miniProgramWx)) {
|
|
142
|
-
throw new Error("当前环境不存在微信小程序 wx");
|
|
143
|
-
}
|
|
144
|
-
return miniProgramWx;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private createRequestUrl(url: string, querys?: IWxQueryParams): string {
|
|
148
|
-
const baseURL = this.config.baseURL.endsWith("/") ? this.config.baseURL.slice(0, -1) : this.config.baseURL;
|
|
149
|
-
const path = url.startsWith("/") ? url : `/${url}`;
|
|
150
|
-
const mergedQuerys: IWxQueryParams = {
|
|
151
|
-
r: Date.now(),
|
|
152
|
-
...this.createAuthQuerys(),
|
|
153
|
-
...this.toLowerCase(querys)
|
|
154
|
-
};
|
|
155
|
-
const search = Object.entries(mergedQuerys)
|
|
156
|
-
.filter(([, value]) => !_.isNil(value))
|
|
157
|
-
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
|
158
|
-
.join("&");
|
|
159
|
-
if (search.length === 0) {
|
|
160
|
-
return `${baseURL}${path}`;
|
|
161
|
-
}
|
|
162
|
-
return `${baseURL}${path}?${search}`;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
private createAuthQuerys(): IWxQueryParams {
|
|
166
|
-
const querys: IWxQueryParams = {};
|
|
167
|
-
if (!_.isNil(this.config.whobuild) && this.config.whobuild !== 0) {
|
|
168
|
-
querys.whobuild = this.config.whobuild;
|
|
169
|
-
}
|
|
170
|
-
if (!_.isNil(this.config.userIndx) && this.config.userIndx !== 0) {
|
|
171
|
-
querys.userindx = this.config.userIndx;
|
|
172
|
-
}
|
|
173
|
-
return querys;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private createHeader(contentType: string | undefined, headers?: Record<string, string>): Record<string, string> {
|
|
177
|
-
const header: Record<string, string> = {};
|
|
178
|
-
if (!_.isNil(contentType)) {
|
|
179
|
-
header["content-type"] = contentType;
|
|
180
|
-
}
|
|
181
|
-
if (!_.isNil(this.config.usrtoken) && this.config.usrtoken !== "") {
|
|
182
|
-
header.usrtoken = this.config.usrtoken;
|
|
183
|
-
}
|
|
184
|
-
if (!_.isNil(this.config.dbConfig) && this.config.dbConfig !== "") {
|
|
185
|
-
header.dbconfig = this.config.dbConfig;
|
|
186
|
-
}
|
|
187
|
-
if (!_.isNil(headers)) {
|
|
188
|
-
Object.assign(header, headers);
|
|
189
|
-
}
|
|
190
|
-
return header;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private toLowerCase(querys?: IWxQueryParams): IWxQueryParams {
|
|
194
|
-
if (_.isNil(querys)) {
|
|
195
|
-
return {};
|
|
196
|
-
}
|
|
197
|
-
return _.mapKeys(querys, (_value, key) => key.toLowerCase());
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const createWxRequest = (config: IWxConfig): WxRequest => {
|
|
202
|
-
return WxRequest.create(config);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
export { type WxRequest, createWxRequest };
|
package/src/types.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const REQUEST_TIMEOUT_MILLISECONDS = 60000;
|
|
2
|
-
|
|
3
|
-
export interface IWxQueryParams {
|
|
4
|
-
[key: string]: string | number | boolean | null | undefined;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 请求拦截入参/出参(对应 Web axios InternalAxiosRequestConfig)。
|
|
9
|
-
* 国密等可在此改 data、header,并挂 gmSm4KeyHex。
|
|
10
|
-
*/
|
|
11
|
-
export interface IWxInternalRequestConfig {
|
|
12
|
-
/** 业务 path,不含 baseURL / query */
|
|
13
|
-
url: string;
|
|
14
|
-
method: "GET" | "POST";
|
|
15
|
-
querys?: IWxQueryParams;
|
|
16
|
-
data?: object;
|
|
17
|
-
header: Record<string, string>;
|
|
18
|
-
/** 国密会话 SM4,供响应拦截解密 */
|
|
19
|
-
gmSm4KeyHex?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 响应拦截入参/出参(对应 Web axios AxiosResponse)。
|
|
24
|
-
*/
|
|
25
|
-
export interface IWxResponse<T = unknown> {
|
|
26
|
-
data: T;
|
|
27
|
-
statusCode: number;
|
|
28
|
-
config: IWxInternalRequestConfig;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type TWxInterceptorsRequest = (request: IWxInternalRequestConfig) => IWxInternalRequestConfig | Promise<IWxInternalRequestConfig>;
|
|
32
|
-
|
|
33
|
-
export type TWxInterceptorsResponse = (response: IWxResponse) => IWxResponse | Promise<IWxResponse>;
|
|
34
|
-
|
|
35
|
-
export interface IWxConfig {
|
|
36
|
-
baseURL: string;
|
|
37
|
-
timeout?: number;
|
|
38
|
-
whobuild?: number;
|
|
39
|
-
userIndx?: number;
|
|
40
|
-
usrtoken?: string;
|
|
41
|
-
dbConfig?: string;
|
|
42
|
-
/**
|
|
43
|
-
* 请求拦截(对齐 Web createRequest 的 interceptorsRequest)。
|
|
44
|
-
* 在内置鉴权 query/header 组装之后、真正 wx.request 之前调用。
|
|
45
|
-
*/
|
|
46
|
-
interceptorsRequest?: TWxInterceptorsRequest;
|
|
47
|
-
/**
|
|
48
|
-
* 响应拦截(对齐 Web createRequest 的 interceptorsResponse)。
|
|
49
|
-
* 在 HTTP 成功拿到 body 之后、返回给业务之前调用。
|
|
50
|
-
*/
|
|
51
|
-
interceptorsResponse?: TWxInterceptorsResponse;
|
|
52
|
-
/** 会话过期时回调(对齐 Web loseTokenState,按 ERRORKEY 判断) */
|
|
53
|
-
loseTokenState?: () => void;
|
|
54
|
-
/** 与 loseTokenState 配合;不传则不根据 ERRORKEY 踢登录 */
|
|
55
|
-
sessionExpiredErrorKey?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export class TWxConfig implements IWxConfig {
|
|
59
|
-
baseURL: string = "";
|
|
60
|
-
timeout: number = REQUEST_TIMEOUT_MILLISECONDS;
|
|
61
|
-
whobuild: number = 0;
|
|
62
|
-
userIndx: number = 0;
|
|
63
|
-
usrtoken: string = "";
|
|
64
|
-
dbConfig: string = "";
|
|
65
|
-
interceptorsRequest?: TWxInterceptorsRequest = void 0;
|
|
66
|
-
interceptorsResponse?: TWxInterceptorsResponse = void 0;
|
|
67
|
-
loseTokenState?: () => void = void 0;
|
|
68
|
-
sessionExpiredErrorKey?: string = void 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface IWxLoginParams {
|
|
72
|
-
code: string;
|
|
73
|
-
encryptedData: string;
|
|
74
|
-
iv: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export class TWxLoginParams implements IWxLoginParams {
|
|
78
|
-
code: string = "";
|
|
79
|
-
encryptedData: string = "";
|
|
80
|
-
iv: string = "";
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export { REQUEST_TIMEOUT_MILLISECONDS };
|
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"lib": ["ES2023"],
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
|
|
8
|
-
/* Bundler mode */
|
|
9
|
-
"moduleResolution": "bundler",
|
|
10
|
-
"allowImportingTsExtensions": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"moduleDetection": "force",
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
|
|
15
|
-
/* Linting */
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"noFallthroughCasesInSwitch": true,
|
|
20
|
-
"experimentalDecorators": true
|
|
21
|
-
}
|
|
22
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vite";
|
|
2
|
-
|
|
3
|
-
import tsxResolveTypes from "vite-plugin-tsx-resolve-types";
|
|
4
|
-
import dts from "vite-plugin-dts";
|
|
5
|
-
|
|
6
|
-
export default defineConfig({
|
|
7
|
-
plugins: [
|
|
8
|
-
tsxResolveTypes(),
|
|
9
|
-
dts({
|
|
10
|
-
entryRoot: "src",
|
|
11
|
-
outDir: ["es"],
|
|
12
|
-
exclude: ["**/tests/**"]
|
|
13
|
-
})
|
|
14
|
-
],
|
|
15
|
-
build: {
|
|
16
|
-
rollupOptions: {
|
|
17
|
-
external: ["lodash", "@ningboyz/types"],
|
|
18
|
-
output: [
|
|
19
|
-
{
|
|
20
|
-
preserveModules: true,
|
|
21
|
-
preserveModulesRoot: "src",
|
|
22
|
-
entryFileNames: "[name].js",
|
|
23
|
-
format: "esm",
|
|
24
|
-
dir: "es"
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
lib: {
|
|
29
|
-
entry: "src/index.ts"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|