Skip to content

Commit 0b2cd37

Browse files
authored
update tsrest code (#5755)
* doc * update tsrest code
1 parent d755dad commit 0b2cd37

File tree

28 files changed

+508
-357
lines changed

28 files changed

+508
-357
lines changed

document/content/docs/upgrading/4-13/4132.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ description: 'FastGPT V4.13.1 更新说明'
1616

1717
## 🔨 插件更新
1818

19-
1. Perplexity search 工具。
19+
1. Perplexity search 工具。
20+
2. Base64转文件工具。
21+
3. MiniMax TTS 文件生成工具。
22+
4. Openrouter nano banana 绘图工具。
23+
5. 系统工具支持配置是否需要在 Worker 中运行。

document/data/doc-last-modified.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"document/content/docs/protocol/terms.en.mdx": "2025-08-03T22:37:45+08:00",
102102
"document/content/docs/protocol/terms.mdx": "2025-08-03T22:37:45+08:00",
103103
"document/content/docs/toc.en.mdx": "2025-08-04T13:42:36+08:00",
104-
"document/content/docs/toc.mdx": "2025-09-29T11:34:11+08:00",
104+
"document/content/docs/toc.mdx": "2025-10-09T15:10:19+08:00",
105105
"document/content/docs/upgrading/4-10/4100.mdx": "2025-08-02T19:38:37+08:00",
106106
"document/content/docs/upgrading/4-10/4101.mdx": "2025-09-08T20:07:20+08:00",
107107
"document/content/docs/upgrading/4-11/4110.mdx": "2025-08-05T23:20:39+08:00",
@@ -113,6 +113,7 @@
113113
"document/content/docs/upgrading/4-12/4124.mdx": "2025-09-17T22:29:56+08:00",
114114
"document/content/docs/upgrading/4-13/4130.mdx": "2025-09-30T16:00:10+08:00",
115115
"document/content/docs/upgrading/4-13/4131.mdx": "2025-09-30T15:47:06+08:00",
116+
"document/content/docs/upgrading/4-13/4132.mdx": "2025-10-09T15:10:19+08:00",
116117
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00",
117118
"document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00",
118119
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",
Lines changed: 12 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,13 @@
1-
import { contract } from './contracts';
2-
import { initClient, tsRestFetchApi } from '@ts-rest/core';
3-
import { TOKEN_ERROR_CODE } from '../../error/errorCode';
4-
import { getNanoid } from '../../string/tools';
5-
import { type ApiFetcherArgs } from '@ts-rest/core';
6-
import { AnyResponseSchema } from '../../type';
7-
import { ZodError } from 'zod';
8-
import { getWebReqUrl } from '../../../../web/common/system/utils';
9-
10-
export const client = initClient(contract, {
11-
baseUrl: getWebReqUrl('/api'),
12-
throwOnUnknownStatus: true,
13-
validateResponse: false,
14-
credentials: 'include',
15-
baseHeaders: {
16-
'Content-Type': 'application/json;charset=utf-8'
17-
},
18-
api: async (args: BeforeFetchOptions) => {
19-
const prepare = beforeFetch(args);
20-
const response = await tsRestFetchApi(args);
21-
return afterFetch(response, prepare);
22-
}
23-
});
24-
25-
const WHITE_LIST = ['/chat/share', '/chat', '/login'];
26-
async function isTokenExpired() {
27-
if (WHITE_LIST.includes(window.location.pathname)) return;
28-
29-
await client.support.user.account.logout();
30-
const lastRoute = encodeURIComponent(location.pathname + location.search);
31-
window.location.replace(getWebReqUrl(`/login?lastRoute=${lastRoute}`));
32-
}
33-
34-
export function checkBusinessCode(code: number) {
35-
if (code in TOKEN_ERROR_CODE) {
36-
isTokenExpired();
37-
return;
38-
}
39-
}
40-
41-
type Item = { id: string; controller: AbortController };
42-
const queue = new Map<string, Item[]>();
43-
function checkMaxRequestLimitation(options: { url: string; max: number }): {
44-
id: string;
45-
signal: AbortSignal;
46-
release: () => void;
47-
} {
48-
const { url, max } = options;
49-
const id = getNanoid();
50-
const controller = new AbortController();
51-
const item = queue.get(url);
52-
53-
const current = item ?? [];
54-
if (current.length >= max) {
55-
const first = current.shift()!;
56-
first.controller.abort();
57-
}
58-
current.push({ id, controller });
59-
if (!item) queue.set(url, current);
60-
61-
const release = () => {
62-
const item = queue.get(url);
63-
if (!item) return;
64-
65-
const index = item.findIndex((item) => item.id === id);
66-
if (index !== -1) {
67-
item.splice(index, 1);
68-
}
69-
70-
if (item.length <= 0) {
71-
queue.delete(url);
72-
}
73-
};
74-
75-
return { id, signal: controller.signal, release };
76-
}
77-
78-
function checkHttpStatus(status: number): status is 200 {
79-
if (status !== 200) return false;
80-
return true;
81-
}
82-
83-
type BeforeFetchOptions = ApiFetcherArgs & { max?: number };
84-
function beforeFetch(options: BeforeFetchOptions):
85-
| {
86-
limit: { id: string; url: string; release: () => void };
87-
}
88-
| undefined {
89-
const { max, ...args } = options;
90-
if (!max || max <= 0) return;
91-
92-
const { id, signal, release } = checkMaxRequestLimitation({ url: args.path, max });
93-
args.fetchOptions ??= {};
94-
args.fetchOptions.signal = signal;
95-
96-
return {
97-
limit: { id, url: args.path, release }
98-
};
1+
import { initClient } from '@ts-rest/core';
2+
import { fastgptContract } from './contracts';
3+
4+
export function createFastGPTClient(options: {
5+
baseUrl: string;
6+
baseHeaders?: Record<string, string>;
7+
api?: any;
8+
credentials?: RequestCredentials;
9+
throwOnUnknownStatus?: boolean;
10+
validateResponse?: boolean;
11+
}) {
12+
return initClient(fastgptContract, options);
9913
}
100-
101-
function afterFetch(
102-
response: Awaited<ReturnType<typeof tsRestFetchApi>>,
103-
prepare?: ReturnType<typeof beforeFetch>
104-
) {
105-
if (checkHttpStatus(response.status)) {
106-
try {
107-
const body = AnyResponseSchema.parse(response.body);
108-
109-
response.body = body.data;
110-
111-
if (prepare?.limit) {
112-
prepare.limit.release();
113-
}
114-
115-
return response;
116-
} catch (error) {
117-
if (error instanceof ZodError) {
118-
throw new Error(error.message);
119-
}
120-
121-
throw new Error('Unknown error while intercept response');
122-
}
123-
} else {
124-
throw new Error(`HTTP error, status: ${response.status}`);
125-
}
126-
}
127-
128-
type Client = typeof client;
129-
type U<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : U<T[K]> }[keyof T];
130-
export type Endpoints = U<Client>;
131-
type _Options<T extends Endpoints> = NonNullable<Parameters<T>[0]>;
132-
type ExtractBodySchema<T extends Endpoints> = 'body' extends keyof _Options<T>
133-
? _Options<T>['body']
134-
: never;
135-
type ExtractQuerySchema<T extends Endpoints> = 'query' extends keyof _Options<T>
136-
? _Options<T>['query']
137-
: never;
138-
export type Params<T extends Endpoints> = (ExtractBodySchema<T> extends never
139-
? {}
140-
: ExtractBodySchema<T>) &
141-
(ExtractQuerySchema<T> extends never ? {} : ExtractQuerySchema<T>);
142-
export type Options<T extends Endpoints> = Omit<_Options<T>, 'body' | 'query'>;
143-
type Body<T extends Endpoints> = Extract<Awaited<ReturnType<T>>, { status: 200 }>['body'];
144-
type RestAPIResult<T extends Endpoints> = Body<T>;
145-
146-
const call = async <T extends Endpoints>(
147-
api: T,
148-
options: _Options<T>
149-
): Promise<RestAPIResult<T>> => {
150-
const res = await api(options as any);
151-
152-
if (res.status !== 200) {
153-
throw new Error(`Unexpected status: ${res.status}`);
154-
}
155-
156-
return res.body as RestAPIResult<T>;
157-
};
158-
159-
export const RestAPI = <T extends Endpoints>(
160-
endpoint: T,
161-
transform?: (params: Params<T>) => {
162-
body?: ExtractBodySchema<T> extends never ? any : ExtractBodySchema<T>;
163-
query?: ExtractQuerySchema<T> extends never ? any : ExtractQuerySchema<T>;
164-
}
165-
) => {
166-
return (params?: Params<T>, options?: Options<T>) => {
167-
const transformedData = params && transform ? transform(params) : {};
168-
const finalOptions = { ...options, ...transformedData } as _Options<T>;
169-
170-
return call(endpoint, finalOptions);
171-
};
172-
};

packages/global/common/tsRest/fastgpt/contracts/chat/setting/index.ts

Lines changed: 0 additions & 37 deletions
This file was deleted.

packages/global/common/tsRest/fastgpt/contracts/chat/index.ts renamed to packages/global/common/tsRest/fastgpt/contracts/core/chat/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { settingContract } from './setting';
2-
import { c } from '../../../init';
2+
import { initContract } from '@ts-rest/core';
3+
const c = initContract();
34

45
export const chatContract = c.router({
56
setting: settingContract
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import { ObjectIdSchema } from '../../../../../../type';
1+
import z from 'zod';
22
import {
3-
ChatFavouriteAppResponseItemSchema,
4-
ChatFavouriteAppUpdateSchema
5-
} from '../../../../../../../core/chat/favouriteApp/type';
6-
import { c } from '../../../../../init';
7-
import { z } from 'zod';
3+
ChatSettingResponseSchema,
4+
ChatSettingSchema
5+
} from '../../../../../../core/chat/setting/type';
6+
import { ChatFavouriteAppResponseItemSchema } from '../../../../../../core/chat/favouriteApp/type';
7+
import { ObjectIdSchema } from '../../../../../type';
8+
import { initContract } from '@ts-rest/core';
89

9-
export const favouriteContract = c.router({
10+
const c = initContract();
11+
const favouriteContract = c.router({
1012
list: {
1113
path: '/proApi/core/chat/setting/favourite/list',
1214
method: 'GET',
@@ -23,37 +25,39 @@ export const favouriteContract = c.router({
2325
description: '获取精选应用列表',
2426
summary: '获取精选应用列表'
2527
},
26-
2728
update: {
2829
path: '/proApi/core/chat/setting/favourite/update',
2930
method: 'PUT',
30-
body: ChatFavouriteAppUpdateSchema,
31+
body: z.array(
32+
z.object({
33+
appId: z.string(),
34+
order: z.number()
35+
})
36+
),
3137
responses: {
32-
200: c.type<void>()
38+
200: z.void()
3339
},
3440
metadata: {
3541
tags: ['chat']
3642
},
3743
description: '更新精选应用',
3844
summary: '更新精选应用'
3945
},
40-
4146
delete: {
4247
path: '/proApi/core/chat/setting/favourite/delete',
4348
method: 'DELETE',
4449
query: z.object({
4550
id: ObjectIdSchema
4651
}),
4752
responses: {
48-
200: c.type<void>()
53+
200: z.void()
4954
},
5055
metadata: {
5156
tags: ['chat']
5257
},
5358
description: '删除精选应用',
5459
summary: '删除精选应用'
5560
},
56-
5761
order: {
5862
path: '/proApi/core/chat/setting/favourite/order',
5963
method: 'PUT',
@@ -64,15 +68,14 @@ export const favouriteContract = c.router({
6468
})
6569
),
6670
responses: {
67-
200: c.type<void>()
71+
200: z.void()
6872
},
6973
metadata: {
7074
tags: ['chat']
7175
},
7276
description: '更新精选应用顺序',
7377
summary: '更新精选应用顺序'
7478
},
75-
7679
tags: {
7780
path: '/proApi/core/chat/setting/favourite/tags',
7881
method: 'PUT',
@@ -83,7 +86,7 @@ export const favouriteContract = c.router({
8386
})
8487
),
8588
responses: {
86-
200: c.type<void>()
89+
200: z.void()
8790
},
8891
metadata: {
8992
tags: ['chat']
@@ -92,3 +95,33 @@ export const favouriteContract = c.router({
9295
summary: '更新精选应用标签'
9396
}
9497
});
98+
99+
export const settingContract = c.router({
100+
favourite: favouriteContract,
101+
102+
detail: {
103+
path: '/proApi/core/chat/setting/detail',
104+
method: 'GET',
105+
responses: {
106+
200: ChatSettingResponseSchema
107+
},
108+
metadata: {
109+
tags: ['chat']
110+
},
111+
description: '获取聊天设置',
112+
summary: '获取聊天设置'
113+
},
114+
update: {
115+
path: '/proApi/core/chat/setting/update',
116+
method: 'PUT',
117+
body: ChatSettingSchema.partial(),
118+
responses: {
119+
200: z.void()
120+
},
121+
metadata: {
122+
tags: ['chat']
123+
},
124+
description: '更新聊天设置',
125+
summary: '更新聊天设置'
126+
}
127+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { initContract } from '@ts-rest/core';
2+
import { chatContract } from './chat';
3+
const c = initContract();
4+
5+
export const coreContract = c.router({
6+
chat: chatContract
7+
});

0 commit comments

Comments
 (0)