@autional/shared 0.1.0-rc.39 → 0.1.0-rc.40
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/LICENSE +661 -661
- package/package.json +1 -1
- package/src/utils/__tests__/error.test.ts +26 -9
- package/src/utils/error.ts +4 -2
package/package.json
CHANGED
|
@@ -4,19 +4,36 @@ import { extractApiError, extractApiErrorMessage } from '../error';
|
|
|
4
4
|
// UP-17-B 回归锁(AC-401):extractApiError message 键链。
|
|
5
5
|
// 后端 Problem 契约(service-core/base/dto/problem.go)为 title 必填 / detail / code / i18n_key,无 message;
|
|
6
6
|
// 只认 message 会把 Problem 类错误整类退化为 defaultMsg。
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// U380 回归锁:detail 优先于 title,对齐 Problem.GetMessage()(Detail 非空优先)。
|
|
8
|
+
describe('extractApiError message 键链(UP-17-B / AC-401 / U380)', () => {
|
|
9
|
+
it('detail 优先:Problem 契约(title/detail/code)→ 取 detail', () => {
|
|
9
10
|
const err = {
|
|
10
|
-
response: { data: { code: 403, title: '
|
|
11
|
+
response: { data: { code: 403, title: 'Platform Access Denied', detail: '需要平台角色' } },
|
|
11
12
|
};
|
|
12
13
|
const out = extractApiError(err, 'fallback');
|
|
13
|
-
expect(out.message).toBe('
|
|
14
|
+
expect(out.message).toBe('需要平台角色');
|
|
14
15
|
expect(out.code).toBe(403);
|
|
15
16
|
});
|
|
16
17
|
|
|
17
|
-
it('
|
|
18
|
-
const err = { response: { data: {
|
|
19
|
-
expect(extractApiError(err, 'fallback').message).toBe('
|
|
18
|
+
it('title 兜底:无 message/detail 时取 title', () => {
|
|
19
|
+
const err = { response: { data: { title: 'Invalid Request' } } };
|
|
20
|
+
expect(extractApiError(err, 'fallback').message).toBe('Invalid Request');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('U380:英文 title + 中文 detail → 中文 detail 胜出', () => {
|
|
24
|
+
const err = {
|
|
25
|
+
response: {
|
|
26
|
+
data: {
|
|
27
|
+
code: 61040050,
|
|
28
|
+
title: 'push challenge not found',
|
|
29
|
+
detail: '推送挑战未找到',
|
|
30
|
+
i18n_key: 'error.push_challenge_not_found',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const out = extractApiError(err, 'fallback');
|
|
35
|
+
expect(out.message).toBe('推送挑战未找到');
|
|
36
|
+
expect(out.i18nKey).toBe('error.push_challenge_not_found');
|
|
20
37
|
});
|
|
21
38
|
|
|
22
39
|
it('皆无回落 err.message,再皆无回落 defaultMsg', () => {
|
|
@@ -52,8 +69,8 @@ describe('extractApiError i18n_key 透出(AUTH-46)', () => {
|
|
|
52
69
|
};
|
|
53
70
|
const out = extractApiError(err, 'fallback');
|
|
54
71
|
expect(out.i18nKey).toBe('error.oauth_state_missing');
|
|
55
|
-
// message
|
|
56
|
-
expect(out.message).toBe('
|
|
72
|
+
// U380:键链为 message → detail → title
|
|
73
|
+
expect(out.message).toBe('state not found');
|
|
57
74
|
});
|
|
58
75
|
|
|
59
76
|
it('响应拦截器深 camel 后(i18nKey)同样识别', () => {
|
package/src/utils/error.ts
CHANGED
|
@@ -17,13 +17,15 @@ export function extractApiErrorMessage(err: unknown, defaultMsg: string): string
|
|
|
17
17
|
|
|
18
18
|
export function extractApiError(err: unknown, defaultMsg: string): ExtractedApiError {
|
|
19
19
|
// UP-17-B:后端 Problem 契约(service-core/base/dto/problem.go)字段为 title(必填)/ detail / code / i18n_key,
|
|
20
|
-
// **没有 message** —— 只认 message 会把整类后端错误退化成 defaultMsg
|
|
20
|
+
// **没有 message** —— 只认 message 会把整类后端错误退化成 defaultMsg。
|
|
21
|
+
// U380:键链 message → detail → title,对齐 Problem.GetMessage()(Detail 非空优先),
|
|
22
|
+
// 避免英文 title 压过本地化 detail。
|
|
21
23
|
// 继续用 `||`(而非 `??`):空串语义按「缺省」处理,与既有实现一致。
|
|
22
24
|
// AUTH-46:附加透出 i18n_key(响应拦截器深 camel 后为 i18nKey,两者都认)。
|
|
23
25
|
const data = (err as any)?.response?.data;
|
|
24
26
|
return {
|
|
25
27
|
code: data?.code || 'UNKNOWN',
|
|
26
|
-
message: data?.message || data?.
|
|
28
|
+
message: data?.message || data?.detail || data?.title || (err as any)?.message || defaultMsg,
|
|
27
29
|
i18nKey: data?.i18n_key || data?.i18nKey || undefined,
|
|
28
30
|
};
|
|
29
31
|
}
|