@yeepay/client-utils 3.0.5 → 3.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/index.d.ts CHANGED
@@ -1,5 +1,52 @@
1
1
  import { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
2
2
 
3
+ //#region src/request/mock.d.ts
4
+
5
+ /**
6
+ * A valid `picomatch` glob pattern, or array of patterns.
7
+ */
8
+ type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null;
9
+ interface Mock {
10
+ /**
11
+ * Default is enable localhost domain, is disabled at other domains.
12
+ *
13
+ * @default undefined
14
+ */
15
+ enabled?: boolean;
16
+ /**
17
+ * Response delay in milliseconds.
18
+ *
19
+ * @default 200
20
+ */
21
+ delay?: number;
22
+ /**
23
+ * The Modules that store mock data.
24
+ *
25
+ * Please use glob patterns to specify the modules.
26
+ *
27
+ * @default {}
28
+ */
29
+ modules?: Record<string, unknown | (() => Promise<unknown>)>;
30
+ /**
31
+ * If enabled log in console.
32
+ *
33
+ * @default true
34
+ */
35
+ log?: boolean;
36
+ /**
37
+ * The Modules to include the mock.
38
+ *
39
+ * @default ['*']
40
+ */
41
+ includes?: FilterPattern;
42
+ /**
43
+ * The Modules to exclude the mock.
44
+ *
45
+ * @default []
46
+ */
47
+ excludes?: FilterPattern;
48
+ }
49
+ //#endregion
3
50
  //#region src/request/index.d.ts
4
51
  interface ServiceFactoryOptions {
5
52
  baseUrl?: string;
@@ -7,7 +54,7 @@ interface ServiceFactoryOptions {
7
54
  headers?: Record<string, string>;
8
55
  code?: string | number;
9
56
  debug?: boolean;
10
- mockModules?: Record<string, unknown | (() => Promise<unknown>)>;
57
+ mock?: Mock;
11
58
  }
12
59
  interface ServiceFactoryCallbacks {
13
60
  successCallback?: (response: AxiosResponse<any>) => any;
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { toArray } from "@imyangyong/utils";
1
+ import { interopDefault, toArray } from "@imyangyong/utils";
2
2
  import axios from "axios";
3
3
  import { bold, cyan, gray, green, red, yellow } from "ansis";
4
4
  import AxiosMockAdapter from "axios-mock-adapter";
5
+ import picomatch from "picomatch/posix";
5
6
  import Cookie from "js-cookie";
6
7
 
7
8
  //#region src/request/mock.ts
@@ -20,32 +21,68 @@ function longestCommonPrefix(strs) {
20
21
  function isLocalhost() {
21
22
  return window.location.hostname === "localhost";
22
23
  }
23
- async function setupMockAdapter(axiosInstance, mockModules) {
24
- if (!mockModules) return;
25
- if (!isLocalhost()) return;
26
- const mock = new AxiosMockAdapter(axiosInstance);
27
- const paths = Object.keys(mockModules);
28
- const longestPrefix = longestCommonPrefix(paths);
29
- paths.forEach((path) => {
24
+ /**
25
+ * Simple pattern matching function that handles basic glob patterns and regex
26
+ */
27
+ function matchesPattern(str, pattern) {
28
+ if (pattern instanceof RegExp) return pattern.test(str);
29
+ if (typeof pattern === "string") {
30
+ if (pattern === "*") return true;
31
+ const isMatch = picomatch(pattern);
32
+ return isMatch(str);
33
+ }
34
+ return false;
35
+ }
36
+ /**
37
+ * Check if a uri should be included based on includes/excludes patterns
38
+ */
39
+ function shouldIncludeModule(uri, includes, excludes) {
40
+ 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;
46
+ }
47
+ async function setupMockAdapter(axiosInstance, mock) {
48
+ if (!mock) return;
49
+ const { enabled, delay = 200, modules, includes = ["*"], excludes = [], log = true } = mock;
50
+ if (enabled === void 0 && !isLocalhost() || enabled === false) return;
51
+ if (!modules) return;
52
+ const mockAdapter = new AxiosMockAdapter(axiosInstance, {
53
+ delayResponse: delay,
54
+ onNoMatch: "passthrough"
55
+ });
56
+ const allPaths = Object.keys(modules);
57
+ const longestPrefix = longestCommonPrefix(allPaths);
58
+ const paths = allPaths.map((path) => {
30
59
  const longestPrefixIndex = longestPrefix.lastIndexOf("/");
31
60
  const dotIndex = path.lastIndexOf(".");
32
61
  const uri = path.slice(longestPrefixIndex, dotIndex);
62
+ return {
63
+ uri,
64
+ path
65
+ };
66
+ });
67
+ const filteredPaths = paths.filter(({ uri }) => shouldIncludeModule(uri, includes, excludes));
68
+ if (filteredPaths.length === 0) return;
69
+ filteredPaths.forEach(({ uri, path }) => {
33
70
  const registerMock = (mod) => {
34
- const replyFunc = typeof mod.default === "function" ? mod.default : () => [200, mod.default];
35
- mock.onAny(new RegExp(uri)).reply((config) => {
71
+ const replyFunc = typeof mod === "function" ? mod : () => [200, mod];
72
+ mockAdapter.onAny(new RegExp(uri)).reply((config) => {
36
73
  const response = replyFunc(config);
37
74
  const status = String(response[0]);
38
75
  const statusColor = status.startsWith("2") ? green(status) : status.startsWith("3") ? yellow(status) : red(status);
39
76
  const data = response[1] ? JSON.stringify(response[1], null, 2) : "";
40
77
  const headers = response[2] ? JSON.stringify(response[2], null, 2) : "";
41
- console.log(`${gray("Mocked:")} ${bold("URI")}: ${cyan.bold(uri)} \n${bold("Status")}: ${statusColor} \n${bold("Response")}: ${data} \n${headers ? `${bold("Headers:")} ${headers}` : ""}`);
78
+ if (log) console.log(`${gray("Mocked:")} ${bold("URI")}: ${cyan.bold(uri)} \n${bold("Status")}: ${statusColor} \n${bold("Response")}: ${data} \n${headers ? `${bold("Headers:")} ${headers}` : ""}`);
42
79
  return response;
43
80
  });
44
81
  };
45
- if (typeof mockModules[path] === "function") mockModules[path]().then(registerMock).catch((error) => {
82
+ if (typeof modules[path] === "function") interopDefault(modules[path]()).then(registerMock).catch((error) => {
46
83
  console.error(`@yeepay/client-utils mock trying to loading ${path} failed`, error);
47
84
  });
48
- else registerMock(mockModules[path]);
85
+ else registerMock(modules[path]);
49
86
  });
50
87
  }
51
88
 
@@ -128,7 +165,7 @@ function blobToJson(blob) {
128
165
  });
129
166
  }
130
167
  function serviceFactory(options, ...callbacks) {
131
- const { baseUrl = "/", timeout = 12e5, headers, code, debug, mockModules } = options;
168
+ const { baseUrl = "/", timeout = 12e5, headers, code, debug, mock } = options;
132
169
  const { successCallback = (_response) => ({}), failCallback = (_error) => ({}), unauthorizedCallback = (_response) => ({}), forbiddenCallback = (_response) => ({}), notfoundCallback = (_response) => ({}), requestInterceptor = (c) => c, responseInterceptor = (r) => r } = compatibleCallback(callbacks);
133
170
  const service = axios.create({
134
171
  baseURL: baseUrl,
@@ -202,7 +239,7 @@ function serviceFactory(options, ...callbacks) {
202
239
  service.interceptors.response.use(responseInterceptor, (error) => {
203
240
  return Promise.reject(error);
204
241
  });
205
- if (mockModules) setupMockAdapter(service, mockModules);
242
+ if (mock) setupMockAdapter(service, mock);
206
243
  return service;
207
244
  }
208
245
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yeepay/client-utils",
3
3
  "type": "module",
4
- "version": "3.0.5",
4
+ "version": "3.1.0",
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",
@@ -14,6 +14,7 @@
14
14
  "import": "./dist/index.js"
15
15
  }
16
16
  },
17
+ "main": "./dist/index.js",
17
18
  "types": "./dist/index.d.ts",
18
19
  "files": [
19
20
  "dist"
@@ -23,11 +24,13 @@
23
24
  "ansis": "^4.1.0",
24
25
  "axios": "^1.7.0",
25
26
  "axios-mock-adapter": "^2.1.0",
26
- "js-cookie": "^3.0.5"
27
+ "js-cookie": "^3.0.5",
28
+ "picomatch": "^4.0.3"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@antfu/ni": "^0.21.12",
30
32
  "@types/js-cookie": "^3.0.6",
33
+ "@types/picomatch": "^4.0.2",
31
34
  "@yeepay/eslint-config": "^4.17.0",
32
35
  "bumpp": "^9.4.1",
33
36
  "eslint": "^9.32.0",