react-toolkits 2.27.20 → 2.28.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/locale/hooks.js CHANGED
@@ -2,11 +2,348 @@ import { template, has, get } from 'lodash-es';
2
2
  import { createContext, useMemo, useContext } from 'react';
3
3
  import 'antd';
4
4
  import { useStore } from 'zustand';
5
+ import ky from 'ky';
5
6
  import 'zustand/middleware';
6
7
  import 'jwt-decode';
7
8
  import 'react/jsx-runtime';
8
9
 
9
- // src/locale/hooks.ts
10
+ var __defProp = Object.defineProperty;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
+
14
+ // src/constants/index.ts
15
+ var APP_ID_HEADER = "App-ID";
16
+
17
+ // src/libs/ky.ts
18
+ var DEFAULT_SUCCESS_RESPONSE_CODES = [0, 1, 200];
19
+ var DEFAULT_STATUS_FIELDS = ["code", "status", "errno"];
20
+ var DEFAULT_ERROR_FIELDS = ["msg", "message", "error"];
21
+ var HTTP_STATUS = {
22
+ OK: 200,
23
+ UNAUTHORIZED: 401,
24
+ FORBIDDEN: 403,
25
+ UNREGISTERED: 412
26
+ };
27
+ var REQUEST_TIMEOUT = 3e4;
28
+ function isStatusCodeSuccess(config) {
29
+ const { value, allowedCodes } = config;
30
+ if (value === void 0 || value === null) {
31
+ return false;
32
+ }
33
+ if (typeof value !== "number") {
34
+ return false;
35
+ }
36
+ return allowedCodes.includes(value);
37
+ }
38
+ function isSuccessResponse(data, status, config) {
39
+ if (config?.isSuccess) {
40
+ return config.isSuccess(data, status);
41
+ }
42
+ if (status < HTTP_STATUS.OK || status >= 300) {
43
+ return false;
44
+ }
45
+ if (!data || typeof data !== "object") {
46
+ return true;
47
+ }
48
+ const successCodes = config?.successCodes || DEFAULT_SUCCESS_RESPONSE_CODES;
49
+ const statusFields = config?.statusFields || DEFAULT_STATUS_FIELDS;
50
+ const dataObj = data;
51
+ const statusChecks = statusFields.map((field) => ({
52
+ field,
53
+ value: dataObj[field],
54
+ allowedCodes: successCodes
55
+ }));
56
+ const hasBusinessStatusCode = statusChecks.some((check) => check.value !== void 0 && check.value !== null);
57
+ if (hasBusinessStatusCode) {
58
+ return statusChecks.every((check) => check.value === void 0 || check.value === null || isStatusCodeSuccess(check));
59
+ }
60
+ return true;
61
+ }
62
+ function extractErrorMessage(data, config) {
63
+ if (!data || typeof data !== "object") {
64
+ return "Unknown error";
65
+ }
66
+ if (config?.extractErrorMessage) {
67
+ return config.extractErrorMessage(data);
68
+ }
69
+ const errorFields = config?.errorFields || DEFAULT_ERROR_FIELDS;
70
+ for (const field of errorFields) {
71
+ const value = data[field];
72
+ if (value) {
73
+ return String(value);
74
+ }
75
+ }
76
+ return "Unknown error";
77
+ }
78
+ async function processResponseByType(response, responseType) {
79
+ switch (responseType) {
80
+ case "text":
81
+ return response.text();
82
+ case "arrayBuffer":
83
+ return response.arrayBuffer();
84
+ case "formData":
85
+ return response.formData();
86
+ case "json":
87
+ return response.json();
88
+ default:
89
+ return response;
90
+ }
91
+ }
92
+ var KyClient = class {
93
+ constructor(options = {}) {
94
+ __publicField(this, "_instance");
95
+ __publicField(this, "businessConfig");
96
+ __publicField(this, "errorConfig");
97
+ __publicField(this, "errorHandlers");
98
+ __publicField(this, "context");
99
+ __publicField(this, "disableDefaultErrorNotification");
100
+ __publicField(this, "get", (url, options) => {
101
+ return this.makeRequest("GET", url, void 0, options);
102
+ });
103
+ __publicField(this, "post", (url, data, options) => {
104
+ return this.makeRequest("POST", url, data, options);
105
+ });
106
+ __publicField(this, "put", (url, data, options) => {
107
+ return this.makeRequest("PUT", url, data, options);
108
+ });
109
+ __publicField(this, "delete", (url, options) => {
110
+ return this.makeRequest("DELETE", url, void 0, options);
111
+ });
112
+ __publicField(this, "patch", (url, data, options) => {
113
+ return this.makeRequest("PATCH", url, data, options);
114
+ });
115
+ __publicField(this, "options", (url, requestOptions) => {
116
+ return this.makeRequest("OPTIONS", url, void 0, requestOptions);
117
+ });
118
+ __publicField(this, "head", (url, requestOptions) => {
119
+ return this.makeRequest("HEAD", url, void 0, requestOptions);
120
+ });
121
+ __publicField(this, "request", (requestOptions) => {
122
+ const { url, ...requestOpts } = requestOptions;
123
+ return this.makeRequest(requestOpts.method || "GET", url, void 0, requestOpts);
124
+ });
125
+ const {
126
+ baseURL,
127
+ successCodes,
128
+ statusFields,
129
+ errorFields,
130
+ extractErrorMessage: customExtractErrorMessage,
131
+ onUnauthorized: customOnUnauthorized,
132
+ onForbidden: customOnForbidden,
133
+ onUnregistered: customOnUnregistered,
134
+ onError: customOnError,
135
+ onNetworkError: customOnNetworkError,
136
+ isSuccess: customIsSuccess,
137
+ disableDefaultErrorNotification = false,
138
+ context
139
+ } = options;
140
+ this.context = context;
141
+ this.disableDefaultErrorNotification = disableDefaultErrorNotification;
142
+ this.businessConfig = {
143
+ successCodes,
144
+ statusFields,
145
+ isSuccess: customIsSuccess
146
+ };
147
+ this.errorConfig = {
148
+ errorFields,
149
+ extractErrorMessage: customExtractErrorMessage
150
+ };
151
+ this.errorHandlers = {
152
+ onUnauthorized: customOnUnauthorized,
153
+ onForbidden: customOnForbidden,
154
+ onUnregistered: customOnUnregistered,
155
+ onError: customOnError,
156
+ onNetworkError: customOnNetworkError
157
+ };
158
+ this._instance = ky.create({
159
+ prefixUrl: baseURL ?? context?.apiBaseUrl,
160
+ retry: 0,
161
+ timeout: REQUEST_TIMEOUT,
162
+ hooks: {
163
+ beforeRequest: [this.handleBeforeRequest.bind(this)],
164
+ beforeError: [this.handleBeforeError.bind(this)]
165
+ }
166
+ });
167
+ }
168
+ /** 获取 ky 实例(用于高级用法) */
169
+ get instance() {
170
+ return this._instance;
171
+ }
172
+ /**
173
+ * 通用请求处理函数
174
+ */
175
+ async makeRequest(method, url, data, requestOptions) {
176
+ const { responseType = "json", ...kyOptions } = requestOptions || {};
177
+ const finalOptions = {
178
+ ...kyOptions,
179
+ hooks: {
180
+ ...kyOptions.hooks,
181
+ afterResponse: [...kyOptions.hooks?.afterResponse || [], this.createResponseHandler(responseType)]
182
+ }
183
+ };
184
+ let response;
185
+ if (data) {
186
+ if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob || typeof data === "string" || data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
187
+ response = await this._instance(url, { method, body: data, ...finalOptions });
188
+ } else {
189
+ response = await this._instance(url, { method, json: data, ...finalOptions });
190
+ }
191
+ } else {
192
+ response = await this._instance(url, { method, ...finalOptions });
193
+ }
194
+ return processResponseByType(response, responseType);
195
+ }
196
+ /**
197
+ * 创建响应处理函数
198
+ */
199
+ createResponseHandler(responseType) {
200
+ return async (_request, _options, response) => {
201
+ if (responseType === "blob" || responseType === "arrayBuffer" || responseType === "text" || responseType === "formData") {
202
+ return response;
203
+ }
204
+ let data;
205
+ try {
206
+ data = await response.clone().json();
207
+ } catch {
208
+ return response;
209
+ }
210
+ if (isSuccessResponse(data, response.status, this.businessConfig)) {
211
+ return new Response(JSON.stringify(data), {
212
+ status: response.status,
213
+ statusText: response.statusText,
214
+ headers: response.headers
215
+ });
216
+ }
217
+ const errorMessage = extractErrorMessage(data, this.errorConfig);
218
+ if (!this.disableDefaultErrorNotification && !this.errorHandlers.onError && this.context?.notifyError) {
219
+ this.context.notifyError("Request failed", errorMessage);
220
+ }
221
+ if (this.errorHandlers.onError) {
222
+ this.errorHandlers.onError(response.status, data, errorMessage);
223
+ }
224
+ const error = new Error(errorMessage);
225
+ error.response = response;
226
+ error.data = data;
227
+ throw error;
228
+ };
229
+ }
230
+ /**
231
+ * 请求前处理:设置认证和 appId headers
232
+ */
233
+ handleBeforeRequest(request) {
234
+ const { token, isGlobalMode, appId } = this.context || {};
235
+ if (token) {
236
+ request.headers.set("Authorization", `Bearer ${token}`);
237
+ }
238
+ if (!request.headers.has(APP_ID_HEADER)) {
239
+ if (isGlobalMode || !appId) {
240
+ request.headers.set(APP_ID_HEADER, "global");
241
+ } else {
242
+ request.headers.set(APP_ID_HEADER, encodeURIComponent(String(appId)));
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * 错误前处理:处理 HTTP 状态码错误
248
+ */
249
+ async handleBeforeError(error) {
250
+ const { response } = error;
251
+ if (response) {
252
+ const status = response.status;
253
+ let data;
254
+ try {
255
+ const contentType = response.headers.get("content-type") || "";
256
+ if (contentType.includes("application/json") || contentType.startsWith("text/")) {
257
+ data = await response.clone().json();
258
+ }
259
+ } catch {
260
+ }
261
+ this.handleHttpStatusError(status, data);
262
+ } else {
263
+ if (this.errorHandlers.onNetworkError) {
264
+ this.errorHandlers.onNetworkError(error);
265
+ } else if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
266
+ this.context.notifyError("Network Error", error.message || "Network request failed");
267
+ }
268
+ }
269
+ return error;
270
+ }
271
+ /**
272
+ * 处理 HTTP 状态码错误
273
+ */
274
+ handleHttpStatusError(status, data) {
275
+ switch (status) {
276
+ case HTTP_STATUS.UNAUTHORIZED:
277
+ if (this.errorHandlers.onUnauthorized) {
278
+ this.errorHandlers.onUnauthorized(data);
279
+ } else {
280
+ this.defaultHandleUnauthorized();
281
+ }
282
+ break;
283
+ case HTTP_STATUS.UNREGISTERED:
284
+ if (this.errorHandlers.onUnregistered) {
285
+ this.errorHandlers.onUnregistered(data);
286
+ } else {
287
+ this.defaultHandleUnregistered();
288
+ }
289
+ break;
290
+ case HTTP_STATUS.FORBIDDEN:
291
+ if (this.errorHandlers.onForbidden) {
292
+ this.errorHandlers.onForbidden(data);
293
+ } else {
294
+ this.defaultHandleForbidden();
295
+ }
296
+ break;
297
+ default: {
298
+ const errorMessage = extractErrorMessage(data, this.errorConfig) || `HTTP ${status} Error`;
299
+ if (this.errorHandlers.onError) {
300
+ this.errorHandlers.onError(status, data, errorMessage);
301
+ } else if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
302
+ this.context.notifyError("Request failed", errorMessage);
303
+ }
304
+ break;
305
+ }
306
+ }
307
+ }
308
+ /**
309
+ * 默认处理未授权错误
310
+ */
311
+ defaultHandleUnauthorized() {
312
+ const { clear, loginPath } = this.context || {};
313
+ if (clear && loginPath) {
314
+ clear();
315
+ window.location.href = loginPath;
316
+ }
317
+ }
318
+ /**
319
+ * 默认处理未注册错误
320
+ */
321
+ defaultHandleUnregistered() {
322
+ const { clear, loginPath } = this.context || {};
323
+ if (clear && loginPath) {
324
+ clear();
325
+ const url = new URL(loginPath, window.location.origin);
326
+ url.searchParams.set("unregistered", "true");
327
+ window.location.href = url.toString();
328
+ }
329
+ }
330
+ /**
331
+ * 默认处理禁止访问错误
332
+ */
333
+ defaultHandleForbidden() {
334
+ if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
335
+ this.context.notifyError("\u8BBF\u95EE\u88AB\u7981\u6B62", "\u60A8\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6B64\u8D44\u6E90\u3002");
336
+ }
337
+ }
338
+ /**
339
+ * 更新上下文信息
340
+ * 用于在运行时更新 context(例如在 React 组件中从 context 获取最新信息)
341
+ */
342
+ updateContext(context) {
343
+ this.context = context;
344
+ }
345
+ };
346
+ new KyClient();
10
347
  var ToolkitsContext = createContext(null);
