@yeepay/client-utils 3.1.0 → 3.1.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/README.md CHANGED
@@ -41,8 +41,9 @@ const service = serviceFactory(
41
41
  {
42
42
  baseUrl: '/xxx-server',
43
43
  headers: {},
44
- // glob mock 数据文件位置
45
- mockModules: import.meta.glob('./mock/**/*.json', { eager: true }),
44
+ mock: {
45
+ modules: import.meta.glob('./mock/**/*.json', { eager: true }),
46
+ },
46
47
  },
47
48
  successCallback,
48
49
  failCallback,
@@ -81,3 +82,34 @@ export default (config: AxiosRequestConfig) => {
81
82
  }, { 'new-header-hello': 'world' }]
82
83
  }
83
84
  ```
85
+
86
+ ### Debug 日志打印
87
+
88
+ 开发者常常使用 console.log 日志打印来调试代码,且往往会忘记删除这些日志,导致线上环境也打印日志,影响性能与潜在安全风险。
89
+
90
+ `@yeepay/client-utils` 提供了 debug 模块来帮助开发者更好地控制日志打印。
91
+
92
+ #### 基本使用
93
+
94
+ ```javascript
95
+ import { debug } from '@yeepay/client-utils'
96
+
97
+ debug.page1('page1 is loaded')
98
+
99
+ debug.api('fetch user api is called')
100
+ ```
101
+
102
+ ![image](http://gitlab.yeepay.com/fex/client-utils/-/raw/master/static/debug-demo.png)
103
+
104
+ 这些日志默认在开发环境打印,而在生产环境不打印。
105
+
106
+ 如果想要在生产环境打印,可以在浏览器控制台执行:
107
+
108
+ ```javascript
109
+ debug.enableAll()
110
+ // 或者打印特定模块
111
+ debug.enable('page1')
112
+
113
+ // 恢复默认行为
114
+ debug.disable()
115
+ ```
package/dist/index.d.ts CHANGED
@@ -1,7 +1,19 @@
1
+ import debug from "debug";
1
2
  import { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
2
3
 
4
+ //#region src/debug.d.ts
5
+ declare const logger: Record<string, debug.Debugger> & debug.Debugger;
6
+ declare global {
7
+ interface Window {
8
+ debug: {
9
+ enableAll: () => void;
10
+ enable: (namespace: string) => void;
11
+ disable: () => void;
12
+ };
13
+ }
14
+ }
15
+ //#endregion
3
16
  //#region src/request/mock.d.ts
4
-
5
17
  /**
6
18
  * A valid `picomatch` glob pattern, or array of patterns.
7
19
  */
@@ -81,4 +93,4 @@ declare function removeToken(): void;
81
93
  //#region src/utils.d.ts
82
94
  declare function getQueryObject(url?: string): Record<string, string>;
83
95
  //#endregion
84
- export { getQueryObject, getToken, removeToken, serviceFactory, setTokenFromUrl, verifySuccessCode };
96
+ export { logger as debug, getQueryObject, getToken, removeToken, serviceFactory, setTokenFromUrl, verifySuccessCode };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import debug from "debug";
1
2
  import { interopDefault, toArray } from "@imyangyong/utils";
2
3
  import axios from "axios";
3
4
  import { bold, cyan, gray, green, red, yellow } from "ansis";
@@ -5,6 +6,55 @@ import AxiosMockAdapter from "axios-mock-adapter";
5
6
  import picomatch from "picomatch/posix";
6
7
  import Cookie from "js-cookie";
7
8
 
9
+ //#region src/debug.ts
10
+ function createLogger(namespace) {
11
+ return debug(namespace);
12
+ }
13
+ const loggers = {};
14
+ const logger = new Proxy(function() {}, {
15
+ get(_, prop) {
16
+ if (prop in loggers) return loggers[prop];
17
+ const newLogger = createLogger(`${prop}`);
18
+ loggers[prop] = newLogger;
19
+ return newLogger;
20
+ },
21
+ apply(_, thisArg, args) {
22
+ return (loggers.app || (loggers.app = createLogger("app"))).apply(thisArg, args);
23
+ }
24
+ });
25
+ window.debug = {
26
+ enableAll: () => {
27
+ localStorage.setItem("debug", "*");
28
+ location.reload();
29
+ },
30
+ enable: (namespace) => {
31
+ if (!namespace) {
32
+ window.debug.enableAll();
33
+ return;
34
+ }
35
+ const namespaces = (localStorage.getItem("debug") || "").split(",").filter(Boolean);
36
+ namespaces.push(`${namespace}`);
37
+ localStorage.setItem("debug", namespaces.join(","));
38
+ location.reload();
39
+ },
40
+ disable: () => {
41
+ try {
42
+ if (process?.env?.NODE_ENV === "development") localStorage.setItem("debug", "null");
43
+ else localStorage.removeItem("debug");
44
+ } finally {
45
+ location.reload();
46
+ }
47
+ }
48
+ };
49
+ try {
50
+ if (process.env.NODE_ENV === "development") {
51
+ if (!localStorage.getItem("debug")) window.debug.enableAll();
52
+ }
53
+ } catch (error) {
54
+ console.error("Error enabling logger:", error);
55
+ }
56
+
57
+ //#endregion
8
58
  //#region src/request/mock.ts
9
59
  /**
10
60
  * 查找数组中最长相同前缀连续子序列
@@ -28,8 +78,7 @@ function matchesPattern(str, pattern) {
28
78
  if (pattern instanceof RegExp) return pattern.test(str);
29
79
  if (typeof pattern === "string") {
30
80
  if (pattern === "*") return true;
31
- const isMatch = picomatch(pattern);
32
- return isMatch(str);
81
+ return picomatch(pattern)(str);
33
82
  }
34
83
  return false;
35
84
  }
@@ -38,11 +87,8 @@ function matchesPattern(str, pattern) {
38
87
  */
39
88
  function shouldIncludeModule(uri, includes, excludes) {
40
89
  const includePatterns = includes ? Array.isArray(includes) ? includes : [includes] : ["*"];
41
- const excludePatterns = excludes ? Array.isArray(excludes) ? excludes : [excludes] : [];
42
- const isExcluded = excludePatterns.some((pattern) => pattern && matchesPattern(uri, pattern));
43
- if (isExcluded) return false;
44
- const isIncluded = includePatterns.some((pattern) => pattern && matchesPattern(uri, pattern));
45
- return isIncluded;
90
+ if ((excludes ? Array.isArray(excludes) ? excludes : [excludes] : []).some((pattern) => pattern && matchesPattern(uri, pattern))) return false;
91
+ return includePatterns.some((pattern) => pattern && matchesPattern(uri, pattern));
46
92
  }
47
93
  async function setupMockAdapter(axiosInstance, mock) {
48
94
  if (!mock) return;
@@ -55,16 +101,14 @@ async function setupMockAdapter(axiosInstance, mock) {
55
101
  });
56
102
  const allPaths = Object.keys(modules);
57
103
  const longestPrefix = longestCommonPrefix(allPaths);
58
- const paths = allPaths.map((path) => {
104
+ const filteredPaths = allPaths.map((path) => {
59
105
  const longestPrefixIndex = longestPrefix.lastIndexOf("/");
60
106
  const dotIndex = path.lastIndexOf(".");
61
- const uri = path.slice(longestPrefixIndex, dotIndex);
62
107
  return {
63
- uri,
108
+ uri: path.slice(longestPrefixIndex, dotIndex),
64
109
  path
65
110
  };
66
- });
67
- const filteredPaths = paths.filter(({ uri }) => shouldIncludeModule(uri, includes, excludes));
111
+ }).filter(({ uri }) => shouldIncludeModule(uri, includes, excludes));
68
112
  if (filteredPaths.length === 0) return;
69
113
  filteredPaths.forEach(({ uri, path }) => {
70
114
  const registerMock = (mod) => {
@@ -92,8 +136,7 @@ function getQueryObject(url) {
92
136
  url = !url ? window.location.href : url;
93
137
  const search = url.substring(url.lastIndexOf("?") + 1);
94
138
  const obj = {};
95
- const reg = /([^?&=]+)=([^?&=]*)/g;
96
- search.replace(reg, (rs, $1, $2) => {
139
+ search.replace(/([^?&=]+)=([^?&=]*)/g, (rs, $1, $2) => {
97
140
  const name = decodeURIComponent($1);
98
141
  let val = decodeURIComponent($2);
99
142
  val = String(val);
@@ -165,7 +208,7 @@ function blobToJson(blob) {
165
208
  });
166
209
  }
167
210
  function serviceFactory(options, ...callbacks) {
168
- const { baseUrl = "/", timeout = 12e5, headers, code, debug, mock } = options;
211
+ const { baseUrl = "/", timeout = 12e5, headers, code, debug: debug$1, mock } = options;
169
212
  const { successCallback = (_response) => ({}), failCallback = (_error) => ({}), unauthorizedCallback = (_response) => ({}), forbiddenCallback = (_response) => ({}), notfoundCallback = (_response) => ({}), requestInterceptor = (c) => c, responseInterceptor = (r) => r } = compatibleCallback(callbacks);
170
213
  const service = axios.create({
171
214
  baseURL: baseUrl,
@@ -186,7 +229,7 @@ function serviceFactory(options, ...callbacks) {
186
229
  config.headers.Authorization = getToken();
187
230
  const { method, url = "" } = config;
188
231
  if (method === "get") {
189
- if (!debug) if (url.includes("?")) config.url = `${url}&_t=${(/* @__PURE__ */ new Date()).getTime()}`;
232
+ if (!debug$1) if (url.includes("?")) config.url = `${url}&_t=${(/* @__PURE__ */ new Date()).getTime()}`;
190
233
  else config.url = `${url}?_t=${(/* @__PURE__ */ new Date()).getTime()}`;
191
234
  }
192
235
  return config;
@@ -244,4 +287,4 @@ function serviceFactory(options, ...callbacks) {
244
287
  }
245
288
 
246
289
  //#endregion
247
- export { getQueryObject, getToken, removeToken, serviceFactory, setTokenFromUrl, verifySuccessCode };
290
+ export { logger as debug, getQueryObject, getToken, removeToken, serviceFactory, setTokenFromUrl, verifySuccessCode };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yeepay/client-utils",
3
3
  "type": "module",
4
- "version": "3.1.0",
4
+ "version": "3.1.1",
5
5
  "description": "shared utilities for yeepay client packages",
6
6
  "author": "Yong Yang",
7
7
  "homepage": "http://gitlab.yeepay.com/ued/client-utils#readme",
@@ -21,20 +21,24 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "@imyangyong/utils": "^0.8.0",
24
+ "@yeepay/client-utils": "link:",
24
25
  "ansis": "^4.1.0",
25
26
  "axios": "^1.7.0",
26
27
  "axios-mock-adapter": "^2.1.0",
28
+ "debug": "^4.4.3",
27
29
  "js-cookie": "^3.0.5",
28
30
  "picomatch": "^4.0.3"
29
31
  },
30
32
  "devDependencies": {
31
33
  "@antfu/ni": "^0.21.12",
34
+ "@types/debug": "^4.1.12",
32
35
  "@types/js-cookie": "^3.0.6",
33
36
  "@types/picomatch": "^4.0.2",
34
37
  "@yeepay/eslint-config": "^4.17.0",
35
38
  "bumpp": "^9.4.1",
36
39
  "eslint": "^9.32.0",
37
40
  "eslint-plugin-format": "^0.1.1",
41
+ "happy-dom": "^18.0.1",
38
42
  "lint-staged": "^15.2.2",
39
43
  "simple-git-hooks": "^2.11.1",
40
44
  "tsdown": "^0.14.1",
@@ -53,6 +57,7 @@
53
57
  "watch": "tsdown --watch",
54
58
  "lint": "eslint .",
55
59
  "release": "bumpp && pnpm publish",
56
- "test": "vitest"
60
+ "test": "vitest",
61
+ "play": "npm -C playground run dev"
57
62
  }
58
63
  }