@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autional/shared",
3
- "version": "0.1.0-rc.39",
3
+ "version": "0.1.0-rc.40",
4
4
  "description": "Autional shared layer — API client, auth, types, hooks, utils",
5
5
  "license": "AGPL-3.0",
6
6
  "main": "./src/index.ts",
@@ -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
- describe('extractApiError message 键链(UP-17-B / AC-401)', () => {
8
- it('title 优先:Problem 契约(title/detail/code)→ 取 title', () => {
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: '平台级访问受限', detail: '需要平台角色' } },
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('detail 兜底:无 message/title 时取 detail', () => {
18
- const err = { response: { data: { detail: '令牌已过期' } } };
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 键链不回归(title 优先于 detail)
56
- expect(out.message).toBe('Invalid Parameter');
72
+ // U380:键链为 message → detail → title
73
+ expect(out.message).toBe('state not found');
57
74
  });
58
75
 
59
76
  it('响应拦截器深 camel 后(i18nKey)同样识别', () => {
@@ -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。键链:message → title → detail → err.message。
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?.title || data?.detail || (err as any)?.message || defaultMsg,
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
  }