@aithe/aithe-ui 26.3.1 → 26.3.2
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 +8 -5
- package/dist/apps/api/i18n/de-DE.d.ts.map +1 -1
- package/dist/apps/api/i18n/de-DE.js +1 -0
- package/dist/apps/api/i18n/en-US.d.ts.map +1 -1
- package/dist/apps/api/i18n/en-US.js +1 -0
- package/dist/apps/api/i18n/es-ES.d.ts.map +1 -1
- package/dist/apps/api/i18n/es-ES.js +1 -0
- package/dist/apps/api/i18n/fr-FR.d.ts.map +1 -1
- package/dist/apps/api/i18n/fr-FR.js +1 -0
- package/dist/apps/api/i18n/ja-JP.d.ts.map +1 -1
- package/dist/apps/api/i18n/ja-JP.js +1 -0
- package/dist/apps/api/i18n/ko-KR.d.ts.map +1 -1
- package/dist/apps/api/i18n/ko-KR.js +1 -0
- package/dist/apps/api/i18n/pt-BR.d.ts.map +1 -1
- package/dist/apps/api/i18n/pt-BR.js +1 -0
- package/dist/apps/api/i18n/zh-CN.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-CN.js +1 -0
- package/dist/apps/api/i18n/zh-HK.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-HK.js +1 -0
- package/dist/apps/api/i18n/zh-TW.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-TW.js +1 -0
- package/dist/apps/api/pages/docs.d.ts.map +1 -1
- package/dist/apps/api/pages/docs.js +2 -0
- package/dist/apps/demo/app.d.ts.map +1 -1
- package/dist/apps/demo/app.js +2 -0
- package/dist/apps/demo/i18n/de-DE.d.ts.map +1 -1
- package/dist/apps/demo/i18n/de-DE.js +20 -0
- package/dist/apps/demo/i18n/en-US.d.ts.map +1 -1
- package/dist/apps/demo/i18n/en-US.js +20 -0
- package/dist/apps/demo/i18n/es-ES.d.ts.map +1 -1
- package/dist/apps/demo/i18n/es-ES.js +20 -0
- package/dist/apps/demo/i18n/fr-FR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/fr-FR.js +20 -0
- package/dist/apps/demo/i18n/ja-JP.d.ts.map +1 -1
- package/dist/apps/demo/i18n/ja-JP.js +20 -0
- package/dist/apps/demo/i18n/ko-KR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/ko-KR.js +20 -0
- package/dist/apps/demo/i18n/pt-BR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/pt-BR.js +20 -0
- package/dist/apps/demo/i18n/zh-CN.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-CN.js +20 -0
- package/dist/apps/demo/i18n/zh-HK.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-HK.js +20 -0
- package/dist/apps/demo/i18n/zh-TW.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-TW.js +20 -0
- package/dist/apps/demo/pages/autoform.d.ts.map +1 -1
- package/dist/apps/demo/pages/autoform.js +10 -0
- package/dist/apps/demo/pages/autoview.d.ts +3 -0
- package/dist/apps/demo/pages/autoview.d.ts.map +1 -0
- package/dist/apps/demo/pages/autoview.js +310 -0
- package/dist/apps/demo/pages/form.d.ts.map +1 -1
- package/dist/apps/demo/pages/form.js +20 -0
- package/dist/components/data/tree-menu.js +1 -1
- package/dist/components/display/autoview.d.ts +139 -0
- package/dist/components/display/autoview.d.ts.map +1 -0
- package/dist/components/display/autoview.js +460 -0
- package/dist/components/display/desc.d.ts +4 -0
- package/dist/components/display/desc.d.ts.map +1 -1
- package/dist/components/display/desc.js +45 -3
- package/dist/components/form/autoform-item.d.ts +6 -0
- package/dist/components/form/autoform-item.d.ts.map +1 -1
- package/dist/components/form/autoform-item.js +34 -4
- package/dist/components/form/combobox.d.ts +4 -0
- package/dist/components/form/combobox.d.ts.map +1 -1
- package/dist/components/form/combobox.js +56 -13
- package/dist/components/form/select.d.ts +4 -0
- package/dist/components/form/select.d.ts.map +1 -1
- package/dist/components/form/select.js +84 -40
- package/dist/components/navigation/sub-menu.d.ts.map +1 -1
- package/dist/components/navigation/sub-menu.js +0 -1
- package/dist/core/autoform/autoview.d.ts +86 -0
- package/dist/core/autoform/autoview.d.ts.map +1 -0
- package/dist/core/autoform/autoview.js +37 -0
- package/dist/core/autoform/index.d.ts +2 -0
- package/dist/core/autoform/index.d.ts.map +1 -1
- package/dist/core/autoform/index.js +1 -0
- package/dist/core/datahub/__tests__/force-options.test.d.ts +8 -0
- package/dist/core/datahub/__tests__/force-options.test.d.ts.map +1 -0
- package/dist/core/datahub/__tests__/force-options.test.js +161 -0
- package/dist/core/datahub/core/api-styles.d.ts.map +1 -1
- package/dist/core/datahub/core/api-styles.js +5 -0
- package/dist/core/datahub/core/datahub-core.d.ts +50 -0
- package/dist/core/datahub/core/datahub-core.d.ts.map +1 -1
- package/dist/core/datahub/core/datahub-core.js +160 -81
- package/dist/core/datahub/types.d.ts +18 -0
- package/dist/core/datahub/types.d.ts.map +1 -1
- package/dist/core/markdown/plugins.d.ts +2 -1
- package/dist/core/markdown/plugins.d.ts.map +1 -1
- package/dist/core/markdown/plugins.js +168 -21
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1267 -753
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +282 -138
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/i18n/locales/de-DE.d.ts.map +1 -1
- package/dist/styles/i18n/locales/de-DE.js +3 -0
- package/dist/styles/i18n/locales/en-US.d.ts.map +1 -1
- package/dist/styles/i18n/locales/en-US.js +3 -0
- package/dist/styles/i18n/locales/es-ES.d.ts.map +1 -1
- package/dist/styles/i18n/locales/es-ES.js +3 -0
- package/dist/styles/i18n/locales/fr-FR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/fr-FR.js +3 -0
- package/dist/styles/i18n/locales/ja-JP.d.ts.map +1 -1
- package/dist/styles/i18n/locales/ja-JP.js +3 -0
- package/dist/styles/i18n/locales/ko-KR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/ko-KR.js +3 -0
- package/dist/styles/i18n/locales/pt-BR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/pt-BR.js +3 -0
- package/dist/styles/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-CN.js +3 -0
- package/dist/styles/i18n/locales/zh-HK.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-HK.js +3 -0
- package/dist/styles/i18n/locales/zh-TW.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-TW.js +3 -0
- package/docs/api/display/autoview.md +277 -0
- package/docs/api/display/desc.md +56 -14
- package/docs/api/form/autoform-item.md +16 -1
- package/docs/api/form/autoform.md +3 -2
- package/docs/api/form/combobox.md +27 -7
- package/docs/api/form/select.md +30 -8
- package/docs/api/summary.md +1 -0
- package/docs/autoform.md +1 -32
- package/docs/changelog/CHANGELOG.md +76 -1
- package/docs/changelog/VERSION_26.3.1.md +5 -5
- package/docs/changelog/VERSION_26.3.2.md +852 -0
- package/docs/datahub.md +3 -0
- package/docs/framework-integration.md +1 -1
- package/docs/guide.md +7 -6
- package/docs/i18n.md +1 -3
- package/docs/issue/26.3.2/issue_26.3.2.1.md +46 -0
- package/docs/issue/26.3.2/issue_26.3.2.2.md +82 -0
- package/docs/issue/26.3.2/issue_26.3.2.3.md +57 -0
- package/docs/issue/26.3.2/issue_26.3.2.4.md +43 -0
- package/docs/issue/AGENTS.md +24 -3
- package/docs/markdown.md +2 -2
- package/docs/quickstart.md +3 -3
- package/docs/theming.md +5 -4
- package/package.json +1 -1
- package/dist/components/navigation/dropdown.d.ts +0 -56
- package/dist/components/navigation/dropdown.d.ts.map +0 -1
- /package/docs/issue/{issue_26.2.2.1.md → 26.2.2/issue_26.2.2.1.md} +0 -0
- /package/docs/issue/{issue_26.2.2.2.md → 26.2.2/issue_26.2.2.2.md} +0 -0
- /package/docs/issue/{issue_26.2.2.3.md → 26.2.2/issue_26.2.2.3.md} +0 -0
- /package/docs/issue/{issue_26.2.2.4.md → 26.2.2/issue_26.2.2.4.md} +0 -0
- /package/docs/issue/{issue_26.2.3.1.md → 26.2.3/issue_26.2.3.1.md} +0 -0
- /package/docs/issue/{issue_26.2.3.10.md → 26.2.3/issue_26.2.3.10.md} +0 -0
- /package/docs/issue/{issue_26.2.3.11.md → 26.2.3/issue_26.2.3.11.md} +0 -0
- /package/docs/issue/{issue_26.2.3.12.md → 26.2.3/issue_26.2.3.12.md} +0 -0
- /package/docs/issue/{issue_26.2.3.13.md → 26.2.3/issue_26.2.3.13.md} +0 -0
- /package/docs/issue/{issue_26.2.3.14.md → 26.2.3/issue_26.2.3.14.md} +0 -0
- /package/docs/issue/{issue_26.2.3.15.md → 26.2.3/issue_26.2.3.15.md} +0 -0
- /package/docs/issue/{issue_26.2.3.16.md → 26.2.3/issue_26.2.3.16.md} +0 -0
- /package/docs/issue/{issue_26.2.3.2.md → 26.2.3/issue_26.2.3.2.md} +0 -0
- /package/docs/issue/{issue_26.2.3.3.md → 26.2.3/issue_26.2.3.3.md} +0 -0
- /package/docs/issue/{issue_26.2.3.4.md → 26.2.3/issue_26.2.3.4.md} +0 -0
- /package/docs/issue/{issue_26.2.3.5.md → 26.2.3/issue_26.2.3.5.md} +0 -0
- /package/docs/issue/{issue_26.2.3.6.md → 26.2.3/issue_26.2.3.6.md} +0 -0
- /package/docs/issue/{issue_26.2.3.7.md → 26.2.3/issue_26.2.3.7.md} +0 -0
- /package/docs/issue/{issue_26.2.3.8.md → 26.2.3/issue_26.2.3.8.md} +0 -0
- /package/docs/issue/{issue_26.2.3.9.md → 26.2.3/issue_26.2.3.9.md} +0 -0
- /package/docs/issue/{issue_26.3.1.0.md → 26.3.1/issue_26.3.1.0.md} +0 -0
- /package/docs/issue/{issue_26.3.1.1.md → 26.3.1/issue_26.3.1.1.md} +0 -0
- /package/docs/issue/{issue_26.3.1.2.md → 26.3.1/issue_26.3.1.2.md} +0 -0
- /package/docs/issue/{issue_26.3.1.3.md → 26.3.1/issue_26.3.1.3.md} +0 -0
- /package/docs/issue/{issue_26.3.1.4.md → 26.3.1/issue_26.3.1.4.md} +0 -0
- /package/docs/issue/{issue_26.3.1.5.md → 26.3.1/issue_26.3.1.5.md} +0 -0
- /package/docs/issue/{issue_26.3.1.6.md → 26.3.1/issue_26.3.1.6.md} +0 -0
- /package/docs/issue/{issue_26.3.1.7.md → 26.3.1/issue_26.3.1.7.md} +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DataHubCore forceDedup / forceCache 选项测试
|
|
3
|
+
* @description 验证当 URL 不以 query/list/get 结尾时,
|
|
4
|
+
* forceDedup 和 forceCache 选项能强制启用去重和缓存,
|
|
5
|
+
* 且不会被幂等守卫拦截。
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
8
|
+
import { DataHubCore } from '../../datahub/core/datahub-core';
|
|
9
|
+
/** 构造一个可控的假适配器 / Build a controllable fake adapter */
|
|
10
|
+
function createFakeAdapter() {
|
|
11
|
+
const adapter = {
|
|
12
|
+
name: 'fake',
|
|
13
|
+
callCount: 0,
|
|
14
|
+
reset() {
|
|
15
|
+
this.callCount = 0;
|
|
16
|
+
},
|
|
17
|
+
async request(req) {
|
|
18
|
+
this.callCount++;
|
|
19
|
+
return { ok: true, status: 200, data: { url: req.url, n: this.callCount } };
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
return adapter;
|
|
23
|
+
}
|
|
24
|
+
/** 构造一个使用 raw APIStyle 的 DataHubCore(不做业务协议解析)/ Build a DataHubCore with raw APIStyle */
|
|
25
|
+
function createCore(adapter) {
|
|
26
|
+
const core = new DataHubCore({ defaultCacheTTL: 1000, defaultAdapter: adapter.name });
|
|
27
|
+
core.registerAdapter(adapter);
|
|
28
|
+
core.setAPIStyle('raw');
|
|
29
|
+
return core;
|
|
30
|
+
}
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
// 每个用例前清空全局缓存和去重记录,避免用例间相互干扰
|
|
33
|
+
// Clear global cache and dedup records before each case to avoid cross-test interference
|
|
34
|
+
});
|
|
35
|
+
describe('DataHubCore - forceDedup', () => {
|
|
36
|
+
it('非 query URL 默认走幂等守卫,并发第二个请求被拒绝', async () => {
|
|
37
|
+
const fake = createFakeAdapter();
|
|
38
|
+
const core = createCore(fake);
|
|
39
|
+
// /system/roles/viewer 结尾不是 query/list/get,默认判为 submit
|
|
40
|
+
const p1 = core.request('/system/roles/viewer', undefined, { method: 'GET' });
|
|
41
|
+
const p2 = core.request('/system/roles/viewer', undefined, { method: 'GET' });
|
|
42
|
+
// p2 应被幂等守卫拒绝
|
|
43
|
+
await expect(p2).rejects.toThrow(/duplicate submit/);
|
|
44
|
+
await p1;
|
|
45
|
+
expect(fake.callCount).toBe(1);
|
|
46
|
+
});
|
|
47
|
+
it('forceDedup: true 时,非 query URL 并发请求被去重,只发一次', async () => {
|
|
48
|
+
const fake = createFakeAdapter();
|
|
49
|
+
const core = createCore(fake);
|
|
50
|
+
core.clearDedup();
|
|
51
|
+
core.clearIdempotent();
|
|
52
|
+
const p1 = core.request('/system/roles/viewer', undefined, {
|
|
53
|
+
method: 'GET',
|
|
54
|
+
forceDedup: true,
|
|
55
|
+
});
|
|
56
|
+
const p2 = core.request('/system/roles/viewer', undefined, {
|
|
57
|
+
method: 'GET',
|
|
58
|
+
forceDedup: true,
|
|
59
|
+
});
|
|
60
|
+
const [r1, r2] = await Promise.all([p1, p2]);
|
|
61
|
+
// 两个调用共享同一结果,只发一次实际请求
|
|
62
|
+
expect(fake.callCount).toBe(1);
|
|
63
|
+
expect(r1).toEqual(r2);
|
|
64
|
+
});
|
|
65
|
+
it('forceDedup 不影响不同 URL 的请求', async () => {
|
|
66
|
+
const fake = createFakeAdapter();
|
|
67
|
+
const core = createCore(fake);
|
|
68
|
+
core.clearDedup();
|
|
69
|
+
core.clearIdempotent();
|
|
70
|
+
await Promise.all([
|
|
71
|
+
core.request('/system/roles/a', undefined, { method: 'GET', forceDedup: true }),
|
|
72
|
+
core.request('/system/roles/b', undefined, { method: 'GET', forceDedup: true }),
|
|
73
|
+
]);
|
|
74
|
+
expect(fake.callCount).toBe(2);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('DataHubCore - forceCache', () => {
|
|
78
|
+
it('非 query URL 默认不缓存,两次请求发两次', async () => {
|
|
79
|
+
const fake = createFakeAdapter();
|
|
80
|
+
const core = createCore(fake);
|
|
81
|
+
core.clearCache();
|
|
82
|
+
core.clearIdempotent();
|
|
83
|
+
await core.request('/system/roles/viewer', undefined, { method: 'GET', skipIdempotent: true });
|
|
84
|
+
await core.request('/system/roles/viewer', undefined, { method: 'GET', skipIdempotent: true });
|
|
85
|
+
expect(fake.callCount).toBe(2);
|
|
86
|
+
});
|
|
87
|
+
it('forceCache: true 时,非 query URL 第二次请求命中缓存', async () => {
|
|
88
|
+
const fake = createFakeAdapter();
|
|
89
|
+
const core = createCore(fake);
|
|
90
|
+
core.clearCache();
|
|
91
|
+
core.clearIdempotent();
|
|
92
|
+
const r1 = await core.request('/system/roles/viewer', undefined, {
|
|
93
|
+
method: 'GET',
|
|
94
|
+
forceCache: true,
|
|
95
|
+
skipIdempotent: true,
|
|
96
|
+
});
|
|
97
|
+
const r2 = await core.request('/system/roles/viewer', undefined, {
|
|
98
|
+
method: 'GET',
|
|
99
|
+
forceCache: true,
|
|
100
|
+
skipIdempotent: true,
|
|
101
|
+
});
|
|
102
|
+
// 第二次命中缓存,只发一次实际请求
|
|
103
|
+
expect(fake.callCount).toBe(1);
|
|
104
|
+
expect(r1).toEqual(r2);
|
|
105
|
+
});
|
|
106
|
+
it('forceCache 配合 skipCache 时不命中缓存', async () => {
|
|
107
|
+
const fake = createFakeAdapter();
|
|
108
|
+
const core = createCore(fake);
|
|
109
|
+
core.clearCache();
|
|
110
|
+
core.clearIdempotent();
|
|
111
|
+
await core.request('/system/roles/viewer', undefined, {
|
|
112
|
+
method: 'GET',
|
|
113
|
+
forceCache: true,
|
|
114
|
+
skipIdempotent: true,
|
|
115
|
+
});
|
|
116
|
+
await core.request('/system/roles/viewer', undefined, {
|
|
117
|
+
method: 'GET',
|
|
118
|
+
forceCache: true,
|
|
119
|
+
skipCache: true,
|
|
120
|
+
skipIdempotent: true,
|
|
121
|
+
});
|
|
122
|
+
expect(fake.callCount).toBe(2);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
describe('DataHubCore - forceDedup + forceCache 跳过幂等守卫', () => {
|
|
126
|
+
it('forceDedup 为 true 时,即使 URL 被判为 submit 也不会触发幂等守卫', async () => {
|
|
127
|
+
const fake = createFakeAdapter();
|
|
128
|
+
const core = createCore(fake);
|
|
129
|
+
core.clearDedup();
|
|
130
|
+
core.clearIdempotent();
|
|
131
|
+
// 串行两次请求(不并发),验证幂等守卫不会拦截第二次
|
|
132
|
+
await core.request('/system/roles/viewer', undefined, {
|
|
133
|
+
method: 'GET',
|
|
134
|
+
forceDedup: true,
|
|
135
|
+
});
|
|
136
|
+
// 第二次请求不应被幂等守卫拒绝(dedup 记录已清理,会重新发请求)
|
|
137
|
+
const r2 = await core.request('/system/roles/viewer', undefined, {
|
|
138
|
+
method: 'GET',
|
|
139
|
+
forceDedup: true,
|
|
140
|
+
});
|
|
141
|
+
expect(r2.ok).toBe(true);
|
|
142
|
+
expect(fake.callCount).toBe(2);
|
|
143
|
+
});
|
|
144
|
+
it('forceCache 为 true 时,即使 URL 被判为 submit 也不会触发幂等守卫', async () => {
|
|
145
|
+
const fake = createFakeAdapter();
|
|
146
|
+
const core = createCore(fake);
|
|
147
|
+
core.clearCache();
|
|
148
|
+
core.clearIdempotent();
|
|
149
|
+
await core.request('/system/roles/viewer', undefined, {
|
|
150
|
+
method: 'GET',
|
|
151
|
+
forceCache: true,
|
|
152
|
+
});
|
|
153
|
+
// 第二次命中缓存,且不被幂等守卫拦截
|
|
154
|
+
const r2 = await core.request('/system/roles/viewer', undefined, {
|
|
155
|
+
method: 'GET',
|
|
156
|
+
forceCache: true,
|
|
157
|
+
});
|
|
158
|
+
expect(r2.ok).toBe(true);
|
|
159
|
+
expect(fake.callCount).toBe(1);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-styles.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/core/api-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"api-styles.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/core/api-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,qBAAqB,CAAC;AAqI7B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEzE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C"}
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
const defaultStyle = {
|
|
15
15
|
name: 'default',
|
|
16
16
|
onRequest(req) {
|
|
17
|
+
// GET 请求不发送 body,无需包装 data,避免触发 "GET request with body is unusual" 警告
|
|
18
|
+
// GET requests do not send a body, so skip wrapping data to avoid the "GET request with body is unusual" warning
|
|
19
|
+
if (req.options.method === 'GET') {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
17
22
|
req.data = { data: req.data };
|
|
18
23
|
},
|
|
19
24
|
onResponse(res) {
|
|
@@ -107,6 +107,56 @@ export declare class DataHubCore {
|
|
|
107
107
|
* if (biz.code === 'Ok') { /* handle success *\/ }
|
|
108
108
|
*/
|
|
109
109
|
request<T = unknown>(url: string, data?: unknown, options?: DataHubRequestOptions): Promise<DataHubAdapterResponse<T>>;
|
|
110
|
+
/**
|
|
111
|
+
* 应用全局响应拦截器(命中缓存与实际请求路径共用)。
|
|
112
|
+
* Apply global response interceptor (shared by cache-hit and real-request paths).
|
|
113
|
+
*/
|
|
114
|
+
private applyResponseInterceptor;
|
|
115
|
+
/**
|
|
116
|
+
* 实际执行请求:适配器调用 + 响应拦截 + HTTP 错误处理 + 统一响应处理 + 缓存写入。
|
|
117
|
+
* Execute the request: adapter call + response interceptor + HTTP error handling +
|
|
118
|
+
* unified response handling + cache write.
|
|
119
|
+
*/
|
|
120
|
+
private executeRequest;
|
|
121
|
+
/**
|
|
122
|
+
* 构造 HTTP 传输层错误:优先用 APIStyle 解析响应体,回退到 transport error。
|
|
123
|
+
* Build HTTP transport error: try APIStyle first, fall back to transport error.
|
|
124
|
+
*/
|
|
125
|
+
private buildHttpError;
|
|
126
|
+
/**
|
|
127
|
+
* 是否可缓存:strategy 默认判定,或 forceCache 强制启用。
|
|
128
|
+
* Whether cacheable: by strategy, or force-enabled by forceCache.
|
|
129
|
+
*/
|
|
130
|
+
private isCacheable;
|
|
131
|
+
/**
|
|
132
|
+
* 是否可去重:strategy 默认判定,或 forceDedup 强制启用。
|
|
133
|
+
* Whether dedupable: by strategy, or force-enabled by forceDedup.
|
|
134
|
+
*/
|
|
135
|
+
private isDedupable;
|
|
136
|
+
/**
|
|
137
|
+
* 是否需要幂等防护:strategy 判定为提交类、未跳过、且未被 force 选项豁免。
|
|
138
|
+
* Whether idempotent guard applies: strategy says submit, not skipped, and not
|
|
139
|
+
* exempted by forceDedup/forceCache (which mark the request as a query).
|
|
140
|
+
*/
|
|
141
|
+
private shouldGuardIdempotent;
|
|
142
|
+
/**
|
|
143
|
+
* 统一响应处理:APIStyle 转换 + isSuccess 业务校验 + 返回业务数据
|
|
144
|
+
* Unified response handling: APIStyle transform + isSuccess check + return business data
|
|
145
|
+
*
|
|
146
|
+
* 抽取该方法的目的:让「实际请求路径」与「缓存命中路径」走完全一致的响应处理逻辑,
|
|
147
|
+
* 避免缓存命中时跳过 isSuccess 校验或丢失 code/message 等字段。
|
|
148
|
+
*
|
|
149
|
+
* This method is extracted so that both the real-request path and the cache-hit path
|
|
150
|
+
* share identical response handling, avoiding skipped isSuccess checks or lost
|
|
151
|
+
* code/message fields when cache hits.
|
|
152
|
+
*
|
|
153
|
+
* @param res - 适配器返回的原始响应 / Raw response from adapter
|
|
154
|
+
* @param requestStyle - 解析后的 APIStyle / Resolved APIStyle
|
|
155
|
+
* @param traceId - 链路追踪 ID / Trace ID
|
|
156
|
+
* @param fullUrl - 完整请求 URL / Full request URL
|
|
157
|
+
* @returns 业务数据已替换的响应 / Response with business data replaced
|
|
158
|
+
*/
|
|
159
|
+
private handleResponse;
|
|
110
160
|
/** 清空所有缓存 / Clear all cache */
|
|
111
161
|
clearCache(): void;
|
|
112
162
|
/** 清空所有去重记录 / Clear all dedup records */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datahub-core.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/core/datahub-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,
|
|
1
|
+
{"version":3,"file":"datahub-core.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/core/datahub-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EAEhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,IAAI,iBAAiB,EAAyC,MAAM,qBAAqB,CAAC;AAO/G,OAAO,EAA4B,eAAe,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAenG;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,uDAAuD;IACvD,OAAO,CAAC,MAAM,CAAiB;IAC/B,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAA8B;IAE9C;;OAEG;gBACS,MAAM,GAAE,aAAkB;IAatC;;;;OAIG;IACI,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIrD;;;;OAIG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAM3D;;;;;;;;;;;;;;;OAeG;IACI,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI;IAezD;;;OAGG;IACI,WAAW,IAAI,eAAe,GAAG,SAAS;IAIjD;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;;;;;;;;;;;;;;;;;OAkBG;IACU,OAAO,CAAC,CAAC,GAAG,OAAO,EAC9B,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IA8ErC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAMhC;;;;OAIG;YACW,cAAc;IAuD5B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAoBtB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAInB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAInB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAS7B;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,cAAc;IA+BtB,+BAA+B;IACxB,UAAU,IAAI,IAAI;IAIzB,yCAAyC;IAClC,UAAU,IAAI,IAAI;IAIzB,2CAA2C;IACpC,eAAe,IAAI,IAAI;IAM9B;;OAEG;IACI,qBAAqB,CAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,qBAAqB,GAAG,IAAI,GACpE,IAAI;IAIP;;OAEG;IACI,sBAAsB,CAC3B,OAAO,EAAE,CACP,GAAG,EAAE,sBAAsB,EAC3B,GAAG,EAAE,qBAAqB,KACvB,sBAAsB,GAAG,IAAI,GACjC,IAAI;IAIP;;OAEG;IACI,eAAe,CACpB,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,qBAAqB,KAAK,IAAI,GACtE,IAAI;IAIP;;OAEG;IACI,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAIzD;;OAEG;IACI,SAAS,IAAI,QAAQ,CAAC,aAAa,CAAC;IAM3C,2DAA2D;IACpD,eAAe,yBAAmB;IAEzC,wEAAwE;IACjE,SAAS,mBAAa;IAI7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;;OAGG;IACH,OAAO,CAAC,cAAc;CA0BvB"}
|
|
@@ -195,101 +195,180 @@ export class DataHubCore {
|
|
|
195
195
|
}
|
|
196
196
|
// 6. 缓存检查:查询类请求且未跳过缓存时,尝试命中缓存
|
|
197
197
|
// Cache check: for query requests without skipCache, try to hit cache
|
|
198
|
-
|
|
198
|
+
// forceCache 选项可无视 URL 命名约定强制启用缓存
|
|
199
|
+
// forceCache option bypasses URL naming convention to force-enable caching
|
|
200
|
+
const cacheable = this.isCacheable(strategy, merged);
|
|
201
|
+
if (cacheable && !merged.skipCache) {
|
|
199
202
|
const cached = cacheGet(fullUrl, data);
|
|
200
|
-
if (cached)
|
|
201
|
-
|
|
203
|
+
if (cached) {
|
|
204
|
+
// 缓存命中:先走全局响应拦截器,再走统一响应处理(与实际请求路径保持一致)
|
|
205
|
+
// Cache hit: apply global response interceptor first, then unified response handling
|
|
206
|
+
// (consistent with the real-request path)
|
|
207
|
+
this.applyResponseInterceptor(cached, req);
|
|
208
|
+
return this.handleResponse(cached, requestStyle, traceId, fullUrl);
|
|
209
|
+
}
|
|
202
210
|
}
|
|
203
211
|
// 实际执行请求的内部函数 / Internal function that actually executes the request
|
|
204
|
-
const execute =
|
|
205
|
-
// 标记 loading 开始 / Mark loading start
|
|
206
|
-
loadingStart(fullUrl);
|
|
207
|
-
try {
|
|
208
|
-
// 7. 解析并调用适配器 / Resolve and call adapter
|
|
209
|
-
const adapter = this.resolveAdapter(merged);
|
|
210
|
-
const res = await adapter.request(req);
|
|
211
|
-
// 8. 响应拦截器 / Response interceptor
|
|
212
|
-
if (this.config.onResponse) {
|
|
213
|
-
const intercepted = this.config.onResponse(res, req);
|
|
214
|
-
if (intercepted)
|
|
215
|
-
Object.assign(res, intercepted);
|
|
216
|
-
}
|
|
217
|
-
// 9. HTTP 传输层错误处理:HTTP 非 2xx 时,优先用 APIStyle 解析响应体
|
|
218
|
-
// HTTP transport error: when !res.ok, try APIStyle first, fall back to transport error
|
|
219
|
-
if (!res.ok) {
|
|
220
|
-
if (requestStyle) {
|
|
221
|
-
const result = requestStyle.onResponse(res);
|
|
222
|
-
throw new DataHubErrorClass({
|
|
223
|
-
code: result.code ?? `HTTP_${res.status}`,
|
|
224
|
-
message: result.message || `HTTP request failed with status ${res.status}`,
|
|
225
|
-
trace: traceId,
|
|
226
|
-
status: res.status,
|
|
227
|
-
url: fullUrl,
|
|
228
|
-
data: res.data,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
throw this.createTransportError(res, traceId, fullUrl);
|
|
232
|
-
}
|
|
233
|
-
// 10. 使用 APIStyle 解析业务结果(code/message/data)
|
|
234
|
-
// Use APIStyle to parse business result (code/message/data)
|
|
235
|
-
if (requestStyle) {
|
|
236
|
-
const result = requestStyle.onResponse(res);
|
|
237
|
-
// 11. 业务错误处理:根据风格自定义的成功判断
|
|
238
|
-
// Business error handling: success check defined by the style
|
|
239
|
-
if (!requestStyle.isSuccess(result)) {
|
|
240
|
-
throw new DataHubErrorClass({
|
|
241
|
-
code: result.code,
|
|
242
|
-
message: result.message || `error: ${result.code}`,
|
|
243
|
-
trace: traceId,
|
|
244
|
-
status: res.status,
|
|
245
|
-
url: fullUrl,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
// 缓存写入:查询类请求成功后写入缓存
|
|
249
|
-
// Cache write: write to cache after successful query request
|
|
250
|
-
if (strategy.cacheable && !merged.skipCache) {
|
|
251
|
-
const ttl = merged.cacheTTL ?? DEFAULT_CONFIG.defaultCacheTTL;
|
|
252
|
-
cacheSet(fullUrl, data, res, ttl);
|
|
253
|
-
}
|
|
254
|
-
// 返回时 data 替换为业务数据 / Replace data with business data in response
|
|
255
|
-
return { ...res, data: result.data };
|
|
256
|
-
}
|
|
257
|
-
// 缓存写入:查询类请求成功后写入缓存
|
|
258
|
-
// Cache write: write to cache after successful query request
|
|
259
|
-
if (strategy.cacheable && !merged.skipCache) {
|
|
260
|
-
const ttl = merged.cacheTTL ?? DEFAULT_CONFIG.defaultCacheTTL;
|
|
261
|
-
cacheSet(fullUrl, data, res, ttl);
|
|
262
|
-
}
|
|
263
|
-
// APIStyle 为空,直接返回原始响应 / No APIStyle, return raw response directly
|
|
264
|
-
return res;
|
|
265
|
-
}
|
|
266
|
-
catch (err) {
|
|
267
|
-
// 13. 统一错误处理:将各类异常转换为 DataHubError
|
|
268
|
-
// Unified error handling: convert all exceptions to DataHubError
|
|
269
|
-
const error = this.normalizeError(err, fullUrl, traceId);
|
|
270
|
-
if (this.config.onError) {
|
|
271
|
-
this.config.onError(error, req);
|
|
272
|
-
}
|
|
273
|
-
throw error;
|
|
274
|
-
}
|
|
275
|
-
finally {
|
|
276
|
-
// 无论成功失败,标记 loading 结束 / Mark loading end regardless of success or failure
|
|
277
|
-
loadingEnd(fullUrl);
|
|
278
|
-
}
|
|
279
|
-
};
|
|
212
|
+
const execute = () => this.executeRequest(req, merged, requestStyle, traceId, fullUrl, data, cacheable);
|
|
280
213
|
// 12. 去重处理:查询类请求自动合并相同并发请求
|
|
281
214
|
// Dedup: automatically merge identical concurrent query requests
|
|
282
|
-
|
|
215
|
+
// forceDedup 选项可无视 URL 命名约定强制启用去重
|
|
216
|
+
// forceDedup option bypasses URL naming convention to force-enable dedup
|
|
217
|
+
const dedupable = this.isDedupable(strategy, merged);
|
|
218
|
+
if (dedupable && !merged.skipDedup) {
|
|
283
219
|
return dedupTrack(fullUrl, data, execute);
|
|
284
220
|
}
|
|
285
221
|
// 13. 幂等防护:提交类请求阻止重复提交
|
|
286
222
|
// Idempotent guard: block duplicate submissions for submit requests
|
|
287
|
-
|
|
223
|
+
// 当 forceDedup 或 forceCache 为 true 时跳过幂等防护,避免并发查询请求被误判为重复提交
|
|
224
|
+
// Skip idempotent guard when forceDedup or forceCache is true, preventing concurrent
|
|
225
|
+
// query requests from being misjudged as duplicate submissions
|
|
226
|
+
if (this.shouldGuardIdempotent(strategy, merged)) {
|
|
288
227
|
return idempotentGuard(fullUrl, data, execute);
|
|
289
228
|
}
|
|
290
229
|
// 14. 无需中间件,直接执行 / No middleware needed, execute directly
|
|
291
230
|
return execute();
|
|
292
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* 应用全局响应拦截器(命中缓存与实际请求路径共用)。
|
|
234
|
+
* Apply global response interceptor (shared by cache-hit and real-request paths).
|
|
235
|
+
*/
|
|
236
|
+
applyResponseInterceptor(res, req) {
|
|
237
|
+
if (!this.config.onResponse)
|
|
238
|
+
return;
|
|
239
|
+
const intercepted = this.config.onResponse(res, req);
|
|
240
|
+
if (intercepted)
|
|
241
|
+
Object.assign(res, intercepted);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 实际执行请求:适配器调用 + 响应拦截 + HTTP 错误处理 + 统一响应处理 + 缓存写入。
|
|
245
|
+
* Execute the request: adapter call + response interceptor + HTTP error handling +
|
|
246
|
+
* unified response handling + cache write.
|
|
247
|
+
*/
|
|
248
|
+
async executeRequest(req, merged, requestStyle, traceId, fullUrl, data, cacheable) {
|
|
249
|
+
// 标记 loading 开始 / Mark loading start
|
|
250
|
+
loadingStart(fullUrl);
|
|
251
|
+
try {
|
|
252
|
+
// 7. 解析并调用适配器 / Resolve and call adapter
|
|
253
|
+
const adapter = this.resolveAdapter(merged);
|
|
254
|
+
const res = await adapter.request(req);
|
|
255
|
+
// 8. 响应拦截器 / Response interceptor
|
|
256
|
+
this.applyResponseInterceptor(res, req);
|
|
257
|
+
// 9. HTTP 传输层错误处理:HTTP 非 2xx 时,优先用 APIStyle 解析响应体
|
|
258
|
+
// HTTP transport error: when !res.ok, try APIStyle first, fall back to transport error
|
|
259
|
+
if (!res.ok) {
|
|
260
|
+
throw this.buildHttpError(res, requestStyle, traceId, fullUrl);
|
|
261
|
+
}
|
|
262
|
+
// 10. 统一响应处理:APIStyle 转换 + isSuccess 业务校验 + 返回业务数据
|
|
263
|
+
// Unified response handling: APIStyle transform + isSuccess check + return business data
|
|
264
|
+
// 注意:handleResponse 内部会抛出 DataHubError,与原逻辑保持一致
|
|
265
|
+
// Note: handleResponse throws DataHubError on business failure, consistent with original logic
|
|
266
|
+
const handled = this.handleResponse(res, requestStyle, traceId, fullUrl);
|
|
267
|
+
// 11. 缓存写入:查询类请求成功后写入缓存(写入原始 res,保持现有行为)
|
|
268
|
+
// Cache write: write to cache after successful query request (write raw res, keep existing behavior)
|
|
269
|
+
if (cacheable && !merged.skipCache) {
|
|
270
|
+
const ttl = merged.cacheTTL ?? DEFAULT_CONFIG.defaultCacheTTL;
|
|
271
|
+
cacheSet(fullUrl, data, res, ttl);
|
|
272
|
+
}
|
|
273
|
+
// 返回经 handleResponse 处理后的响应(data 已替换为业务数据)
|
|
274
|
+
// Return the response processed by handleResponse (data replaced with business data)
|
|
275
|
+
return handled;
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
// 统一错误处理:将各类异常转换为 DataHubError
|
|
279
|
+
// Unified error handling: convert all exceptions to DataHubError
|
|
280
|
+
const error = this.normalizeError(err, fullUrl, traceId);
|
|
281
|
+
if (this.config.onError) {
|
|
282
|
+
this.config.onError(error, req);
|
|
283
|
+
}
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
// 无论成功失败,标记 loading 结束 / Mark loading end regardless of success or failure
|
|
288
|
+
loadingEnd(fullUrl);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* 构造 HTTP 传输层错误:优先用 APIStyle 解析响应体,回退到 transport error。
|
|
293
|
+
* Build HTTP transport error: try APIStyle first, fall back to transport error.
|
|
294
|
+
*/
|
|
295
|
+
buildHttpError(res, requestStyle, traceId, fullUrl) {
|
|
296
|
+
if (requestStyle) {
|
|
297
|
+
const result = requestStyle.onResponse(res);
|
|
298
|
+
return new DataHubErrorClass({
|
|
299
|
+
code: result.code ?? `HTTP_${res.status}`,
|
|
300
|
+
message: result.message || `HTTP request failed with status ${res.status}`,
|
|
301
|
+
trace: traceId,
|
|
302
|
+
status: res.status,
|
|
303
|
+
url: fullUrl,
|
|
304
|
+
data: res.data,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
return this.createTransportError(res, traceId, fullUrl);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* 是否可缓存:strategy 默认判定,或 forceCache 强制启用。
|
|
311
|
+
* Whether cacheable: by strategy, or force-enabled by forceCache.
|
|
312
|
+
*/
|
|
313
|
+
isCacheable(strategy, options) {
|
|
314
|
+
return strategy.cacheable || options.forceCache === true;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* 是否可去重:strategy 默认判定,或 forceDedup 强制启用。
|
|
318
|
+
* Whether dedupable: by strategy, or force-enabled by forceDedup.
|
|
319
|
+
*/
|
|
320
|
+
isDedupable(strategy, options) {
|
|
321
|
+
return strategy.dedupable || options.forceDedup === true;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 是否需要幂等防护:strategy 判定为提交类、未跳过、且未被 force 选项豁免。
|
|
325
|
+
* Whether idempotent guard applies: strategy says submit, not skipped, and not
|
|
326
|
+
* exempted by forceDedup/forceCache (which mark the request as a query).
|
|
327
|
+
*/
|
|
328
|
+
shouldGuardIdempotent(strategy, options) {
|
|
329
|
+
if (!strategy.idempotent || options.skipIdempotent)
|
|
330
|
+
return false;
|
|
331
|
+
const forceQuery = options.forceDedup === true || options.forceCache === true;
|
|
332
|
+
return !forceQuery;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 统一响应处理:APIStyle 转换 + isSuccess 业务校验 + 返回业务数据
|
|
336
|
+
* Unified response handling: APIStyle transform + isSuccess check + return business data
|
|
337
|
+
*
|
|
338
|
+
* 抽取该方法的目的:让「实际请求路径」与「缓存命中路径」走完全一致的响应处理逻辑,
|
|
339
|
+
* 避免缓存命中时跳过 isSuccess 校验或丢失 code/message 等字段。
|
|
340
|
+
*
|
|
341
|
+
* This method is extracted so that both the real-request path and the cache-hit path
|
|
342
|
+
* share identical response handling, avoiding skipped isSuccess checks or lost
|
|
343
|
+
* code/message fields when cache hits.
|
|
344
|
+
*
|
|
345
|
+
* @param res - 适配器返回的原始响应 / Raw response from adapter
|
|
346
|
+
* @param requestStyle - 解析后的 APIStyle / Resolved APIStyle
|
|
347
|
+
* @param traceId - 链路追踪 ID / Trace ID
|
|
348
|
+
* @param fullUrl - 完整请求 URL / Full request URL
|
|
349
|
+
* @returns 业务数据已替换的响应 / Response with business data replaced
|
|
350
|
+
*/
|
|
351
|
+
handleResponse(res, requestStyle, traceId, fullUrl) {
|
|
352
|
+
// 无 APIStyle:直接返回原始响应,不做业务转换 / No APIStyle: return raw response
|
|
353
|
+
if (!requestStyle)
|
|
354
|
+
return res;
|
|
355
|
+
// 使用 APIStyle 解析业务结果(code/message/data)
|
|
356
|
+
// Use APIStyle to parse business result (code/message/data)
|
|
357
|
+
const result = requestStyle.onResponse(res);
|
|
358
|
+
// 业务错误处理:根据风格自定义的成功判断
|
|
359
|
+
// Business error handling: success check defined by the style
|
|
360
|
+
if (!requestStyle.isSuccess(result)) {
|
|
361
|
+
throw new DataHubErrorClass({
|
|
362
|
+
code: result.code,
|
|
363
|
+
message: result.message || `error: ${result.code}`,
|
|
364
|
+
trace: traceId,
|
|
365
|
+
status: res.status,
|
|
366
|
+
url: fullUrl,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
// 返回时 data 替换为业务数据 / Replace data with business data in response
|
|
370
|
+
return { ...res, data: result.data };
|
|
371
|
+
}
|
|
293
372
|
// ─── 状态清理方法 / State Cleanup Methods ─────────────────────
|
|
294
373
|
/** 清空所有缓存 / Clear all cache */
|
|
295
374
|
clearCache() {
|
|
@@ -74,6 +74,24 @@ export interface DataHubRequestOptions {
|
|
|
74
74
|
skipDedup?: boolean;
|
|
75
75
|
/** 是否跳过幂等防护,允许同一提交重复执行 / Whether to skip idempotent guard, allowing duplicate submissions */
|
|
76
76
|
skipIdempotent?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* 是否强制启用去重:为 true 时无视 URL 命名约定,对本请求启用并发去重。
|
|
79
|
+
* 适用于 URL 不以 query/list/get 结尾、但语义为查询且可能被并发调用的 GET 请求。
|
|
80
|
+
* Force enable dedup: when true, bypasses URL naming convention and enables
|
|
81
|
+
* concurrent dedup for this request. Applicable to GET requests whose URL does
|
|
82
|
+
* not end with query/list/get but are semantically queries and may be called concurrently.
|
|
83
|
+
*/
|
|
84
|
+
forceDedup?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* 是否强制启用缓存:为 true 时无视 URL 命名约定,对本请求启用结果缓存。
|
|
87
|
+
* 配合 cacheTTL 控制有效期。适用于 URL 不以 query/list/get 结尾、
|
|
88
|
+
* 但语义为查询且结果可短期复用的 GET 请求。
|
|
89
|
+
* Force enable cache: when true, bypasses URL naming convention and enables
|
|
90
|
+
* result caching for this request. Use with cacheTTL to control TTL.
|
|
91
|
+
* Applicable to GET requests whose URL does not end with query/list/get
|
|
92
|
+
* but are semantically queries with short-term reusable results.
|
|
93
|
+
*/
|
|
94
|
+
forceCache?: boolean;
|
|
77
95
|
/** 是否使用 Mock 适配器 / Whether to use the Mock adapter */
|
|
78
96
|
mock?: boolean;
|
|
79
97
|
/** Mock 返回的业务数据 / Mock business data to return */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/datahub/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/datahub/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* 分类:
|
|
8
8
|
* - Leaf blocks(叶子块):heading, setextHeading, thematicBreak, codeFence, table
|
|
9
|
-
* - Container blocks(容器块):blockquote, list
|
|
9
|
+
* - Container blocks(容器块):blockquote, list(含嵌套子列表), taskList
|
|
10
10
|
* - Inlines(行内):bold, italic, code, del, link, image
|
|
11
11
|
* - Extensions(扩展):emoji, icon
|
|
12
12
|
*/
|
|
@@ -52,6 +52,7 @@ export declare const blockquotePlugin: AstPlugin;
|
|
|
52
52
|
* 无序 / 有序列表
|
|
53
53
|
*
|
|
54
54
|
* 匹配 `- ` `* ` `+ ` 开头的无序列表,以及 `1. ` 等有序列表。
|
|
55
|
+
* 支持列表项的缩进续行和嵌套子列表。
|
|
55
56
|
*/
|
|
56
57
|
export declare const listPlugin: AstPlugin;
|
|
57
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../../src/core/markdown/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAW,SAAS,EAAE,MAAM,SAAS,CAAC;AA8DlD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAc3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAejC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAQjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,SAkC7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAqDzB,CAAC;AAYF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,SA8B9B,CAAC;
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../../src/core/markdown/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAW,SAAS,EAAE,MAAM,SAAS,CAAC;AA8DlD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAc3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAejC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAQjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,SAkC7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAqDzB,CAAC;AAYF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,SA8B9B,CAAC;AAgIF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,SA0DxB,CAAC;AAoCF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAiC5B,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SA+BxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,SAU1B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAUxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,SAUvB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,SAAS,CAqB5C;AAED,0BAA0B;AAC1B,eAAO,MAAM,UAAU,EAAE,SAA8B,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAUzB,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAUxB,CAAC;AAwEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAYzB,CAAC"}
|