11
348
  function useToolkitsStore(selector) {
12
349
  const store = useContext(ToolkitsContext);
package/locale/index.js CHANGED
@@ -2,11 +2,348 @@ import { template, has, get } from 'lodash-es';
2
2
  import { createContext, useMemo, useContext } from 'react';
3
3
  import 'antd';
4
4
  import { useStore } from 'zustand';
5
+ import ky from 'ky';
5
6
  import 'zustand/middleware';
6
7
  import 'jwt-decode';
7
8
  import 'react/jsx-runtime';
8
9
 
9
- // src/locale/hooks.ts
10
+ var __defProp = Object.defineProperty;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
+
14
+ // src/constants/index.ts
15
+ var APP_ID_HEADER = "App-ID";
16
+
17
+ // src/libs/ky.ts
18
+ var DEFAULT_SUCCESS_RESPONSE_CODES = [0, 1, 200];
19
+ var DEFAULT_STATUS_FIELDS = ["code", "status", "errno"];
20
+ var DEFAULT_ERROR_FIELDS = ["msg", "message", "error"];
21
+ var HTTP_STATUS = {
22
+ OK: 200,
23
+ UNAUTHORIZED: 401,
24
+ FORBIDDEN: 403,
25
+ UNREGISTERED: 412
26
+ };
27
+ var REQUEST_TIMEOUT = 3e4;
28
+ function isStatusCodeSuccess(config) {
29
+ const { value, allowedCodes } = config;
30
+ if (value === void 0 || value === null) {
31
+ return false;
32
+ }
33
+ if (typeof value !== "number") {
34
+ return false;
35
+ }
36
+ return allowedCodes.includes(value);
37
+ }
38
+ function isSuccessResponse(data, status, config) {
39
+ if (config?.isSuccess) {
40
+ return config.isSuccess(data, status);
41
+ }
42
+ if (status < HTTP_STATUS.OK || status >= 300) {
43
+ return false;
44
+ }
45
+ if (!data || typeof data !== "object") {
46
+ return true;
47
+ }
48
+ const successCodes = config?.successCodes || DEFAULT_SUCCESS_RESPONSE_CODES;
49
+ const statusFields = config?.statusFields || DEFAULT_STATUS_FIELDS;
50
+ const dataObj = data;
51
+ const statusChecks = statusFields.map((field) => ({
52
+ field,
53
+ value: dataObj[field],
54
+ allowedCodes: successCodes
55
+ }));
56
+ const hasBusinessStatusCode = statusChecks.some((check) => check.value !== void 0 && check.value !== null);
57
+ if (hasBusinessStatusCode) {
58
+ return statusChecks.every((check) => check.value === void 0 || check.value === null || isStatusCodeSuccess(check));
59
+ }
60
+ return true;
61
+ }
62
+ function extractErrorMessage(data, config) {
63
+ if (!data || typeof data !== "object") {
64
+ return "Unknown error";
65
+ }
66
+ if (config?.extractErrorMessage) {
67
+ return config.extractErrorMessage(data);
68
+ }
69
+ const errorFields = config?.errorFields || DEFAULT_ERROR_FIELDS;
70
+ for (const field of errorFields) {
71
+ const value = data[field];
72
+ if (value) {
73
+ return String(value);
74
+ }
75
+ }
76
+ return "Unknown error";
77
+ }
78
+ async function processResponseByType(response, responseType) {
79
+ switch (responseType) {
80
+ case "text":
81
+ return response.text();
82
+ case "arrayBuffer":
83
+ return response.arrayBuffer();
84
+ case "formData":
85
+ return response.formData();
86
+ case "json":
87
+ return response.json();
88
+ default:
89
+ return response;
90
+ }
91
+ }
92
+ var KyClient = class {
93
+ constructor(options = {}) {
94
+ __publicField(this, "_instance");
95
+ __publicField(this, "businessConfig");
96
+ __publicField(this, "errorConfig");
97
+ __publicField(this, "errorHandlers");
98
+ __publicField(this, "context");
99
+ __publicField(this, "disableDefaultErrorNotification");
100
+ __publicField(this, "get", (url, options) => {
101
+ return this.makeRequest("GET", url, void 0, options);
102
+ });
103
+ __publicField(this, "post", (url, data, options) => {
104
+ return this.makeRequest("POST", url, data, options);
105
+ });
106
+ __publicField(this, "put", (url, data, options) => {
107
+ return this.makeRequest("PUT", url, data, options);
108
+ });
109
+ __publicField(this, "delete", (url, options) => {
110
+ return this.makeRequest("DELETE", url, void 0, options);
111
+ });
112
+ __publicField(this, "patch", (url, data, options) => {
113
+ return this.makeRequest("PATCH", url, data, options);
114
+ });
115
+ __publicField(this, "options", (url, requestOptions) => {
116
+ return this.makeRequest("OPTIONS", url, void 0, requestOptions);
117
+ });
118
+ __publicField(this, "head", (url, requestOptions) => {
119
+ return this.makeRequest("HEAD", url, void 0, requestOptions);
120
+ });
121
+ __publicField(this, "request", (requestOptions) => {
122
+ const { url, ...requestOpts } = requestOptions;
123
+ return this.makeRequest(requestOpts.method || "GET", url, void 0, requestOpts);
124
+ });
125
+ const {
126
+ baseURL,
127
+ successCodes,
128
+ statusFields,
129
+ errorFields,
130
+ extractErrorMessage: customExtractErrorMessage,
131
+ onUnauthorized: customOnUnauthorized,
132
+ onForbidden: customOnForbidden,
133
+ onUnregistered: customOnUnregistered,
134
+ onError: customOnError,
135
+ onNetworkError: customOnNetworkError,
136
+ isSuccess: customIsSuccess,
137
+ disableDefaultErrorNotification = false,
138
+ context
139
+ } = options;
140
+ this.context = context;
141
+ this.disableDefaultErrorNotification = disableDefaultErrorNotification;
142
+ this.businessConfig = {
143
+ successCodes,
144
+ statusFields,
145
+ isSuccess: customIsSuccess
146
+ };
147
+ this.errorConfig = {
148
+ errorFields,
149
+ extractErrorMessage: customExtractErrorMessage
150
+ };
151
+ this.errorHandlers = {
152
+ onUnauthorized: customOnUnauthorized,
153
+ onForbidden: customOnForbidden,
154
+ onUnregistered: customOnUnregistered,
155
+ onError: customOnError,
156
+ onNetworkError: customOnNetworkError
157
+ };
158
+ this._instance = ky.create({
159
+ prefixUrl: baseURL ?? context?.apiBaseUrl,
160
+ retry: 0,
161
+ timeout: REQUEST_TIMEOUT,
162
+ hooks: {
163
+ beforeRequest: [this.handleBeforeRequest.bind(this)],
164
+ beforeError: [this.handleBeforeError.bind(this)]
165
+ }
166
+ });
167
+ }
168
+ /** 获取 ky 实例(用于高级用法) */
169
+ get instance() {
170
+ return this._instance;
171
+ }
172
+ /**
173
+ * 通用请求处理函数
174
+ */
175
+ async makeRequest(method, url, data, requestOptions) {
176
+ const { responseType = "json", ...kyOptions } = requestOptions || {};
177
+ const finalOptions = {
178
+ ...kyOptions,
179
+ hooks: {
180
+ ...kyOptions.hooks,
181
+ afterResponse: [...kyOptions.hooks?.afterResponse || [], this.createResponseHandler(responseType)]
182
+ }
183
+ };
184
+ let response;
185
+ if (data) {
186
+ if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob || typeof data === "string" || data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
187
+ response = await this._instance(url, { method, body: data, ...finalOptions });
188
+ } else {
189
+ response = await this._instance(url, { method, json: data, ...finalOptions });
190
+ }
191
+ } else {
192
+ response = await this._instance(url, { method, ...finalOptions });
193
+ }
194
+ return processResponseByType(response, responseType);
195
+ }
196
+ /**
197
+ * 创建响应处理函数
198
+ */
199
+ createResponseHandler(responseType) {
200
+ return async (_request, _options, response) => {
201
+ if (responseType === "blob" || responseType === "arrayBuffer" || responseType === "text" || responseType === "formData") {
202
+ return response;
203
+ }
204
+ let data;
205
+ try {
206
+ data = await response.clone().json();
207
+ } catch {
208
+ return response;
209
+ }
210
+ if (isSuccessResponse(data, response.status, this.businessConfig)) {
211
+ return new Response(JSON.stringify(data), {
212
+ status: response.status,
213
+ statusText: response.statusText,
214
+ headers: response.headers
215
+ });
216
+ }
217
+ const errorMessage = extractErrorMessage(data, this.errorConfig);
218
+ if (!this.disableDefaultErrorNotification && !this.errorHandlers.onError && this.context?.notifyError) {
219
+ this.context.notifyError("Request failed", errorMessage);
220
+ }
221
+ if (this.errorHandlers.onError) {
222
+ this.errorHandlers.onError(response.status, data, errorMessage);
223
+ }
224
+ const error = new Error(errorMessage);
225
+ error.response = response;
226
+ error.data = data;
227
+ throw error;
228
+ };
229
+ }
230
+ /**
231
+ * 请求前处理:设置认证和 appId headers
232
+ */
233
+ handleBeforeRequest(request) {
234
+ const { token, isGlobalMode, appId } = this.context || {};
235
+ if (token) {
236
+ request.headers.set("Authorization", `Bearer ${token}`);
237
+ }
238
+ if (!request.headers.has(APP_ID_HEADER)) {
239
+ if (isGlobalMode || !appId) {
240
+ request.headers.set(APP_ID_HEADER, "global");
241
+ } else {
242
+ request.headers.set(APP_ID_HEADER, encodeURIComponent(String(appId)));
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * 错误前处理:处理 HTTP 状态码错误
248
+ */
249
+ async handleBeforeError(error) {
250
+ const { response } = error;
251
+ if (response) {
252
+ const status = response.status;
253
+ let data;
254
+ try {
255
+ const contentType = response.headers.get("content-type") || "";
256
+ if (contentType.includes("application/json") || contentType.startsWith("text/")) {
257
+ data = await response.clone().json();
258
+ }
259
+ } catch {
260
+ }
261
+ this.handleHttpStatusError(status, data);
262
+ } else {
263
+ if (this.errorHandlers.onNetworkError) {
264
+ this.errorHandlers.onNetworkError(error);
265
+ } else if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
266
+ this.context.notifyError("Network Error", error.message || "Network request failed");
267
+ }
268
+ }
269
+ return error;
270
+ }
271
+ /**
272
+ * 处理 HTTP 状态码错误
273
+ */
274
+ handleHttpStatusError(status, data) {
275
+ switch (status) {
276
+ case HTTP_STATUS.UNAUTHORIZED:
277
+ if (this.errorHandlers.onUnauthorized) {
278
+ this.errorHandlers.onUnauthorized(data);
279
+ } else {
280
+ this.defaultHandleUnauthorized();
281
+ }
282
+ break;
283
+ case HTTP_STATUS.UNREGISTERED:
284
+ if (this.errorHandlers.onUnregistered) {
285
+ this.errorHandlers.onUnregistered(data);
286
+ } else {
287
+ this.defaultHandleUnregistered();
288
+ }
289
+ break;
290
+ case HTTP_STATUS.FORBIDDEN:
291
+ if (this.errorHandlers.onForbidden) {
292
+ this.errorHandlers.onForbidden(data);
293
+ } else {
294
+ this.defaultHandleForbidden();
295
+ }
296
+ break;
297
+ default: {
298
+ const errorMessage = extractErrorMessage(data, this.errorConfig) || `HTTP ${status} Error`;
299
+ if (this.errorHandlers.onError) {
300
+ this.errorHandlers.onError(status, data, errorMessage);
301
+ } else if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
302
+ this.context.notifyError("Request failed", errorMessage);
303
+ }
304
+ break;
305
+ }
306
+ }
307
+ }
308
+ /**
309
+ * 默认处理未授权错误
310
+ */
311
+ defaultHandleUnauthorized() {
312
+ const { clear, loginPath } = this.context || {};
313
+ if (clear && loginPath) {
314
+ clear();
315
+ window.location.href = loginPath;
316
+ }
317
+ }
318
+ /**
319
+ * 默认处理未注册错误
320
+ */
321
+ defaultHandleUnregistered() {
322
+ const { clear, loginPath } = this.context || {};
323
+ if (clear && loginPath) {
324
+ clear();
325
+ const url = new URL(loginPath, window.location.origin);
326
+ url.searchParams.set("unregistered", "true");
327
+ window.location.href = url.toString();
328
+ }
329
+ }
330
+ /**
331
+ * 默认处理禁止访问错误
332
+ */
333
+ defaultHandleForbidden() {
334
+ if (!this.disableDefaultErrorNotification && this.context?.notifyError) {
335
+ this.context.notifyError("\u8BBF\u95EE\u88AB\u7981\u6B62", "\u60A8\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6B64\u8D44\u6E90\u3002");
336
+ }
337
+ }
338
+ /**
339
+ * 更新上下文信息
340
+ * 用于在运行时更新 context(例如在 React 组件中从 context 获取最新信息)
341
+ */
342
+ updateContext(context) {
343
+ this.context = context;
344
+ }
345
+ };
346
+ new KyClient();
10
347
  var ToolkitsContext = createContext(null);
11
348
  function useToolkitsStore(selector) {
12
349
  const store = useContext(ToolkitsContext);