From 667386bcb72672591fa412dcbb0666a77bc16d4c Mon Sep 17 00:00:00 2001 From: xqvvu Date: Thu, 16 Oct 2025 13:37:59 +0800 Subject: [PATCH] refactor: zod schema to generate OpenAPI instead --- .../global/common/tsRest/fastgpt/client.ts | 13 - .../fastgpt/contracts/core/chat/index.ts | 7 - .../fastgpt/contracts/core/chat/setting.ts | 127 ---- .../tsRest/fastgpt/contracts/core/index.ts | 7 - .../common/tsRest/fastgpt/contracts/index.ts | 12 - .../tsRest/fastgpt/contracts/support/index.ts | 7 - .../fastgpt/contracts/support/user/account.ts | 19 - .../fastgpt/contracts/support/user/index.ts | 7 - .../global/common/tsRest/fastgpt/openapi.ts | 36 -- .../global/common/tsRest/fastgpt/router.ts | 20 - .../tsRest/fastgptpro/contracts/index.ts | 56 -- .../global/common/tsRest/fastgptpro/server.ts | 21 - packages/global/common/tsRest/type.ts | 35 -- packages/global/common/type/index.ts | 24 - packages/global/common/type/mongo.ts | 6 + packages/global/core/chat/favouriteApp/api.ts | 20 + .../global/core/chat/favouriteApp/type.ts | 35 +- packages/global/core/chat/setting/type.ts | 97 +-- packages/global/openapi/chat/favourite.ts | 134 +++++ packages/global/openapi/chat/index.ts | 7 + packages/global/openapi/chat/setting.ts | 48 ++ packages/global/openapi/index.ts | 15 + packages/global/openapi/type.ts | 3 + packages/global/package.json | 7 +- packages/service/core/chat/setting/schema.ts | 4 +- pnpm-lock.yaml | 565 ++++++++---------- projects/app/package.json | 9 +- projects/app/src/apiRouters/proApi.ts | 58 -- .../support/user/acccount/loginout.ts | 15 - .../src/pageComponents/chat/ChatHeader.tsx | 4 +- .../AddFavouriteAppModal.tsx | 4 +- .../FavouriteAppSetting/TagManageModal.tsx | 6 +- .../ChatSetting/FavouriteAppSetting/index.tsx | 15 +- .../ChatSetting/HomepageSetting/index.tsx | 18 +- .../chat/ChatSetting/ToolSelectModal.tsx | 4 +- projects/app/src/pages/_app.tsx | 9 +- projects/app/src/pages/api/[...ts-rest].ts | 31 - projects/app/src/pages/api/openapi.json.ts | 6 + projects/app/src/pages/openapi.tsx | 22 + projects/app/src/pages/openapi/index.tsx | 16 - projects/app/src/service/middleware/entry.ts | 61 -- projects/app/src/web/common/api/client.ts | 157 ----- projects/app/src/web/core/chat/api.ts | 49 +- .../core/chat/context/chatSettingContext.tsx | 10 +- projects/app/src/web/support/user/api.ts | 3 +- 45 files changed, 644 insertions(+), 1185 deletions(-) delete mode 100644 packages/global/common/tsRest/fastgpt/client.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/core/chat/index.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/core/chat/setting.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/core/index.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/index.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/support/index.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/support/user/account.ts delete mode 100644 packages/global/common/tsRest/fastgpt/contracts/support/user/index.ts delete mode 100644 packages/global/common/tsRest/fastgpt/openapi.ts delete mode 100644 packages/global/common/tsRest/fastgpt/router.ts delete mode 100644 packages/global/common/tsRest/fastgptpro/contracts/index.ts delete mode 100644 packages/global/common/tsRest/fastgptpro/server.ts delete mode 100644 packages/global/common/tsRest/type.ts delete mode 100644 packages/global/common/type/index.ts create mode 100644 packages/global/common/type/mongo.ts create mode 100644 packages/global/core/chat/favouriteApp/api.ts create mode 100644 packages/global/openapi/chat/favourite.ts create mode 100644 packages/global/openapi/chat/index.ts create mode 100644 packages/global/openapi/chat/setting.ts create mode 100644 packages/global/openapi/index.ts create mode 100644 packages/global/openapi/type.ts delete mode 100644 projects/app/src/apiRouters/proApi.ts delete mode 100644 projects/app/src/apiRouters/support/user/acccount/loginout.ts delete mode 100644 projects/app/src/pages/api/[...ts-rest].ts create mode 100644 projects/app/src/pages/api/openapi.json.ts create mode 100644 projects/app/src/pages/openapi.tsx delete mode 100644 projects/app/src/pages/openapi/index.tsx diff --git a/packages/global/common/tsRest/fastgpt/client.ts b/packages/global/common/tsRest/fastgpt/client.ts deleted file mode 100644 index 05e85738b68a..000000000000 --- a/packages/global/common/tsRest/fastgpt/client.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { initClient } from '@ts-rest/core'; -import { fastgptContract } from './contracts'; - -export function createFastGPTClient(options: { - baseUrl: string; - baseHeaders?: Record; - api?: any; - credentials?: RequestCredentials; - throwOnUnknownStatus?: boolean; - validateResponse?: boolean; -}) { - return initClient(fastgptContract, options); -} diff --git a/packages/global/common/tsRest/fastgpt/contracts/core/chat/index.ts b/packages/global/common/tsRest/fastgpt/contracts/core/chat/index.ts deleted file mode 100644 index 60dfb87b463b..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/core/chat/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { settingContract } from './setting'; -import { initContract } from '@ts-rest/core'; -const c = initContract(); - -export const chatContract = c.router({ - setting: settingContract -}); diff --git a/packages/global/common/tsRest/fastgpt/contracts/core/chat/setting.ts b/packages/global/common/tsRest/fastgpt/contracts/core/chat/setting.ts deleted file mode 100644 index 0e2057acce6c..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/core/chat/setting.ts +++ /dev/null @@ -1,127 +0,0 @@ -import z from 'zod'; -import { - ChatSettingResponseSchema, - ChatSettingSchema -} from '../../../../../../core/chat/setting/type'; -import { ChatFavouriteAppResponseItemSchema } from '../../../../../../core/chat/favouriteApp/type'; -import { ObjectIdSchema } from '../../../../../type'; -import { initContract } from '@ts-rest/core'; - -const c = initContract(); -export const favouriteContract = c.router({ - list: { - path: '/proApi/core/chat/setting/favourite/list', - method: 'GET', - query: z.object({ - name: z.string().optional().openapi({ example: 'FastGPT' }), - tag: z.string().optional().openapi({ example: 'i7Ege2W2' }) - }), - responses: { - 200: z.array(ChatFavouriteAppResponseItemSchema) - }, - metadata: { - tags: ['chat'] - }, - description: '获取精选应用列表', - summary: '获取精选应用列表' - }, - update: { - path: '/proApi/core/chat/setting/favourite/update', - method: 'PUT', - body: z.array( - z.object({ - appId: z.string(), - order: z.number() - }) - ), - responses: { - 200: z.void() - }, - metadata: { - tags: ['chat'] - }, - description: '更新精选应用', - summary: '更新精选应用' - }, - delete: { - path: '/proApi/core/chat/setting/favourite/delete', - method: 'DELETE', - query: z.object({ - id: ObjectIdSchema - }), - responses: { - 200: z.void() - }, - metadata: { - tags: ['chat'] - }, - description: '删除精选应用', - summary: '删除精选应用' - }, - order: { - path: '/proApi/core/chat/setting/favourite/order', - method: 'PUT', - body: z.array( - z.object({ - id: ObjectIdSchema, - order: z.number() - }) - ), - responses: { - 200: z.void() - }, - metadata: { - tags: ['chat'] - }, - description: '更新精选应用顺序', - summary: '更新精选应用顺序' - }, - tags: { - path: '/proApi/core/chat/setting/favourite/tags', - method: 'PUT', - body: z.array( - z.object({ - id: z.string(), - tags: z.array(z.string()) - }) - ), - responses: { - 200: z.void() - }, - metadata: { - tags: ['chat'] - }, - description: '更新精选应用标签', - summary: '更新精选应用标签' - } -}); - -export const settingContract = c.router({ - favourite: favouriteContract, - - detail: { - path: '/proApi/core/chat/setting/detail', - method: 'GET', - responses: { - 200: ChatSettingResponseSchema - }, - metadata: { - tags: ['chat'] - }, - description: '获取聊天设置', - summary: '获取聊天设置' - }, - update: { - path: '/proApi/core/chat/setting/update', - method: 'PUT', - body: ChatSettingSchema.partial(), - responses: { - 200: z.void() - }, - metadata: { - tags: ['chat'] - }, - description: '更新聊天设置', - summary: '更新聊天设置' - } -}); diff --git a/packages/global/common/tsRest/fastgpt/contracts/core/index.ts b/packages/global/common/tsRest/fastgpt/contracts/core/index.ts deleted file mode 100644 index c114ec7d8fa7..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/core/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { initContract } from '@ts-rest/core'; -import { chatContract } from './chat'; -const c = initContract(); - -export const coreContract = c.router({ - chat: chatContract -}); diff --git a/packages/global/common/tsRest/fastgpt/contracts/index.ts b/packages/global/common/tsRest/fastgpt/contracts/index.ts deleted file mode 100644 index 89ca30cb12ee..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { initContract } from '@ts-rest/core'; -import { coreContract } from './core'; -import { supportContract } from './support'; - -const c = initContract(); - -export const fastgptContract = c.router({ - core: coreContract, - support: supportContract -}); - -export type FadtGPTContractType = typeof fastgptContract; diff --git a/packages/global/common/tsRest/fastgpt/contracts/support/index.ts b/packages/global/common/tsRest/fastgpt/contracts/support/index.ts deleted file mode 100644 index f71e6620cfd3..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/support/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { userContract } from './user'; -import { initContract } from '@ts-rest/core'; -const c = initContract(); - -export const supportContract = c.router({ - user: userContract -}); diff --git a/packages/global/common/tsRest/fastgpt/contracts/support/user/account.ts b/packages/global/common/tsRest/fastgpt/contracts/support/user/account.ts deleted file mode 100644 index b1340e0b49a0..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/support/user/account.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { initContract } from '@ts-rest/core'; -import z from 'zod'; -const c = initContract(); - -export const accountContract = c.router({ - logout: { - path: '/support/user/account/login', - method: 'POST', - body: z.undefined(), - responses: { - 200: z.void() - }, - metadata: { - tags: ['support'] - }, - description: '退出登录', - summary: '退出登录' - } -}); diff --git a/packages/global/common/tsRest/fastgpt/contracts/support/user/index.ts b/packages/global/common/tsRest/fastgpt/contracts/support/user/index.ts deleted file mode 100644 index 135e525231b7..000000000000 --- a/packages/global/common/tsRest/fastgpt/contracts/support/user/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { accountContract } from './account'; -import { initContract } from '@ts-rest/core'; -const c = initContract(); - -export const userContract = c.router({ - account: accountContract -}); diff --git a/packages/global/common/tsRest/fastgpt/openapi.ts b/packages/global/common/tsRest/fastgpt/openapi.ts deleted file mode 100644 index 217f9313b568..000000000000 --- a/packages/global/common/tsRest/fastgpt/openapi.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { fastgptContract, type FadtGPTContractType } from './contracts'; -import { generateOpenApi } from '@ts-rest/open-api'; - -const hasCustomTags = (metadata: unknown): metadata is { tags: string[] } => { - return !!metadata && typeof metadata === 'object' && 'tags' in metadata; -}; - -type OpenAPIObject = ReturnType; -function generateOpenApiDocument(c: FadtGPTContractType): OpenAPIObject { - return generateOpenApi( - c, - { - info: { - title: 'FastGPT OpenAPI', - version: '4.13.2', - description: 'FastGPT OpenAPI' - }, - servers: [{ url: '/api' }] - }, - { - operationMapper(operation, appRoute) { - return { - ...operation, - ...(hasCustomTags(appRoute.metadata) - ? { - tags: appRoute.metadata.tags - } - : {}) - }; - }, - setOperationId: false - } - ); -} - -export const fastgptOpenApiDocument = generateOpenApiDocument(fastgptContract); diff --git a/packages/global/common/tsRest/fastgpt/router.ts b/packages/global/common/tsRest/fastgpt/router.ts deleted file mode 100644 index bb57ce374152..000000000000 --- a/packages/global/common/tsRest/fastgpt/router.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { fastgptContract } from './contracts'; -import { createNextRoute, createNextRouter } from '@ts-rest/next'; - -/** - * 创建 FastGPT 单个路由 - */ -export function createServerRoute( - implementation: Parameters>[1] -) { - return createNextRoute(fastgptContract, implementation); -} - -/** - * 创建 FastGPT 路由器([...ts-rest]) - */ -export function createServerRouter( - router: Parameters>[1] -) { - return createNextRouter(fastgptContract, router); -} diff --git a/packages/global/common/tsRest/fastgptpro/contracts/index.ts b/packages/global/common/tsRest/fastgptpro/contracts/index.ts deleted file mode 100644 index 282686c74223..000000000000 --- a/packages/global/common/tsRest/fastgptpro/contracts/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { chatContract } from '../../fastgpt/contracts/core/chat'; -import { initContract } from '@ts-rest/core'; -const c = initContract(); - -/** - * 转换路径前缀 - * 将 /proApi 替换为空字符串,用于 Pro 后端 - */ -function transformPaths>( - router: T, - removePrefix: string = '/proApi', - replaceWith: string = '' -): T { - const transform = (obj: any): any => { - if (typeof obj !== 'object' || obj === null) return obj; - - // 如果是路由定义(有 path 属性) - if ('path' in obj && typeof obj.path === 'string') { - return { - ...obj, - path: obj.path.replace(removePrefix, replaceWith), - metadata: { - ...obj.metadata, - originalPath: obj.path - } - }; - } - - // 递归处理嵌套的路由 - const result: any = {}; - for (const key in obj) { - result[key] = transform(obj[key]); - } - return result; - }; - - return transform(router) as T; -} - -// 通过 FastGPT 后端转发到 Pro 后端使用的合约 -const transformedProContract = c.router({ - chat: transformPaths(chatContract) -}); - -// Pro 后端独有的接口 -const proOnlyContract = c.router({ - // TODO - // admin: adminContract, -}); - -// 最终的 Pro 合约 = 转换后的 Pro 接口 + Pro 后端独有的接口 -// Pro 后端使用的合约 -export const proContract = c.router({ - ...transformedProContract, - ...proOnlyContract -}); diff --git a/packages/global/common/tsRest/fastgptpro/server.ts b/packages/global/common/tsRest/fastgptpro/server.ts deleted file mode 100644 index d555a0758218..000000000000 --- a/packages/global/common/tsRest/fastgptpro/server.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { proContract } from './contracts'; -import { createNextRoute, createNextRouter } from '@ts-rest/next'; - -/** - * 创建 Pro 单个路由 - */ -export function createProServerRoute( - implementation: Parameters>[1] -) { - return createNextRoute(proContract, implementation); -} - -/** - * 创建 Pro 路由器 - * 只需实现 Pro 接口(路径已自动转换 /proApi → 空) - */ -export function createProServerRouter( - router: Parameters>[1] -) { - return createNextRouter(proContract, router); -} diff --git a/packages/global/common/tsRest/type.ts b/packages/global/common/tsRest/type.ts deleted file mode 100644 index 9503ab7dfe67..000000000000 --- a/packages/global/common/tsRest/type.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { AppRoute } from '@ts-rest/core'; -import type { createSingleRouteHandler } from '@ts-rest/next'; -import z from 'zod'; - -export type { AppRoute } from '@ts-rest/core'; - -export type Endpoint = Parameters>[1]; -export type Args = Parameters>[0]; -type Result = Awaited>>; - -type Ok = Extract, { status: 200 }>; -type Response = - Ok extends { body: infer B } ? (B extends { data: infer D } ? D : B) : never; - -export type Handler = (args: Args) => Promise>; - -export const createCommonResponseSchema = (schema: T) => - z - .object({ - code: z.number().describe('状态码'), - message: z.string().describe('消息'), - data: schema.describe('数据'), - statusText: z.string().describe('状态文本') - }) - .describe('通用响应') - .openapi({ - example: { - code: 200, - data: null, - message: 'Success', - statusText: 'Success' - } - }); -// 任意类型数据的响应 -export const AnyResponseSchema = createCommonResponseSchema(z.any()); diff --git a/packages/global/common/type/index.ts b/packages/global/common/type/index.ts deleted file mode 100644 index cf2fb672ab8d..000000000000 --- a/packages/global/common/type/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { extendZodWithOpenApi } from '@anatine/zod-openapi'; -import { z } from 'zod'; - -extendZodWithOpenApi(z); - -export const ObjectIdSchema = z - .string() - .length(24) - .describe('MongoDB ObjectId 格式的字符串') - .openapi({ example: '6894728240dc458ece573294' }); -export type ObjectIdType = z.infer; - -export const ParentIdSchema = ObjectIdSchema.nullish() - .openapi({ example: null }) - .describe('父级ID, 可以是 ObjectId、null 或 undefined(表示根级)'); -export type ParentIdType = z.infer; - -export const DateTimeSchema = z.date().describe('ISO 8601 格式的时间字符串'); -export type DateTimeType = z.infer; - -export const OptionalDateTimeSchema = DateTimeSchema.nullish() - .openapi({ example: null }) - .describe('ISO 8601 格式的时间字符串, 可以是 null 或 undefined'); -export type OptionalDateTimeType = z.infer; diff --git a/packages/global/common/type/mongo.ts b/packages/global/common/type/mongo.ts new file mode 100644 index 000000000000..c782574d01da --- /dev/null +++ b/packages/global/common/type/mongo.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; + +export const ObjectIdSchema = z + .string() + .regex(/^[0-9a-fA-F]{24}$/) + .meta({ example: '68ee0bd23d17260b7829b137', description: 'ObjectId' }); diff --git a/packages/global/core/chat/favouriteApp/api.ts b/packages/global/core/chat/favouriteApp/api.ts new file mode 100644 index 000000000000..e2c113abbc2e --- /dev/null +++ b/packages/global/core/chat/favouriteApp/api.ts @@ -0,0 +1,20 @@ +import { z } from 'zod'; +import { ObjectIdSchema } from '../../../common/type/mongo'; + +export const GetChatFavouriteListParamsSchema = z.object({ + name: z.string().optional().meta({ example: '测试应用', description: '精选应用名称' }), + tag: z.string().optional().meta({ example: '效率', description: '精选应用标签' }) +}); +export type GetChatFavouriteListParamsType = z.infer; + +export const UpdateFavouriteAppTagsParamsSchema = z.object({ + id: ObjectIdSchema.meta({ example: '68ad85a7463006c963799a05', description: '精选应用 ID' }), + tags: z.array(z.string()).meta({ example: ['效率', '工具'], description: '精选应用标签' }) +}); +export type UpdateFavouriteAppTagsParamsType = z.infer; + +export const UpdateFavouriteAppParamsSchema = z.object({ + appId: ObjectIdSchema.meta({ example: '68ad85a7463006c963799a05', description: '精选应用 ID' }), + order: z.number().meta({ example: 1, description: '排序' }) +}); +export type UpdateFavouriteAppParamsType = z.infer; diff --git a/packages/global/core/chat/favouriteApp/type.ts b/packages/global/core/chat/favouriteApp/type.ts index 989ba033f94f..108863645a14 100644 --- a/packages/global/core/chat/favouriteApp/type.ts +++ b/packages/global/core/chat/favouriteApp/type.ts @@ -1,29 +1,30 @@ import { z } from 'zod'; -import { extendZodWithOpenApi } from '@anatine/zod-openapi'; -import { ObjectIdSchema } from '../../../common/type'; - -extendZodWithOpenApi(z); +import { ObjectIdSchema } from '../../../common/type/mongo'; export const ChatFavouriteTagSchema = z.object({ - id: z.string().openapi({ example: 'i7Ege2W2' }), - name: z.string().openapi({ example: '游戏' }) + id: z.string().meta({ example: 'ptqn6v4I', description: '精选应用标签 ID' }), + name: z.string().meta({ example: '效率', description: '精选应用标签名称' }) }); export type ChatFavouriteTagType = z.infer; -export const ChatFavouriteAppSchema = z.object({ +export const ChatFavouriteAppModelSchema = z.object({ _id: ObjectIdSchema, teamId: ObjectIdSchema, appId: ObjectIdSchema, - favouriteTags: z.array(z.string()).openapi({ example: ['i7Ege2W2', 'i7Ege2W3'] }), - order: z.number().openapi({ example: 1 }) + favouriteTags: z + .array(z.string()) + .meta({ example: ['ptqn6v4I', 'jHLWiqff'], description: '精选应用标签' }), + order: z.number().meta({ example: 1, description: '排序' }) }); -export type ChatFavouriteAppType = z.infer; +export type ChatFavouriteAppModelType = z.infer; -export const ChatFavouriteAppResponseItemSchema = z.object({ - ...ChatFavouriteAppSchema.shape, - name: z.string().openapi({ example: 'FastGPT' }), - intro: z.string().openapi({ example: 'FastGPT' }), - avatar: z.string().openapi({ example: 'https://fastgpt.com/avatar.png' }) +export const ChatFavouriteAppSchema = z.object({ + ...ChatFavouriteAppModelSchema.shape, + name: z.string().meta({ example: 'Jina 网页阅读', description: '精选应用名称' }), + intro: z.string().optional().meta({ example: '', description: '精选应用简介' }), + avatar: z.string().optional().meta({ + example: '/api/system/img/avatar/68ad85a7463006c963799a05/79183cf9face95d336816f492409ed29', + description: '精选应用头像' + }) }); - -export type ChatFavouriteAppResponseItemType = z.infer; +export type ChatFavouriteAppType = z.infer; diff --git a/packages/global/core/chat/setting/type.ts b/packages/global/core/chat/setting/type.ts index c8e196da21cc..7087197b2c51 100644 --- a/packages/global/core/chat/setting/type.ts +++ b/packages/global/core/chat/setting/type.ts @@ -1,58 +1,77 @@ +import { ObjectIdSchema } from '../../../common/type/mongo'; import { z } from 'zod'; -import { extendZodWithOpenApi } from '@anatine/zod-openapi'; -import { ObjectIdSchema } from '../../../common/type'; import { ChatFavouriteTagSchema } from '../favouriteApp/type'; -extendZodWithOpenApi(z); +export const ChatSelectedToolSchema = z.object({ + pluginId: ObjectIdSchema, + inputs: z.record(z.string(), z.any()).meta({ example: null, description: '工具输入参数' }), + name: z.string().meta({ example: '测试应用', description: '工具名称' }), + avatar: z.string().meta({ example: '测试应用', description: '工具头像' }) +}); +export type ChatSelectedToolType = z.infer; export const ChatQuickAppSchema = z.object({ _id: ObjectIdSchema, - name: z.string().openapi({ example: 'FastGPT' }), - avatar: z.string().openapi({ example: 'https://fastgpt.com/avatar.png' }) + name: z.string().meta({ example: '测试应用', description: '快捷应用名称' }), + avatar: z.string().meta({ example: '测试应用', description: '快捷应用头像' }) }); export type ChatQuickAppType = z.infer; -export const ChatSelectedToolSchema = z.object({ - pluginId: z.string().openapi({ example: 'systemTool-getTime' }), - inputs: z.record(z.string(), z.any()).optional(), - name: z.string().openapi({ example: 'FastGPT' }), - avatar: z.string().openapi({ example: 'https://fastgpt.com/avatar.png' }) -}); -export type ChatSelectedToolType = z.infer; - -export const ChatSettingSchema = z.object({ +export const ChatSettingModelSchema = z.object({ _id: ObjectIdSchema, appId: ObjectIdSchema, teamId: ObjectIdSchema, - slogan: z.string().openapi({ example: '你好👋,我是 FastGPT ! 请问有什么可以帮你?' }), - dialogTips: z.string().openapi({ example: '你可以问我任何问题' }), - enableHome: z.boolean().openapi({ example: true }), - homeTabTitle: z.string().openapi({ example: '首页' }), - wideLogoUrl: z.string().optional().openapi({ - example: - '/api/system/img/avatar/686f319cbb6eea8840884338/2025_09_30/9f77bd74be89c71cd3b97bd2fb8b2c05_DeviconMysql.png' + slogan: z + .string() + .optional() + .meta({ example: '你好👋,我是 FastGPT ! 请问有什么可以帮你?', description: 'Slogan' }), + dialogTips: z + .string() + .optional() + .meta({ example: '你可以问我任何问题', description: '对话提示' }), + enableHome: z.boolean().optional().meta({ example: true, description: '是否启用首页' }), + homeTabTitle: z.string().optional().meta({ example: 'FastGPT', description: '首页标签' }), + wideLogoUrl: z.string().optional().meta({ + example: '/api/system/img/avatar/68ad85a7463006c963799a05/79183cf9face95d336816f492409ed29', + description: '宽 LOGO' }), - squareLogoUrl: z.string().optional().openapi({ - example: - '/api/system/img/avatar/686f319cbb6eea8840884338/2025_09_30/9f77bd74be89c71cd3b97bd2fb8b2c05_DeviconMysql.png' + squareLogoUrl: z.string().optional().meta({ + example: '/api/system/img/avatar/68ad85a7463006c963799a05/79183cf9face95d336816f492409ed29', + description: '方 LOGO' }), - selectedTools: z - .array(ChatSelectedToolSchema.pick({ pluginId: true, inputs: true })) - .openapi({ example: [{ pluginId: 'systemTool-getTime', inputs: {} }] }), quickAppIds: z .array(ObjectIdSchema) - .openapi({ example: ['68ac3dc6a717b3bcacc749bb', '68ac2da6a717b3bcacc73032'] }), - favouriteTags: z - .array(ChatFavouriteTagSchema) - .openapi({ example: [{ id: 'i7Ege2W2', name: '游戏' }] }) + .meta({ example: ['68ad85a7463006c963799a05'], description: '快捷应用 ID 列表' }), + selectedTools: z.array(ChatSelectedToolSchema.pick({ pluginId: true, inputs: true })).meta({ + example: [{ pluginId: '68ad85a7463006c963799a05', inputs: {} }], + description: '已选工具列表' + }), + favouriteTags: z.array(ChatFavouriteTagSchema).meta({ + example: [ + { id: 'ptqn6v4I', name: '效率' }, + { id: 'jHLWiqff', name: '学习' } + ], + description: '精选应用标签列表' + }) }); -export type ChatSettingType = z.infer; +export type ChatSettingModelType = z.infer; -export const ChatSettingResponseSchema = z.object({ - ...ChatSettingSchema.omit({ quickAppIds: true, selectedTools: true }).shape, - quickAppList: z.array(ChatQuickAppSchema), - selectedTools: z.array(ChatSelectedToolSchema) +export const ChatSettingSchema = z.object({ + ...ChatSettingModelSchema.omit({ quickAppIds: true }).shape, + quickAppList: z.array(ChatQuickAppSchema).meta({ + example: [{ _id: '68ad85a7463006c963799a05', name: '测试应用', avatar: '测试应用' }], + description: '快捷应用列表' + }), + selectedTools: z.array(ChatSelectedToolSchema).meta({ + example: [ + { + pluginId: '68ad85a7463006c963799a05', + inputs: {}, + name: '获取当前应用', + avatar: '/icon/logo.svg' + } + ], + description: '已选工具列表' + }) }); -export type ChatSettingResponseType = z.infer; - -export type ChatSettingUpdateType = Partial>; +export type ChatSettingType = z.infer; diff --git a/packages/global/openapi/chat/favourite.ts b/packages/global/openapi/chat/favourite.ts new file mode 100644 index 000000000000..2be727e9ba56 --- /dev/null +++ b/packages/global/openapi/chat/favourite.ts @@ -0,0 +1,134 @@ +import { z } from 'zod'; +import type { OpenAPIPath } from '../type'; +import { ChatFavouriteAppSchema } from '../../core/chat/favouriteApp/type'; +import { + GetChatFavouriteListParamsSchema, + UpdateFavouriteAppParamsSchema, + UpdateFavouriteAppTagsParamsSchema +} from '../../core/chat/favouriteApp/api'; +import { ObjectIdSchema } from '../../common/type/mongo'; + +export const ChatFavouriteAppPath: OpenAPIPath = { + '/proApi/core/chat/setting/favourite/list': { + get: { + summary: '获取精选应用列表', + description: '获取团队配置的精选应用列表,支持按名称和标签筛选', + tags: ['对话'], + requestParams: { + query: GetChatFavouriteListParamsSchema + }, + responses: { + 200: { + description: '成功返回精选应用列表', + content: { + 'application/json': { + schema: z.array(ChatFavouriteAppSchema) + } + } + } + } + } + }, + '/proApi/core/chat/setting/favourite/update': { + post: { + summary: '更新精选应用', + description: '批量创建或更新精选应用配置,包括应用 ID、标签和排序信息', + tags: ['对话'], + requestBody: { + content: { + 'application/json': { + schema: z.array(UpdateFavouriteAppParamsSchema) + } + } + }, + responses: { + 200: { + description: '成功更新精选应用', + content: { + 'application/json': { + schema: z.array(ChatFavouriteAppSchema) + } + } + } + } + } + }, + '/proApi/core/chat/setting/favourite/order': { + put: { + summary: '更新精选应用排序', + description: '批量更新精选应用的显示顺序', + tags: ['对话'], + requestBody: { + content: { + 'application/json': { + schema: z.array( + z.object({ + id: ObjectIdSchema.meta({ + example: '68ad85a7463006c963799a05', + description: '精选应用 ID' + }), + order: z.number().meta({ example: 1, description: '排序' }) + }) + ) + } + } + }, + responses: { + 200: { + description: '成功更新精选应用排序', + content: { + 'application/json': { + schema: z.null() + } + } + } + } + } + }, + '/proApi/core/chat/setting/favourite/tags': { + put: { + summary: '更新精选应用标签', + description: '批量更新精选应用的标签分类', + tags: ['对话'], + requestBody: { + content: { + 'application/json': { + schema: z.array(UpdateFavouriteAppTagsParamsSchema) + } + } + }, + responses: { + 200: { + description: '成功更新精选应用标签', + content: { + 'application/json': { + schema: z.null() + } + } + } + } + } + }, + '/proApi/core/chat/setting/favourite/delete': { + delete: { + summary: '删除精选应用', + description: '根据 ID 删除指定的精选应用配置', + tags: ['对话'], + requestParams: { + query: z.object({ + id: ObjectIdSchema + }) + }, + responses: { + 200: { + description: '成功删除精选应用', + content: { + 'application/json': { + schema: z.null() + } + } + } + } + } + } +}; diff --git a/packages/global/openapi/chat/index.ts b/packages/global/openapi/chat/index.ts new file mode 100644 index 000000000000..b8355fc80a1c --- /dev/null +++ b/packages/global/openapi/chat/index.ts @@ -0,0 +1,7 @@ +import { ChatSettingPath } from './setting'; +import { ChatFavouriteAppPath } from './favourite'; + +export const ChatPath = { + ...ChatSettingPath, + ...ChatFavouriteAppPath +}; diff --git a/packages/global/openapi/chat/setting.ts b/packages/global/openapi/chat/setting.ts new file mode 100644 index 000000000000..8b0b4b7a5b43 --- /dev/null +++ b/packages/global/openapi/chat/setting.ts @@ -0,0 +1,48 @@ +import type { OpenAPIPath } from '../type'; +import { ChatSettingSchema, ChatSettingModelSchema } from '../../core/chat/setting/type'; + +export const ChatSettingPath: OpenAPIPath = { + '/proApi/core/chat/setting/detail': { + get: { + summary: '获取聊天设置详情', + description: + '获取当前团队的聊天设置,包括 slogan、对话提示、Logo、快捷应用、已选工具和精选应用标签等配置信息', + tags: ['对话'], + responses: { + 200: { + description: '成功返回聊天设置信息', + content: { + 'application/json': { + schema: ChatSettingSchema + } + } + } + } + } + }, + '/proApi/core/chat/setting/update': { + post: { + summary: '更新聊天设置', + description: + '更新团队的聊天设置配置,包括 slogan、对话提示、Logo、快捷应用、已选工具和精选应用标签等信息', + tags: ['对话'], + requestBody: { + content: { + 'application/json': { + schema: ChatSettingModelSchema.partial() + } + } + }, + responses: { + 200: { + description: '成功更新聊天设置', + content: { + 'application/json': { + schema: ChatSettingSchema + } + } + } + } + } + } +}; diff --git a/packages/global/openapi/index.ts b/packages/global/openapi/index.ts new file mode 100644 index 000000000000..768d0cc2a8f7 --- /dev/null +++ b/packages/global/openapi/index.ts @@ -0,0 +1,15 @@ +import { createDocument } from 'zod-openapi'; +import { ChatPath } from './chat'; + +export const openAPIDocument = createDocument({ + openapi: '3.1.0', + info: { + title: 'FastGPT API', + version: '1.0.0', + description: 'FastGPT API 文档' + }, + paths: { + ...ChatPath + }, + servers: [{ url: '/api' }] +}); diff --git a/packages/global/openapi/type.ts b/packages/global/openapi/type.ts new file mode 100644 index 000000000000..90a7bed76d91 --- /dev/null +++ b/packages/global/openapi/type.ts @@ -0,0 +1,3 @@ +import type { createDocument } from 'zod-openapi'; + +export type OpenAPIPath = Parameters[0]['paths']; diff --git a/packages/global/package.json b/packages/global/package.json index 591ae2ee6896..70c0757c18c7 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -3,13 +3,9 @@ "version": "1.0.0", "dependencies": { "@fastgpt-sdk/plugin": "^0.1.19", - "@anatine/zod-openapi": "^2.2.8", "@apidevtools/swagger-parser": "^10.1.0", "@bany/curl-to-json": "^1.2.8", "axios": "^1.12.1", - "@ts-rest/core": "^3.52.1", - "@ts-rest/next": "^3.52.1", - "@ts-rest/open-api": "^3.52.1", "cron-parser": "^4.9.0", "dayjs": "^1.11.7", "encoding": "^0.1.13", @@ -22,7 +18,8 @@ "openapi-types": "^12.1.3", "timezones-list": "^3.0.2", "lodash": "^4.17.21", - "zod": "^3.24.2" + "zod": "^4.1.12", + "zod-openapi": "^5.4.3" }, "devDependencies": { "@types/lodash": "^4.14.191", diff --git a/packages/service/core/chat/setting/schema.ts b/packages/service/core/chat/setting/schema.ts index eae80af78bf1..6a698ebb16f5 100644 --- a/packages/service/core/chat/setting/schema.ts +++ b/packages/service/core/chat/setting/schema.ts @@ -1,5 +1,5 @@ import { connectionMongo, getMongoModel } from '../../../common/mongo'; -import { type ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; +import { type ChatSettingModelType } from '@fastgpt/global/core/chat/setting/type'; import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant'; import { AppCollectionName } from '../../app/schema'; @@ -55,7 +55,7 @@ ChatSettingSchema.virtual('quickAppList', { ChatSettingSchema.index({ teamId: 1 }); -export const MongoChatSetting = getMongoModel( +export const MongoChatSetting = getMongoModel( ChatSettingCollectionName, ChatSettingSchema ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b12c66af728..72ae2f315428 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,9 +65,6 @@ importers: packages/global: dependencies: - '@anatine/zod-openapi': - specifier: ^2.2.8 - version: 2.2.8(openapi3-ts@2.0.2)(zod@3.25.51) '@apidevtools/swagger-parser': specifier: ^10.1.0 version: 10.1.1(openapi-types@12.1.3) @@ -77,15 +74,6 @@ importers: '@fastgpt-sdk/plugin': specifier: ^0.1.19 version: 0.1.19(@types/node@20.14.0) - '@ts-rest/core': - specifier: ^3.52.1 - version: 3.52.1(@types/node@20.14.0)(zod@3.25.51) - '@ts-rest/next': - specifier: ^3.52.1 - version: 3.52.1(@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.51))(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.85.1))(zod@3.25.51) - '@ts-rest/open-api': - specifier: ^3.52.1 - version: 3.52.1(@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.51))(zod@3.25.51) axios: specifier: ^1.12.1 version: 1.12.1 @@ -118,7 +106,7 @@ importers: version: 14.2.32(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.85.1) openai: specifier: 4.61.0 - version: 4.61.0(encoding@0.1.13)(zod@3.25.51) + version: 4.61.0(encoding@0.1.13)(zod@4.1.12) openapi-types: specifier: ^12.1.3 version: 12.1.3 @@ -126,8 +114,11 @@ importers: specifier: ^3.0.2 version: 3.1.0 zod: - specifier: ^3.24.2 - version: 3.25.51 + specifier: ^4.1.12 + version: 4.1.12 + zod-openapi: + specifier: ^5.4.3 + version: 5.4.3(zod@4.1.12) devDependencies: '@types/js-yaml': specifier: ^4.0.9 @@ -525,20 +516,11 @@ importers: specifier: 2.0.1 version: 2.0.1 '@scalar/api-reference-react': - specifier: 0.7.48 - version: 0.7.48(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(react@18.3.1)(tailwindcss@4.1.14)(typescript@5.8.2) + specifier: ^0.8.1 + version: 0.8.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(react@18.3.1)(tailwindcss@4.1.14)(typescript@5.8.2) '@tanstack/react-query': specifier: ^4.24.10 version: 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ts-rest/core': - specifier: ^3.52.1 - version: 3.52.1(@types/node@20.17.24)(zod@3.24.2) - '@ts-rest/next': - specifier: ^3.52.1 - version: 3.52.1(@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.24.2))(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(zod@3.24.2) - '@ts-rest/open-api': - specifier: ^3.52.1 - version: 3.52.1(@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.24.2))(zod@3.24.2) ahooks: specifier: ^3.7.11 version: 3.8.4(react@18.3.1) @@ -843,18 +825,6 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@anatine/zod-openapi@1.14.2': - resolution: {integrity: sha512-q0qHfnuNYVKu0Swrnnvfj9971AEyW7c8v9jCOZGCl5ZbyGMNG4RPyJkRcMi/JC8CRfdOe0IDfNm1nNsi2avprg==} - peerDependencies: - openapi3-ts: ^2.0.0 || ^3.0.0 - zod: ^3.20.0 - - '@anatine/zod-openapi@2.2.8': - resolution: {integrity: sha512-iyM8mB556KdiZ6a1GTZ67ACLnJakU1hrzzXoh7PLaReldAdMq88MlZn/Ir/U56/TBuQctBhh/4seo0b0B343uw==} - peerDependencies: - openapi3-ts: ^4.1.2 - zod: ^3.20.0 - '@angular-devkit/core@17.3.11': resolution: {integrity: sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==} engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} @@ -1682,8 +1652,8 @@ packages: '@codemirror/state@6.5.2': resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==} - '@codemirror/view@6.38.5': - resolution: {integrity: sha512-SFVsNAgsAoou+BjRewMqN+m9jaztB9wCWN9RSRgePqUbq8UVlvJfku5zB2KVhLPgH/h0RLk38tvd4tGeAhygnw==} + '@codemirror/view@6.38.6': + resolution: {integrity: sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==} '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} @@ -3531,97 +3501,101 @@ packages: resolution: {integrity: sha512-pnkghhqfmSH7hhdlFpu2M3V/6EjP2R0XbKVbmP77JSli12DdInxR1c4Oiw9V5f/jgxQhVczQQTt74cFYbLzI/Q==} engines: {node: '>=20'} - '@scalar/api-client@2.5.32': - resolution: {integrity: sha512-UyFw1LoEB9bCyohgf9J8EopGZzLcmO2rIKhJpZ+xlfJc1XGyd/mEgPgWfI6D/IiCalfxKkTBd4NuzoyUOPxONg==} + '@scalar/api-client@2.8.1': + resolution: {integrity: sha512-l8uuYi3ClX9xmHYRhs8mIlOvSqO+AtJdgZZSdhyX4IYo0gm3pcbfsK3wHbnb6ZyqGPgYrdVPI+VIO9dfFtk+OA==} engines: {node: '>=20'} - '@scalar/api-reference-react@0.7.48': - resolution: {integrity: sha512-F54kzxNghs0j8KED87cO38GVHwZaOPIy6owYxRDPAvW1kNhKKFgtHTYjCloYd0/5iSvNVA8Gu+45+6j3Fh60dw==} + '@scalar/api-reference-react@0.8.1': + resolution: {integrity: sha512-krkNq5cZLD4IEtVto5KbektfRhVTR/ZwiGq+KGOhnXlv/0kFKdkccw6WXPnzq+gXZTYNJxFcrDn60Dj3ilXQrg==} engines: {node: '>=20'} peerDependencies: react: ^18.0.0 || ^19.0.0 - '@scalar/api-reference@1.35.5': - resolution: {integrity: sha512-C7hkHRdv1R2lcBfJjmIqDWEohpBFWCQQwhdkAv7eHOkFn/xBjy10QINGSxtmLj5sEKhkxwQmqPbhpDBvWXdLNA==} + '@scalar/api-reference@1.38.1': + resolution: {integrity: sha512-1r0o1BBhfOpOI2ZTvcDffNkljL4gpzyB1prBZ1wRZ3fY1lkIdAUHzIDj+lCYL+uj0RYVJFOIWvJpmpCBW6KmIg==} engines: {node: '>=20'} - '@scalar/code-highlight@0.1.9': - resolution: {integrity: sha512-WUUVDd1Wk7QJVKWXl/Zdn/VINc2pc1NlWW8VJFYZRm3/hKJwBhi0on7+HjVQNKgUaRy7+zluru5Ckl1gcTHHEg==} + '@scalar/code-highlight@0.2.0': + resolution: {integrity: sha512-p1Bw5J5QXDwaexREMbpqy1XYk9wm9Dda/xt6GRH5PNNJ5fEYmRL/TSqt1qdLN3S2FC9W0XceM3F2VpGnD4jNOg==} engines: {node: '>=20'} - '@scalar/components@0.14.33': - resolution: {integrity: sha512-uCs0hwPphLPK6LHCrVzUDus0TF/wIxue47OXPYsYODAO+nk4DzjUQbjJ9JFQ1p+HMUGdzQjdSiMdx/pJdFHT0Q==} + '@scalar/components@0.15.1': + resolution: {integrity: sha512-LIbTVA0He1g3C55WKEOuKgqgkBA7Fs6PLkEyFEHdoBfASBWYHgu6OOlz3W/KnY4jK8cPyJFXKlPXfC9p+gtadQ==} engines: {node: '>=20'} '@scalar/draggable@0.2.0': resolution: {integrity: sha512-UetHRB5Bqo5egVYlS21roWBcICmyk8CKh2htsidO+bFGAjl2e7Te+rY0borhNrMclr0xezHlPuLpEs1dvgLS2g==} engines: {node: '>=20'} - '@scalar/helpers@0.0.10': - resolution: {integrity: sha512-VmVgIAkSLBmE5fHgkPiQ0EUZqjsYQNSd/Wd5PwsInYgBvTAxojSeiM58ZVZzMsRRfrCwboCkGn9uNEkbZQX8fg==} + '@scalar/helpers@0.0.12': + resolution: {integrity: sha512-4NDmHShyi1hrVRsJCdRZT/FIpy+/5PFbVbQLRYX/pjpu5cYqHBj9s6n5RI6gGDXEBHAIFi63g9FC6Isgr66l1Q==} engines: {node: '>=20'} '@scalar/icons@0.4.7': resolution: {integrity: sha512-0qXPGRdZ180TMfejWCPYy7ILszBrAraq4KBhPtcM12ghc5qkncFWWpTm5yXI/vrbm10t7wvtTK08CLZ36CnXlQ==} engines: {node: '>=20'} - '@scalar/import@0.4.23': - resolution: {integrity: sha512-jG5RfeSbpPCQk8OuBnqUNxRqsfqR6nhxhwr6mPJODQOKkDPbGFek1icJOA4/blv7uBYLPV1/43ZZ9CQ1IBo3+A==} + '@scalar/import@0.4.31': + resolution: {integrity: sha512-3+3dHz+EvS/C4YEQ8eEihZFVxRVZODsMEHsp48tvXTaIs1Qxb4kf3Nkaf9E3k+6rpM2CUrF59K1P8LvhXob48w==} engines: {node: '>=20'} - '@scalar/json-magic@0.4.2': - resolution: {integrity: sha512-a6Jyt4Fz7wt2p5Oy8+eOs19zSUNqm3wA/4EjVkJ498PBS3LQB7qa+fW38Fst+LwJCjRYDRTA1HB0kLqMNQ92LQ==} + '@scalar/json-magic@0.6.1': + resolution: {integrity: sha512-HJMPY5dUU3EXVS4EkjAFXo+uCrby/YFu/gljKDQnhYWRy5zQ0sJWrOEDcHS8nLoJRCIRD5tiVpCxnUnSb6OoAQ==} engines: {node: '>=20'} - '@scalar/oas-utils@0.4.28': - resolution: {integrity: sha512-emyWzDKiuBlrI2bzxDrjqVwvBiVDcjy7MVBoz2Mqbsn8xCyLntc8RuOiTPuRGykXWQt433yQZSwXYn3WQoWXqA==} + '@scalar/oas-utils@0.5.2': + resolution: {integrity: sha512-zuElgEjPDbqHigkF4AGOYztbMGKUlYRa3fUst4KjS1Jeq6LW4ojiiULfypog0S5SQ2hChX3B2PcRjs6lBLEtJQ==} engines: {node: '>=20'} - '@scalar/object-utils@1.2.6': - resolution: {integrity: sha512-8+tt8Zq6cbfyGniaOtW/71jH1fzMfZwC/3zyMvBgt6fZMF0C+ohLryx5Sx1jpIXQauVp1ofzZuA2WfnnxBpHfg==} + '@scalar/object-utils@1.2.8': + resolution: {integrity: sha512-FjPxEg7Hw0tz2iTKvi+gYt+luZK0TqhX50hUIBuaYa/Ja/OMuKLp9QHhB5U68F1L55CZNP4vwoNNfXeYWnVEZg==} engines: {node: '>=20'} - '@scalar/openapi-parser@0.20.5': - resolution: {integrity: sha512-f8suNeHTtvU+GYRuYJ8QFTXmYOWmg8U/md3DXX4BrpXp+V1w+MCPMp984LmyGwnP3IavrgKi7FtlChSJXPFRqg==} + '@scalar/openapi-parser@0.22.3': + resolution: {integrity: sha512-5Znbx9HVJb7EV9EJXJrUj+cs116QIBwX/hxkyaiLaaDL2w5S+z1rjtV+d0Jv7382FCtzAtfv/9llVuxZYPVqXA==} engines: {node: '>=20'} - '@scalar/openapi-types@0.3.7': - resolution: {integrity: sha512-QHSvHBVDze3+dUwAhIGq6l1iOev4jdoqdBK7QpfeN1Q4h+6qpVEw3EEqBiH0AXUSh/iWwObBv4uMgfIx0aNZ5g==} + '@scalar/openapi-types@0.5.0': + resolution: {integrity: sha512-HJBcLa+/mPP+3TCcQngj/iW5UqynRosOQdEETXjmdy6Ngw8wBjwIcT6C86J5jufJ6sI8++HYnt+e7pAvp5FO6A==} engines: {node: '>=20'} - '@scalar/postman-to-openapi@0.3.31': - resolution: {integrity: sha512-W7eGNxzMXFr+LWOOt+OJlQajW5YIWSD85KjbWzys1YevQgcmU0HQulgU0DSBao7MCRGnPpti/fOQ3QVwM627uw==} + '@scalar/openapi-upgrader@0.1.3': + resolution: {integrity: sha512-iROhcgy3vge6zsviPtoTLHale0nYt1PLhuMmJweQwJ0U23ZYyYhV5xgHtAd0OBEXuqT6rjYbJFvKOJZmJOwpNQ==} engines: {node: '>=20'} - '@scalar/snippetz@0.4.9': - resolution: {integrity: sha512-l3dsAHZsUs7NaYwRC4Tuh+I9GFARgWESmY8CE9R6lY1oZQot6e16pXwR/xPdEU4MpHUXqHnRpO62ts3TYrTISA==} + '@scalar/postman-to-openapi@0.3.40': + resolution: {integrity: sha512-FP1p2/mb0Y5GM9hc+TI9ldDM44VV9GHwdhJQ8xGpArtlt8nxtyKmncOXcgayBD7qk3ohV6W1Eftsr258Eq7gGQ==} engines: {node: '>=20'} - '@scalar/themes@0.13.16': - resolution: {integrity: sha512-1Jqey9WywVa+kxbHk1RtEiV8xnkJafHIsnK1gA90KKUyP1UdcE8FpUN2Jagx+vX/vCLAfWAbOEXJZzeXvPO95g==} + '@scalar/snippetz@0.5.1': + resolution: {integrity: sha512-RuCSsD59qVUyux9g6BXQX35TTeJU7U34bilfPeDA9p8+dvo1WDDoRgooBmAUn4Xaxh2H7hVH0qTSJ0ZlPk4SQw==} + engines: {node: '>=20'} + + '@scalar/themes@0.13.22': + resolution: {integrity: sha512-g7nF+u733+O1InQ/9JnCSbRs0DRJhXdEQUbJsofbOEsQvBzNUBFjbYjBcLWUeoQ2maj0WSIl3+aZoEOL8vqk6Q==} engines: {node: '>=20'} '@scalar/typebox@0.1.1': resolution: {integrity: sha512-Mhhubu4zj1PiXhtgvNbz34zniedtO6PYdD80haMkIjOJwV9aWejxXILr2elHGBMsLfdhH3s9qxux6TL6X8Q6/Q==} - '@scalar/types@0.2.15': - resolution: {integrity: sha512-x2aCNmkDqr3VXUHjw7wPXK9KZwHbGGMs4NuxJIzy9MbAxUS9li8HXGG0K82Q5fDm47SAM+68z0/tnWkJpu+kzg==} + '@scalar/types@0.3.2': + resolution: {integrity: sha512-+X10CCvG57nAqYbTGteiSzRFQcMYm7DLfCRMeEfiWQ9Bq2ladat17XsMSvkvwcfpOSlsoepWf3P5dErERUSOQQ==} engines: {node: '>=20'} - '@scalar/use-codemirror@0.12.34': - resolution: {integrity: sha512-sFWMhH65vwA4hY/Z7CR58DkmCbaUQfnzepRXIls9J7uaMMYawFBbX2JlaXwjKHRId8otVydhGqcySA8eG+QFyQ==} + '@scalar/use-codemirror@0.12.43': + resolution: {integrity: sha512-gtI4jzMS4FEaTxq4FZcUJ3tjhMzi442bMvkLJglwrY68zAwGGLI0jtx9NyiC6i+ikwEjgpdZk+J45AeCHUxd0Q==} engines: {node: '>=20'} - '@scalar/use-hooks@0.2.4': - resolution: {integrity: sha512-TXviVV9Cfmei6g24QadnfuFj2r1YkZY56ufsSnwHgLNbtDRd9U9jXGIswXAuA+k7whaEVEgcoZ3Zmq2v5ZLF8w==} + '@scalar/use-hooks@0.2.5': + resolution: {integrity: sha512-ML6o5gBNh5ZGObxmmHjCQA6mZhgi+4e8dBhYS1jcuj35tLmV+pMZe+izYJ58+k/szcyNz7aLixTWADBlgCEm0w==} engines: {node: '>=20'} '@scalar/use-toasts@0.8.0': resolution: {integrity: sha512-u+o77cdTNZ5ePqHPu8ZcFw1BLlISv+cthN0bR1zJHXmqBjvanFTy2kL+Gmv3eW9HxZiHdqycKVETlYd0mWiqJQ==} engines: {node: '>=20'} - '@scalar/workspace-store@0.15.5': - resolution: {integrity: sha512-wkFCDAQa7R7+KJCd1EHNyJdJe1ugw3txS51ri0zvnI5oZyjREh4fFu/nBBNCQPJ6tzDpoJ3jlrc1KO9dE9yR6A==} + '@scalar/workspace-store@0.17.1': + resolution: {integrity: sha512-IWWudWionjVT2JNl+xin9zuoR/I5+f84myt8uzCCKj2PACEjitZvXYwwnqhnLMPPWYI8FQ5dncGKg0zUgRL5zQ==} engines: {node: '>=18'} '@sec-ant/readable-stream@0.4.1': @@ -3772,22 +3746,6 @@ packages: zod: optional: true - '@ts-rest/next@3.52.1': - resolution: {integrity: sha512-LjxBlDlJDIdZafVucAfc/gJnYP3PATGLVN5nxFfSIJBRvLrlJeKK6oXxHB7biTUle/1xgyOZGTjh+i2S+0sJtA==} - peerDependencies: - '@ts-rest/core': ~3.52.0 - next: ^12.0.0 || ^13.0.0 || ^14.0.0 - zod: ^3.22.3 - peerDependenciesMeta: - zod: - optional: true - - '@ts-rest/open-api@3.52.1': - resolution: {integrity: sha512-VY91g6HFzCe1/fNgX4Y3HzaJbIdztCGHTg34drkh7bKgtNOizLJLXV0wwIkMwLGvjhRHojJxnwYxHjGMIkScwg==} - peerDependencies: - '@ts-rest/core': ~3.52.0 - zod: ^3.22.3 - '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -4043,8 +4001,8 @@ packages: '@types/node@20.17.24': resolution: {integrity: sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==} - '@types/node@22.18.9': - resolution: {integrity: sha512-5yBtK0k/q8PjkMXbTfeIEP/XVYnz1R9qZJ3yUicdEW7ppdDJfe+MqXEhpqDL3mtn4Wvs1u0KLEG0RXzCgNpsSg==} + '@types/node@22.18.10': + resolution: {integrity: sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==} '@types/node@24.0.13': resolution: {integrity: sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==} @@ -4130,6 +4088,9 @@ packages: '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + '@types/webidl-conversions@7.0.3': resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} @@ -4346,11 +4307,13 @@ packages: '@vueuse/core@10.11.1': resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==} - '@vueuse/core@11.3.0': - resolution: {integrity: sha512-7OC4Rl1f9G8IT6rUfi9JrKiXy4bfmHhZ5x2Ceojy0jnd3mHNEvV4JaRygH362ror6/NZ+Nl+n13LPzGiPN8cKA==} + '@vueuse/core@13.9.0': + resolution: {integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==} + peerDependencies: + vue: ^3.5.0 - '@vueuse/integrations@11.3.0': - resolution: {integrity: sha512-5fzRl0apQWrDezmobchoiGTkGw238VWESxZHazfhP3RM7pDSiyXy18QbfYkILoYNTd23HPAfQTJpkUc5QbkwTw==} + '@vueuse/integrations@13.9.0': + resolution: {integrity: sha512-SDobKBbPIOe0cVL7QxMzGkuUGHvWTdihi9zOrrWaWUgFKe15cwEcwfWmgrcNzjT6kHnNmWuTajPHoIzUjYNYYQ==} peerDependencies: async-validator: ^4 axios: ^1 @@ -4363,7 +4326,8 @@ packages: nprogress: ^0.2 qrcode: ^1.5 sortablejs: ^1 - universal-cookie: ^7 + universal-cookie: ^7 || ^8 + vue: ^3.5.0 peerDependenciesMeta: async-validator: optional: true @@ -4393,14 +4357,16 @@ packages: '@vueuse/metadata@10.11.1': resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==} - '@vueuse/metadata@11.3.0': - resolution: {integrity: sha512-pwDnDspTqtTo2HwfLw4Rp6yywuuBdYnPYDq+mO38ZYKGebCUQC/nVj/PXSiK9HX5otxLz8Fn7ECPbjiRz2CC3g==} + '@vueuse/metadata@13.9.0': + resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==} '@vueuse/shared@10.11.1': resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==} - '@vueuse/shared@11.3.0': - resolution: {integrity: sha512-P8gSSWQeucH5821ek2mn/ciCk+MS/zoRKqdQIM3bHq6p7GXDAJLmnRRKmF5F65sAVJIfzQlwR3aDzwCn10s8hA==} + '@vueuse/shared@13.9.0': + resolution: {integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==} + peerDependencies: + vue: ^3.5.0 '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -8512,9 +8478,6 @@ packages: openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} - openapi3-ts@2.0.2: - resolution: {integrity: sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==} - option@0.2.4: resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==} @@ -9886,7 +9849,7 @@ packages: superagent@8.1.2: resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==} engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net supertest@6.3.4: resolution: {integrity: sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==} @@ -9927,6 +9890,10 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + tailwind-merge@2.6.0: resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} @@ -10111,10 +10078,6 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} - ts-deepmerge@6.2.1: - resolution: {integrity: sha512-8CYSLazCyj0DJDpPIxOFzJG46r93uh6EynYjuey+bxcLltBeqZL7DMfaE5ZPzZNFlav7wx+2TDa/mBl8gkTYzw==} - engines: {node: '>=14.13.1'} - ts-deepmerge@7.0.3: resolution: {integrity: sha512-Du/ZW2RfwV/D4cmA5rXafYjBQVuvu4qGiEEla4EmEHVHgRdx68Gftx7i66jn2bzHPwSVZY36Ae6OuDn9el4ZKA==} engines: {node: '>=14.13.1'} @@ -10222,9 +10185,9 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} + type-fest@5.0.0: + resolution: {integrity: sha512-GeJop7+u7BYlQ6yQCAY1nBQiRSHR+6OdCEtd8Bwp9a3NK3+fWAVjOaPKJDteB9f6cIJ0wt4IfnScjLG450EpXA==} + engines: {node: '>=20'} type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} @@ -10676,10 +10639,10 @@ packages: '@vue/composition-api': optional: true - vue-router@4.5.1: - resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==} + vue-router@4.6.0: + resolution: {integrity: sha512-YRrWLi4ayHe1d6zyH6sMPwF/WwcDY8XgUOfQGa0Kx4kmugSorLavD1ExrM/Y83B4X2NQMXYpJFSq2pbZh9ildQ==} peerDependencies: - vue: ^3.2.0 + vue: ^3.5.0 vue-sonner@1.3.2: resolution: {integrity: sha512-UbZ48E9VIya3ToiRHAZUbodKute/z/M1iT8/3fU8zEbwBRE11AKuHikssv18LMk2gTTr6eMQT4qf6JoLHWuj/A==} @@ -10937,6 +10900,12 @@ packages: resolution: {integrity: sha512-E1rA6TyQJ1cWWfMoM8KE1hMdDDi5B8Gv+8OYPXe733Lf0C3EwJ+jh1cpoK/KTrYeITumRZQ0KSPkBRMNZuC8oA==} hasBin: true + zod-openapi@5.4.3: + resolution: {integrity: sha512-6kJ/gJdvHZtuxjYHoMtkl2PixCwRuZ/s79dVkEr7arHvZGXfx7Cvh53X3HfJ5h9FzGelXOXlnyjwfX0sKEPByw==} + engines: {node: '>=20'} + peerDependencies: + zod: ^3.25.74 || ^4.0.0 + zod-to-json-schema@3.24.5: resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} peerDependencies: @@ -10957,6 +10926,12 @@ packages: zod@3.25.51: resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} + zod@4.1.11: + resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} + + zod@4.1.12: + resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + zrender@5.4.1: resolution: {integrity: sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA==} @@ -10988,24 +10963,6 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@anatine/zod-openapi@1.14.2(openapi3-ts@2.0.2)(zod@3.24.2)': - dependencies: - openapi3-ts: 2.0.2 - ts-deepmerge: 6.2.1 - zod: 3.24.2 - - '@anatine/zod-openapi@1.14.2(openapi3-ts@2.0.2)(zod@3.25.51)': - dependencies: - openapi3-ts: 2.0.2 - ts-deepmerge: 6.2.1 - zod: 3.25.51 - - '@anatine/zod-openapi@2.2.8(openapi3-ts@2.0.2)(zod@3.25.51)': - dependencies: - openapi3-ts: 2.0.2 - ts-deepmerge: 6.2.1 - zod: 3.25.51 - '@angular-devkit/core@17.3.11(chokidar@3.6.0)': dependencies: ajv: 8.12.0 @@ -12043,14 +12000,14 @@ snapshots: dependencies: '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@codemirror/commands@6.9.0': dependencies: '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@codemirror/lang-css@6.3.1': @@ -12068,7 +12025,7 @@ snapshots: '@codemirror/lang-javascript': 6.2.4 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/css': 1.3.0 '@lezer/html': 1.3.12 @@ -12079,7 +12036,7 @@ snapshots: '@codemirror/language': 6.11.3 '@codemirror/lint': 6.9.0 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/javascript': 1.5.4 @@ -12093,7 +12050,7 @@ snapshots: '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/xml': 1.0.6 @@ -12110,7 +12067,7 @@ snapshots: '@codemirror/language@6.11.3': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 @@ -12119,20 +12076,20 @@ snapshots: '@codemirror/lint@6.9.0': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 crelt: 1.0.6 '@codemirror/search@6.5.11': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 crelt: 1.0.6 '@codemirror/state@6.5.2': dependencies: '@marijn/find-cluster-break': 1.0.2 - '@codemirror/view@6.38.5': + '@codemirror/view@6.38.6': dependencies: '@codemirror/state': 6.5.2 crelt: 1.0.6 @@ -13877,11 +13834,11 @@ snapshots: - '@types/react' - immer - '@replit/codemirror-css-color-picker@6.3.0(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.5)': + '@replit/codemirror-css-color-picker@6.3.0(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.6)': dependencies: '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@rollup/rollup-android-arm-eabi@4.35.0': optional: true @@ -13948,31 +13905,32 @@ snapshots: dependencies: zod: 3.24.1 - '@scalar/api-client@2.5.32(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2)': + '@scalar/api-client@2.8.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2)': dependencies: '@headlessui/tailwindcss': 0.2.2(tailwindcss@4.1.14) '@headlessui/vue': 1.7.23(vue@3.5.22(typescript@5.8.2)) '@scalar/analytics-client': 1.0.0 - '@scalar/components': 0.14.33(typescript@5.8.2) + '@scalar/components': 0.15.1(typescript@5.8.2) '@scalar/draggable': 0.2.0(typescript@5.8.2) - '@scalar/helpers': 0.0.10 + '@scalar/helpers': 0.0.12 '@scalar/icons': 0.4.7(typescript@5.8.2) - '@scalar/import': 0.4.23(typescript@5.8.2) - '@scalar/oas-utils': 0.4.28(typescript@5.8.2) - '@scalar/object-utils': 1.2.6 - '@scalar/openapi-parser': 0.20.5(typescript@5.8.2) - '@scalar/openapi-types': 0.3.7 - '@scalar/postman-to-openapi': 0.3.31(typescript@5.8.2) - '@scalar/snippetz': 0.4.9 - '@scalar/themes': 0.13.16 - '@scalar/types': 0.2.15 - '@scalar/use-codemirror': 0.12.34(typescript@5.8.2) - '@scalar/use-hooks': 0.2.4(typescript@5.8.2) + '@scalar/import': 0.4.31 + '@scalar/json-magic': 0.6.1 + '@scalar/oas-utils': 0.5.2(typescript@5.8.2) + '@scalar/object-utils': 1.2.8 + '@scalar/openapi-parser': 0.22.3 + '@scalar/openapi-types': 0.5.0 + '@scalar/postman-to-openapi': 0.3.40(typescript@5.8.2) + '@scalar/snippetz': 0.5.1 + '@scalar/themes': 0.13.22 + '@scalar/types': 0.3.2 + '@scalar/use-codemirror': 0.12.43(typescript@5.8.2) + '@scalar/use-hooks': 0.2.5(typescript@5.8.2) '@scalar/use-toasts': 0.8.0(typescript@5.8.2) - '@scalar/workspace-store': 0.15.5(typescript@5.8.2) + '@scalar/workspace-store': 0.17.1(typescript@5.8.2) '@types/har-format': 1.2.16 - '@vueuse/core': 11.3.0(vue@3.5.22(typescript@5.8.2)) - '@vueuse/integrations': 11.3.0(axios@1.12.1)(focus-trap@7.6.5)(fuse.js@7.1.0)(nprogress@0.2.0)(qrcode@1.5.4)(vue@3.5.22(typescript@5.8.2)) + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.8.2)) + '@vueuse/integrations': 13.9.0(axios@1.12.1)(focus-trap@7.6.5)(fuse.js@7.1.0)(nprogress@0.2.0)(qrcode@1.5.4)(vue@3.5.22(typescript@5.8.2)) focus-trap: 7.6.5 fuse.js: 7.1.0 js-base64: 3.7.8 @@ -13981,12 +13939,12 @@ snapshots: pretty-bytes: 6.1.1 pretty-ms: 8.0.0 shell-quote: 1.8.3 - type-fest: 4.41.0 + type-fest: 5.0.0 vue: 3.5.22(typescript@5.8.2) - vue-router: 4.5.1(vue@3.5.22(typescript@5.8.2)) + vue-router: 4.6.0(vue@3.5.22(typescript@5.8.2)) whatwg-mimetype: 4.0.0 yaml: 2.8.0 - zod: 3.24.1 + zod: 4.1.11 transitivePeerDependencies: - '@vue/composition-api' - async-validator @@ -14003,10 +13961,10 @@ snapshots: - typescript - universal-cookie - '@scalar/api-reference-react@0.7.48(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(react@18.3.1)(tailwindcss@4.1.14)(typescript@5.8.2)': + '@scalar/api-reference-react@0.8.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(react@18.3.1)(tailwindcss@4.1.14)(typescript@5.8.2)': dependencies: - '@scalar/api-reference': 1.35.5(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2) - '@scalar/types': 0.2.15 + '@scalar/api-reference': 1.38.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2) + '@scalar/types': 0.3.2 react: 18.3.1 transitivePeerDependencies: - '@vue/composition-api' @@ -14024,37 +13982,38 @@ snapshots: - typescript - universal-cookie - '@scalar/api-reference@1.35.5(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2)': + '@scalar/api-reference@1.38.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2)': dependencies: '@floating-ui/vue': 1.1.9(vue@3.5.22(typescript@5.8.2)) '@headlessui/vue': 1.7.23(vue@3.5.22(typescript@5.8.2)) - '@scalar/api-client': 2.5.32(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2) - '@scalar/code-highlight': 0.1.9 - '@scalar/components': 0.14.33(typescript@5.8.2) - '@scalar/helpers': 0.0.10 + '@scalar/api-client': 2.8.1(axios@1.12.1)(nprogress@0.2.0)(qrcode@1.5.4)(tailwindcss@4.1.14)(typescript@5.8.2) + '@scalar/code-highlight': 0.2.0 + '@scalar/components': 0.15.1(typescript@5.8.2) + '@scalar/helpers': 0.0.12 '@scalar/icons': 0.4.7(typescript@5.8.2) - '@scalar/json-magic': 0.4.2(typescript@5.8.2) - '@scalar/oas-utils': 0.4.28(typescript@5.8.2) - '@scalar/object-utils': 1.2.6 - '@scalar/openapi-parser': 0.20.5(typescript@5.8.2) - '@scalar/openapi-types': 0.3.7 - '@scalar/snippetz': 0.4.9 - '@scalar/themes': 0.13.16 - '@scalar/types': 0.2.15 - '@scalar/use-hooks': 0.2.4(typescript@5.8.2) + '@scalar/json-magic': 0.6.1 + '@scalar/oas-utils': 0.5.2(typescript@5.8.2) + '@scalar/object-utils': 1.2.8 + '@scalar/openapi-parser': 0.22.3 + '@scalar/openapi-types': 0.5.0 + '@scalar/openapi-upgrader': 0.1.3 + '@scalar/snippetz': 0.5.1 + '@scalar/themes': 0.13.22 + '@scalar/types': 0.3.2 + '@scalar/use-hooks': 0.2.5(typescript@5.8.2) '@scalar/use-toasts': 0.8.0(typescript@5.8.2) - '@scalar/workspace-store': 0.15.5(typescript@5.8.2) + '@scalar/workspace-store': 0.17.1(typescript@5.8.2) '@unhead/vue': 1.11.20(vue@3.5.22(typescript@5.8.2)) - '@vueuse/core': 11.3.0(vue@3.5.22(typescript@5.8.2)) + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.8.2)) flatted: 3.3.3 fuse.js: 7.1.0 github-slugger: 2.0.0 js-base64: 3.7.8 microdiff: 1.5.0 nanoid: 5.1.5 - type-fest: 4.41.0 + type-fest: 5.0.0 vue: 3.5.22(typescript@5.8.2) - zod: 3.24.1 + zod: 4.1.11 transitivePeerDependencies: - '@vue/composition-api' - async-validator @@ -14071,7 +14030,7 @@ snapshots: - typescript - universal-cookie - '@scalar/code-highlight@0.1.9': + '@scalar/code-highlight@0.2.0': dependencies: hast-util-to-text: 4.0.2 highlight.js: 11.11.1 @@ -14093,19 +14052,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@scalar/components@0.14.33(typescript@5.8.2)': + '@scalar/components@0.15.1(typescript@5.8.2)': dependencies: '@floating-ui/utils': 0.2.10 '@floating-ui/vue': 1.1.9(vue@3.5.22(typescript@5.8.2)) '@headlessui/vue': 1.7.23(vue@3.5.22(typescript@5.8.2)) - '@scalar/code-highlight': 0.1.9 - '@scalar/helpers': 0.0.10 + '@scalar/code-highlight': 0.2.0 + '@scalar/helpers': 0.0.12 '@scalar/icons': 0.4.7(typescript@5.8.2) - '@scalar/oas-utils': 0.4.28(typescript@5.8.2) - '@scalar/themes': 0.13.16 - '@scalar/use-hooks': 0.2.4(typescript@5.8.2) + '@scalar/oas-utils': 0.5.2(typescript@5.8.2) + '@scalar/themes': 0.13.22 + '@scalar/use-hooks': 0.2.5(typescript@5.8.2) '@scalar/use-toasts': 0.8.0(typescript@5.8.2) - '@vueuse/core': 11.3.0(vue@3.5.22(typescript@5.8.2)) + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.8.2)) cva: 1.0.0-beta.2(typescript@5.8.2) nanoid: 5.1.5 pretty-bytes: 6.1.1 @@ -14123,109 +14082,108 @@ snapshots: transitivePeerDependencies: - typescript - '@scalar/helpers@0.0.10': {} + '@scalar/helpers@0.0.12': {} '@scalar/icons@0.4.7(typescript@5.8.2)': dependencies: '@phosphor-icons/core': 2.1.1 - '@types/node': 22.18.9 + '@types/node': 22.18.10 chalk: 5.4.1 vue: 3.5.22(typescript@5.8.2) transitivePeerDependencies: - typescript - '@scalar/import@0.4.23(typescript@5.8.2)': + '@scalar/import@0.4.31': dependencies: - '@scalar/helpers': 0.0.10 - '@scalar/openapi-parser': 0.20.5(typescript@5.8.2) + '@scalar/helpers': 0.0.12 + '@scalar/openapi-parser': 0.22.3 yaml: 2.8.0 - transitivePeerDependencies: - - typescript - '@scalar/json-magic@0.4.2(typescript@5.8.2)': + '@scalar/json-magic@0.6.1': dependencies: - '@scalar/helpers': 0.0.10 - vue: 3.5.22(typescript@5.8.2) + '@scalar/helpers': 0.0.12 yaml: 2.8.0 - transitivePeerDependencies: - - typescript - '@scalar/oas-utils@0.4.28(typescript@5.8.2)': + '@scalar/oas-utils@0.5.2(typescript@5.8.2)': dependencies: '@hyperjump/browser': 1.3.1 '@hyperjump/json-schema': 1.16.3(@hyperjump/browser@1.3.1) - '@scalar/helpers': 0.0.10 - '@scalar/json-magic': 0.4.2(typescript@5.8.2) - '@scalar/object-utils': 1.2.6 - '@scalar/openapi-types': 0.3.7 - '@scalar/themes': 0.13.16 - '@scalar/types': 0.2.15 - '@scalar/workspace-store': 0.15.5(typescript@5.8.2) + '@scalar/helpers': 0.0.12 + '@scalar/json-magic': 0.6.1 + '@scalar/object-utils': 1.2.8 + '@scalar/openapi-types': 0.5.0 + '@scalar/themes': 0.13.22 + '@scalar/types': 0.3.2 + '@scalar/workspace-store': 0.17.1(typescript@5.8.2) '@types/har-format': 1.2.16 flatted: 3.3.3 js-base64: 3.7.8 microdiff: 1.5.0 nanoid: 5.1.5 - type-fest: 4.41.0 + type-fest: 5.0.0 yaml: 2.8.0 - zod: 3.24.1 + zod: 4.1.11 transitivePeerDependencies: - supports-color - typescript - '@scalar/object-utils@1.2.6': + '@scalar/object-utils@1.2.8': dependencies: - '@scalar/helpers': 0.0.10 + '@scalar/helpers': 0.0.12 flatted: 3.3.3 just-clone: 6.2.0 ts-deepmerge: 7.0.3 - type-fest: 4.41.0 + type-fest: 5.0.0 - '@scalar/openapi-parser@0.20.5(typescript@5.8.2)': + '@scalar/openapi-parser@0.22.3': dependencies: - '@scalar/json-magic': 0.4.2(typescript@5.8.2) - '@scalar/openapi-types': 0.3.7 + '@scalar/json-magic': 0.6.1 + '@scalar/openapi-types': 0.5.0 + '@scalar/openapi-upgrader': 0.1.3 ajv: 8.17.1 ajv-draft-04: 1.0.0(ajv@8.17.1) ajv-formats: 3.0.1(ajv@8.17.1) jsonpointer: 5.0.1 leven: 4.1.0 yaml: 2.8.0 - transitivePeerDependencies: - - typescript - '@scalar/openapi-types@0.3.7': + '@scalar/openapi-types@0.5.0': dependencies: - zod: 3.24.1 + zod: 4.1.11 - '@scalar/postman-to-openapi@0.3.31(typescript@5.8.2)': + '@scalar/openapi-upgrader@0.1.3': dependencies: - '@scalar/helpers': 0.0.10 - '@scalar/oas-utils': 0.4.28(typescript@5.8.2) - '@scalar/openapi-types': 0.3.7 + '@scalar/openapi-types': 0.5.0 + + '@scalar/postman-to-openapi@0.3.40(typescript@5.8.2)': + dependencies: + '@scalar/helpers': 0.0.12 + '@scalar/oas-utils': 0.5.2(typescript@5.8.2) + '@scalar/openapi-types': 0.5.0 transitivePeerDependencies: - supports-color - typescript - '@scalar/snippetz@0.4.9': + '@scalar/snippetz@0.5.1': dependencies: - '@scalar/types': 0.2.15 + '@scalar/types': 0.3.2 stringify-object: 5.0.0 - '@scalar/themes@0.13.16': + '@scalar/themes@0.13.22': dependencies: - '@scalar/types': 0.2.15 + '@scalar/types': 0.3.2 nanoid: 5.1.5 '@scalar/typebox@0.1.1': {} - '@scalar/types@0.2.15': + '@scalar/types@0.3.2': dependencies: - '@scalar/openapi-types': 0.3.7 + '@scalar/openapi-types': 0.5.0 nanoid: 5.1.5 - zod: 3.24.1 + type-fest: 5.0.0 + zod: 4.1.11 - '@scalar/use-codemirror@0.12.34(typescript@5.8.2)': + '@scalar/use-codemirror@0.12.43(typescript@5.8.2)': dependencies: '@codemirror/autocomplete': 6.19.0 '@codemirror/commands': 6.9.0 @@ -14237,11 +14195,11 @@ snapshots: '@codemirror/language': 6.11.3 '@codemirror/lint': 6.9.0 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 - '@replit/codemirror-css-color-picker': 6.3.0(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.5) - '@scalar/components': 0.14.33(typescript@5.8.2) + '@replit/codemirror-css-color-picker': 6.3.0(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.6) + '@scalar/components': 0.15.1(typescript@5.8.2) codemirror: 6.0.2 vue: 3.5.22(typescript@5.8.2) transitivePeerDependencies: @@ -14249,16 +14207,15 @@ snapshots: - supports-color - typescript - '@scalar/use-hooks@0.2.4(typescript@5.8.2)': + '@scalar/use-hooks@0.2.5(typescript@5.8.2)': dependencies: '@scalar/use-toasts': 0.8.0(typescript@5.8.2) - '@vueuse/core': 10.11.1(vue@3.5.22(typescript@5.8.2)) + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.8.2)) cva: 1.0.0-beta.2(typescript@5.8.2) tailwind-merge: 2.6.0 vue: 3.5.22(typescript@5.8.2) zod: 3.24.1 transitivePeerDependencies: - - '@vue/composition-api' - typescript '@scalar/use-toasts@0.8.0(typescript@5.8.2)': @@ -14269,17 +14226,17 @@ snapshots: transitivePeerDependencies: - typescript - '@scalar/workspace-store@0.15.5(typescript@5.8.2)': + '@scalar/workspace-store@0.17.1(typescript@5.8.2)': dependencies: - '@scalar/code-highlight': 0.1.9 - '@scalar/helpers': 0.0.10 - '@scalar/json-magic': 0.4.2(typescript@5.8.2) - '@scalar/openapi-parser': 0.20.5(typescript@5.8.2) - '@scalar/snippetz': 0.4.9 + '@scalar/code-highlight': 0.2.0 + '@scalar/helpers': 0.0.12 + '@scalar/json-magic': 0.6.1 + '@scalar/openapi-upgrader': 0.1.3 + '@scalar/snippetz': 0.5.1 '@scalar/typebox': 0.1.1 - '@scalar/types': 0.2.15 + '@scalar/types': 0.3.2 github-slugger: 2.0.0 - type-fest: 4.41.0 + type-fest: 5.0.0 vue: 3.5.22(typescript@5.8.2) yaml: 2.8.0 transitivePeerDependencies: @@ -14430,39 +14387,6 @@ snapshots: '@types/node': 20.14.0 zod: 3.25.51 - '@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.24.2)': - optionalDependencies: - '@types/node': 20.17.24 - zod: 3.24.2 - - '@ts-rest/next@3.52.1(@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.51))(next@14.2.32(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.85.1))(zod@3.25.51)': - dependencies: - '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.51) - next: 14.2.32(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.85.1) - optionalDependencies: - zod: 3.25.51 - - '@ts-rest/next@3.52.1(@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.24.2))(next@14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(zod@3.24.2)': - dependencies: - '@ts-rest/core': 3.52.1(@types/node@20.17.24)(zod@3.24.2) - next: 14.2.32(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) - optionalDependencies: - zod: 3.24.2 - - '@ts-rest/open-api@3.52.1(@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.51))(zod@3.25.51)': - dependencies: - '@anatine/zod-openapi': 1.14.2(openapi3-ts@2.0.2)(zod@3.25.51) - '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.51) - openapi3-ts: 2.0.2 - zod: 3.25.51 - - '@ts-rest/open-api@3.52.1(@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.24.2))(zod@3.24.2)': - dependencies: - '@anatine/zod-openapi': 1.14.2(openapi3-ts@2.0.2)(zod@3.24.2) - '@ts-rest/core': 3.52.1(@types/node@20.17.24)(zod@3.24.2) - openapi3-ts: 2.0.2 - zod: 3.24.2 - '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -14773,7 +14697,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@22.18.9': + '@types/node@22.18.10': dependencies: undici-types: 6.21.0 @@ -14877,6 +14801,8 @@ snapshots: '@types/web-bluetooth@0.0.20': {} + '@types/web-bluetooth@0.0.21': {} + '@types/webidl-conversions@7.0.3': {} '@types/whatwg-url@11.0.5': @@ -15284,34 +15210,28 @@ snapshots: - '@vue/composition-api' - vue - '@vueuse/core@11.3.0(vue@3.5.22(typescript@5.8.2))': + '@vueuse/core@13.9.0(vue@3.5.22(typescript@5.8.2))': dependencies: - '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 11.3.0 - '@vueuse/shared': 11.3.0(vue@3.5.22(typescript@5.8.2)) - vue-demi: 0.14.10(vue@3.5.22(typescript@5.8.2)) - transitivePeerDependencies: - - '@vue/composition-api' - - vue + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.9.0 + '@vueuse/shared': 13.9.0(vue@3.5.22(typescript@5.8.2)) + vue: 3.5.22(typescript@5.8.2) - '@vueuse/integrations@11.3.0(axios@1.12.1)(focus-trap@7.6.5)(fuse.js@7.1.0)(nprogress@0.2.0)(qrcode@1.5.4)(vue@3.5.22(typescript@5.8.2))': + '@vueuse/integrations@13.9.0(axios@1.12.1)(focus-trap@7.6.5)(fuse.js@7.1.0)(nprogress@0.2.0)(qrcode@1.5.4)(vue@3.5.22(typescript@5.8.2))': dependencies: - '@vueuse/core': 11.3.0(vue@3.5.22(typescript@5.8.2)) - '@vueuse/shared': 11.3.0(vue@3.5.22(typescript@5.8.2)) - vue-demi: 0.14.10(vue@3.5.22(typescript@5.8.2)) + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.8.2)) + '@vueuse/shared': 13.9.0(vue@3.5.22(typescript@5.8.2)) + vue: 3.5.22(typescript@5.8.2) optionalDependencies: axios: 1.12.1 focus-trap: 7.6.5 fuse.js: 7.1.0 nprogress: 0.2.0 qrcode: 1.5.4 - transitivePeerDependencies: - - '@vue/composition-api' - - vue '@vueuse/metadata@10.11.1': {} - '@vueuse/metadata@11.3.0': {} + '@vueuse/metadata@13.9.0': {} '@vueuse/shared@10.11.1(vue@3.5.22(typescript@5.8.2))': dependencies: @@ -15320,12 +15240,9 @@ snapshots: - '@vue/composition-api' - vue - '@vueuse/shared@11.3.0(vue@3.5.22(typescript@5.8.2))': + '@vueuse/shared@13.9.0(vue@3.5.22(typescript@5.8.2))': dependencies: - vue-demi: 0.14.10(vue@3.5.22(typescript@5.8.2)) - transitivePeerDependencies: - - '@vue/composition-api' - - vue + vue: 3.5.22(typescript@5.8.2) '@webassemblyjs/ast@1.14.1': dependencies: @@ -16205,7 +16122,7 @@ snapshots: '@codemirror/lint': 6.9.0 '@codemirror/search': 6.5.11 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.5 + '@codemirror/view': 6.38.6 collapse-white-space@1.0.6: {} @@ -20746,7 +20663,7 @@ snapshots: dependencies: mimic-fn: 4.0.0 - openai@4.61.0(encoding@0.1.13)(zod@3.25.51): + openai@4.61.0(encoding@0.1.13)(zod@4.1.12): dependencies: '@types/node': 18.19.80 '@types/node-fetch': 2.6.12 @@ -20758,7 +20675,7 @@ snapshots: node-fetch: 2.7.0(encoding@0.1.13) qs: 6.14.0 optionalDependencies: - zod: 3.25.51 + zod: 4.1.12 transitivePeerDependencies: - encoding @@ -20778,10 +20695,6 @@ snapshots: openapi-types@12.1.3: {} - openapi3-ts@2.0.2: - dependencies: - yaml: 1.10.2 - option@0.2.4: {} optionator@0.9.4: @@ -22463,6 +22376,8 @@ snapshots: tabbable@6.2.0: {} + tagged-tag@1.0.0: {} + tailwind-merge@2.6.0: {} tailwindcss@4.1.14: {} @@ -22629,8 +22544,6 @@ snapshots: ts-dedent@2.2.0: {} - ts-deepmerge@6.2.1: {} - ts-deepmerge@7.0.3: {} ts-jest@29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@20.17.24)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.24)(typescript@5.8.2)))(typescript@5.8.2): @@ -22732,7 +22645,9 @@ snapshots: type-fest@2.19.0: {} - type-fest@4.41.0: {} + type-fest@5.0.0: + dependencies: + tagged-tag: 1.0.0 type-is@1.6.18: dependencies: @@ -23307,7 +23222,7 @@ snapshots: dependencies: vue: 3.5.22(typescript@5.8.2) - vue-router@4.5.1(vue@3.5.22(typescript@5.8.2)): + vue-router@4.6.0(vue@3.5.22(typescript@5.8.2)): dependencies: '@vue/devtools-api': 6.6.4 vue: 3.5.22(typescript@5.8.2) @@ -23638,6 +23553,10 @@ snapshots: - terser - typescript + zod-openapi@5.4.3(zod@4.1.12): + dependencies: + zod: 4.1.12 + zod-to-json-schema@3.24.5(zod@3.25.51): dependencies: zod: 3.25.51 @@ -23652,6 +23571,10 @@ snapshots: zod@3.25.51: {} + zod@4.1.11: {} + + zod@4.1.12: {} + zrender@5.4.1: dependencies: tslib: 2.3.0 diff --git a/projects/app/package.json b/projects/app/package.json index 4c2bcc353bdb..80ccc5afd68b 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -24,11 +24,8 @@ "@fortaine/fetch-event-source": "^3.0.6", "@modelcontextprotocol/sdk": "^1.12.1", "@node-rs/jieba": "2.0.1", - "@scalar/api-reference-react": "0.7.48", + "@scalar/api-reference-react": "^0.8.1", "@tanstack/react-query": "^4.24.10", - "@ts-rest/core": "^3.52.1", - "@ts-rest/next": "^3.52.1", - "@ts-rest/open-api": "^3.52.1", "ahooks": "^3.7.11", "axios": "^1.12.1", "date-fns": "2.30.0", @@ -45,6 +42,7 @@ "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "mermaid": "^10.9.4", + "minio": "^8.0.5", "nanoid": "^5.1.3", "next": "14.2.32", "next-i18next": "15.4.2", @@ -68,8 +66,7 @@ "request-ip": "^3.3.0", "sass": "^1.58.3", "use-context-selector": "^1.4.4", - "zod": "^3.24.2", - "minio": "^8.0.5" + "zod": "^3.24.2" }, "devDependencies": { "@svgr/webpack": "^6.5.1", diff --git a/projects/app/src/apiRouters/proApi.ts b/projects/app/src/apiRouters/proApi.ts deleted file mode 100644 index e3c9c4263335..000000000000 --- a/projects/app/src/apiRouters/proApi.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Handler } from '@fastgpt/global/common/tsRest/type'; -import { RestAPI } from '@/service/middleware/entry'; -import { request } from 'http'; -import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; - -const handler: Handler = async ({ req, res }) => { - return new Promise((resolve, reject) => { - try { - const requestPath = req.url || ''; - - if (!requestPath) { - throw new Error('url is empty'); - } - if (!FastGPTProUrl) { - throw new Error(`未配置商业版链接: ${requestPath}`); - } - - const parsedUrl = new URL(FastGPTProUrl); - - // 删除敏感的 header - const requestHeaders = { ...req.headers }; - delete requestHeaders?.rootkey; - - const requestResult = request({ - protocol: parsedUrl.protocol, - hostname: parsedUrl.hostname, - port: parsedUrl.port, - path: requestPath, - method: req.method, - headers: requestHeaders - }); - - req.pipe(requestResult); - - requestResult.on('response', (response) => { - Object.keys(response.headers).forEach((key) => { - // @ts-ignore - res.setHeader(key, response.headers[key]); - }); - response.statusCode && res.writeHead(response.statusCode); - response.pipe(res); - - // 代理完成后 resolve - response.on('end', () => { - resolve({} as any); - }); - }); - - requestResult.on('error', (e) => { - reject(e); - }); - } catch (error) { - reject(error); - } - }); -}; - -export const proApi = RestAPI(handler); diff --git a/projects/app/src/apiRouters/support/user/acccount/loginout.ts b/projects/app/src/apiRouters/support/user/acccount/loginout.ts deleted file mode 100644 index cb8a55ee4392..000000000000 --- a/projects/app/src/apiRouters/support/user/acccount/loginout.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Handler } from '@fastgpt/global/common/tsRest/type'; -import { RestAPI } from '@/service/middleware/entry'; -import { authCert, clearCookie } from '@fastgpt/service/support/permission/auth/common'; -import { delUserAllSession } from '@fastgpt/service/support/user/session'; -import type { accountContract } from '@fastgpt/global/common/tsRest/fastgpt/contracts/support/user/account'; - -const handler: Handler = async ({ req, res }) => { - try { - const { userId } = await authCert({ req, authToken: true }); - await delUserAllSession(userId); - } catch (error) {} - clearCookie(res); -}; - -export const loginout = RestAPI(handler); diff --git a/projects/app/src/pageComponents/chat/ChatHeader.tsx b/projects/app/src/pageComponents/chat/ChatHeader.tsx index a10f02524807..09bd7c7322ba 100644 --- a/projects/app/src/pageComponents/chat/ChatHeader.tsx +++ b/projects/app/src/pageComponents/chat/ChatHeader.tsx @@ -31,7 +31,7 @@ import { } from '@/pageComponents/chat/constants'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { usePathname } from 'next/navigation'; -import type { ChatSettingResponseType } from '@fastgpt/global/core/chat/setting/type'; +import type { ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; import { ChatTypeEnum } from '@/components/core/chat/ChatContainer/ChatBox/constants'; @@ -45,7 +45,7 @@ const ChatHeader = ({ chatSettings }: { pane: ChatSidebarPaneEnum; - chatSettings?: ChatSettingResponseType; + chatSettings?: ChatSettingType; history: ChatItemType[]; showHistory?: boolean; diff --git a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/AddFavouriteAppModal.tsx b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/AddFavouriteAppModal.tsx index 8eb13a61a51e..7d689caefb84 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/AddFavouriteAppModal.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/AddFavouriteAppModal.tsx @@ -63,7 +63,7 @@ const AddFavouriteAppModal = ({ onClose, onRefresh }: Props) => { manual: false, onSuccess(res) { setSelectedApps( - res.map((item) => ({ id: item.appId, name: item.name, avatar: item.avatar })) + res.map((item) => ({ id: item.appId, name: item.name, avatar: item.avatar || '' })) ); } }); @@ -81,7 +81,7 @@ const AddFavouriteAppModal = ({ onClose, onRefresh }: Props) => { const { run: updateFavourites, loading: isUpdating } = useRequest2( async () => { await updateFavouriteApps( - selectedApps.map((app, index) => ({ appId: app.id, order: index + 1 })) + selectedApps.map((app, order) => ({ appId: app.id, order: order + 1 })) ); }, { diff --git a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx index 3f5afb01e329..6fa9df1bf095 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx @@ -23,7 +23,7 @@ import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getFavouriteApps, updateChatSetting, updateFavouriteAppTags } from '@/web/core/chat/api'; import { useForm } from 'react-hook-form'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import type { ChatFavouriteAppResponseItemType } from '@fastgpt/global/core/chat/favouriteApp/type'; +import type { ChatFavouriteAppType } from '@fastgpt/global/core/chat/favouriteApp/type'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import DndDrag, { Draggable } from '@fastgpt/web/components/common/DndDrag'; @@ -211,9 +211,7 @@ const SaveTagForAppSubPanel = ({ } ); - const [localAllFavourites, setLocalAllFavourites] = useState( - [] - ); + const [localAllFavourites, setLocalAllFavourites] = useState([]); useEffect(() => { setLocalAllFavourites(favouriteApps); diff --git a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx index 717e9d9051c1..6e11dd166b81 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx @@ -29,7 +29,7 @@ import { deleteFavouriteApp, getFavouriteApps, updateFavouriteAppOrder } from '@ import DndDrag, { Draggable } from '@fastgpt/web/components/common/DndDrag'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { Box, Wrap } from '@chakra-ui/react'; -import type { ChatFavouriteAppResponseItemType } from '@fastgpt/global/core/chat/favouriteApp/type'; +import type { ChatFavouriteAppType } from '@fastgpt/global/core/chat/favouriteApp/type'; import MyBox from '@fastgpt/web/components/common/MyBox'; import MyPopover from '@fastgpt/web/components/common/MyPopover'; import type { ChatFavouriteTagType } from '@fastgpt/global/core/chat/favouriteApp/type'; @@ -86,7 +86,7 @@ const FavouriteAppSetting = ({ Header }: Props) => { ) ); - const [localFavourites, setLocalFavourites] = useState([]); + const [localFavourites, setLocalFavourites] = useState([]); // search favourite apps by apps' name and tag const { loading: isSearching, runAsync: getApps } = useRequest2( @@ -107,13 +107,8 @@ const FavouriteAppSetting = ({ Header }: Props) => { // update app order const { runAsync: orderApp } = useRequest2( - async (list: ChatFavouriteAppResponseItemType[]) => { - await updateFavouriteAppOrder( - list.map((item, idx) => ({ - id: item._id, - order: idx - })) - ); + async (list: ChatFavouriteAppType[]) => { + await updateFavouriteAppOrder(list.map((item, idx) => ({ id: item._id, order: idx }))); getApps(); }, { manual: true } @@ -252,7 +247,7 @@ const FavouriteAppSetting = ({ Header }: Props) => { {/* 表格内容 */} {localFavourites.length > 0 ? ( - + dataList={localFavourites} renderInnerPlaceholder={false} onDragEndCb={(list) => { diff --git a/projects/app/src/pageComponents/chat/ChatSetting/HomepageSetting/index.tsx b/projects/app/src/pageComponents/chat/ChatSetting/HomepageSetting/index.tsx index 6c700f89d6af..b224d69bc077 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/HomepageSetting/index.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/HomepageSetting/index.tsx @@ -16,11 +16,6 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import { updateChatSetting } from '@/web/core/chat/api'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import ImageUpload from '@/pageComponents/chat/ChatSetting/ImageUpload'; -import type { - ChatQuickAppType, - ChatSelectedToolType -} from '@fastgpt/global/core/chat/setting/type'; -import type { ChatSettingUpdateType } from '@fastgpt/global/core/chat/setting/type'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import ToolSelectModal from '@/pageComponents/chat/ChatSetting/ToolSelectModal'; import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d'; @@ -35,7 +30,7 @@ import { } from '@/pageComponents/chat/constants'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import dynamic from 'next/dynamic'; -import type { ChatSettingResponseType } from '@fastgpt/global/core/chat/setting/type'; +import type { ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; const AddQuickAppModal = dynamic( () => import('@/pageComponents/chat/ChatSetting/HomepageSetting/AddQuickAppModal') @@ -46,11 +41,6 @@ type Props = { onDiagramShow: (show: boolean) => void; }; -type FormValues = Omit & { - selectedTools: ChatSelectedToolType[]; - quickAppList: ChatQuickAppType[]; -}; - const HomepageSetting = ({ Header, onDiagramShow }: Props) => { const { isPc } = useSystem(); const { t } = useTranslation(); @@ -60,7 +50,7 @@ const HomepageSetting = ({ Header, onDiagramShow }: Props) => { const refreshChatSetting = useContextSelector(ChatSettingContext, (v) => v.refreshChatSetting); const chatSettings2Form = useCallback( - (data?: ChatSettingResponseType) => { + (data?: ChatSettingType) => { return { enableHome: data?.enableHome, slogan: data?.slogan || t('chat:setting.home.slogan.default'), @@ -75,7 +65,7 @@ const HomepageSetting = ({ Header, onDiagramShow }: Props) => { [t] ); - const { register, handleSubmit, reset, setValue, watch } = useForm({ + const { register, handleSubmit, reset, setValue, watch } = useForm({ defaultValues: chatSettings2Form(chatSettings) }); @@ -123,7 +113,7 @@ const HomepageSetting = ({ Header, onDiagramShow }: Props) => { ); const { runAsync: onSubmit, loading: isSaving } = useRequest2( - async (values: FormValues) => { + async (values: ChatSettingType) => { const { quickAppList, ...params } = values; return updateChatSetting({ ...params, diff --git a/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx b/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx index 357cac859146..2734721687e3 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx @@ -44,12 +44,12 @@ import { type AppSimpleEditFormType } from '@fastgpt/global/core/app/type'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { workflowStartNodeId } from '@/web/core/app/constants'; import ConfigToolModal from '@/pageComponents/app/detail/SimpleApp/components/ConfigToolModal'; -import type { ChatSettingResponseType } from '@fastgpt/global/core/chat/setting/type'; +import type { ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; import CostTooltip from '@/components/core/app/plugin/CostTooltip'; import { useSystemStore } from '@/web/common/system/useSystemStore'; type Props = { - selectedTools: ChatSettingResponseType['selectedTools']; + selectedTools: ChatSettingType['selectedTools']; chatConfig?: AppSimpleEditFormType['chatConfig']; onAddTool: (tool: FlowNodeTemplateType) => void; onRemoveTool: (tool: NodeTemplateListItemType) => void; diff --git a/projects/app/src/pages/_app.tsx b/projects/app/src/pages/_app.tsx index 0c874bfe9517..19ff267f2dd4 100644 --- a/projects/app/src/pages/_app.tsx +++ b/projects/app/src/pages/_app.tsx @@ -27,6 +27,8 @@ type AppPropsWithLayout = AppProps & { // 哪些路由有自定义 Head const routesWithCustomHead = ['/chat', '/chat/share', '/app/detail/', '/dataset/detail']; +// 哪些路由不需要 Layout +const routesWithoutLayout = ['/openapi']; function App({ Component, pageProps }: AppPropsWithLayout) { const { feConfigs, scripts, title } = useInitApp(); @@ -49,6 +51,7 @@ function App({ Component, pageProps }: AppPropsWithLayout) { const router = useRouter(); const showHead = !router?.pathname || !routesWithCustomHead.includes(router.pathname); + const shouldUseLayout = !router?.pathname || !routesWithoutLayout.includes(router.pathname); if (router.pathname === '/openapi') { return ( @@ -80,7 +83,11 @@ function App({ Component, pageProps }: AppPropsWithLayout) { - {setLayout()} + {shouldUseLayout ? ( + {setLayout()} + ) : ( + setLayout() + )} diff --git a/projects/app/src/pages/api/[...ts-rest].ts b/projects/app/src/pages/api/[...ts-rest].ts deleted file mode 100644 index 3e34ecdd432c..000000000000 --- a/projects/app/src/pages/api/[...ts-rest].ts +++ /dev/null @@ -1,31 +0,0 @@ -import { createServerRouter } from '@fastgpt/global/common/tsRest/fastgpt/router'; -import { proApi } from '@/apiRouters/proApi'; -import { loginout } from '@/apiRouters/support/user/acccount/loginout'; -import { createServerRoute } from '@fastgpt/global/common/tsRest/fastgpt/router'; - -const router = createServerRoute({ - core: { - chat: { - setting: { - favourite: { - list: proApi, - update: proApi, - delete: proApi, - order: proApi, - tags: proApi - }, - detail: proApi, - update: proApi - } - } - }, - support: { - user: { - account: { - loginout - } - } - } -}); - -export default createServerRouter(router); diff --git a/projects/app/src/pages/api/openapi.json.ts b/projects/app/src/pages/api/openapi.json.ts new file mode 100644 index 000000000000..6fb172df4777 --- /dev/null +++ b/projects/app/src/pages/api/openapi.json.ts @@ -0,0 +1,6 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { openAPIDocument } from '@fastgpt/global/openapi'; + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + res.status(200).json(openAPIDocument); +} diff --git a/projects/app/src/pages/openapi.tsx b/projects/app/src/pages/openapi.tsx new file mode 100644 index 000000000000..7994eb820dfe --- /dev/null +++ b/projects/app/src/pages/openapi.tsx @@ -0,0 +1,22 @@ +import { ApiReferenceReact } from '@scalar/api-reference-react'; +import '@scalar/api-reference-react/style.css'; +import { Box } from '@chakra-ui/react'; + +function OpenAPIPage() { + return ( + + + + ); +} + +export default OpenAPIPage; diff --git a/projects/app/src/pages/openapi/index.tsx b/projects/app/src/pages/openapi/index.tsx deleted file mode 100644 index 72fac8b51ce0..000000000000 --- a/projects/app/src/pages/openapi/index.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import NextHead from '@/components/common/NextHead'; -import { ApiReferenceReact } from '@scalar/api-reference-react'; -import { fastgptOpenApiDocument } from '@fastgpt/global/common/tsRest/fastgpt/openapi'; - -export default function OpenAPI() { - const config = { - content: fastgptOpenApiDocument - }; - - return ( - <> - - - - ); -} diff --git a/projects/app/src/service/middleware/entry.ts b/projects/app/src/service/middleware/entry.ts index 0b8417051f83..d15af65619b4 100644 --- a/projects/app/src/service/middleware/entry.ts +++ b/projects/app/src/service/middleware/entry.ts @@ -1,64 +1,3 @@ import { NextEntry } from '@fastgpt/service/common/middle/entry'; -import type { AppRoute, Args, Handler, Endpoint } from '@fastgpt/global/common/tsRest/type'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { withNextCors } from '@fastgpt/service/common/middle/cors'; -import { processError } from '@fastgpt/service/common/response'; -import { clearCookie } from '@fastgpt/service/support/permission/auth/common'; export const NextAPI = NextEntry({ beforeCallback: [] }); - -export function RestAPI(handler: Handler): Endpoint { - return (async (args: Args) => { - const start = Date.now(); - const url = `${args.req?.method || 'Unknown'} ${args.req?.url || 'Unknown'}`; - addLog.debug(`RestAPI Request start ${url}`); - - await Promise.all([withNextCors(args.req, args.res)]); - - try { - const body = await handler(args); - - // Get request duration - const duration = Date.now() - start; - if (duration < 2000) { - addLog.debug(`RestAPI Request finish ${url}, time: ${duration}ms`); - } else { - addLog.warn(`RestAPI Request finish ${url}, time: ${duration}ms`); - } - - return { - status: 200 as const, - body: { - code: 200, - data: body, - message: '', - statusText: '' - } - } as any; - } catch (error) { - const duration = Date.now() - start; - - // 使用统一的错误处理逻辑 - const processedError = processError({ - error, - url, - defaultCode: 500 - }); - - // 如果需要清除 cookie - if (processedError.shouldClearCookie) { - clearCookie(args.res); - } - - return { - status: 200 as const, - body: { - code: processedError.code, - statusText: processedError.statusText, - message: processedError.message, - data: processedError.data - } - } as any; - } - }) as unknown as Endpoint; -} diff --git a/projects/app/src/web/common/api/client.ts b/projects/app/src/web/common/api/client.ts index 22d8fc7fdd4e..6e2c3bae29a6 100644 --- a/projects/app/src/web/common/api/client.ts +++ b/projects/app/src/web/common/api/client.ts @@ -1,9 +1,5 @@ -import { createFastGPTClient } from '@fastgpt/global/common/tsRest/fastgpt/client'; import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode'; import { getNanoid } from '@fastgpt/global/common/string/tools'; -import type { ApiFetcherArgs } from '@ts-rest/core'; -import { tsRestFetchApi } from '@ts-rest/core'; -import { AnyResponseSchema } from '@fastgpt/global/common/tsRest/type'; import { ZodError } from 'zod'; import { getWebReqUrl, subRoute } from '@fastgpt/web/common/system/utils'; import { i18nT } from '@fastgpt/web/i18n/utils'; @@ -11,96 +7,6 @@ import { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; import { useSystemStore } from '../system/useSystemStore'; import { clearToken } from '@/web/support/user/auth'; -const queue = new Map(); -type BeforeFetchOptions = ApiFetcherArgs & { max?: number }; -const beforeFetch = ( - options: BeforeFetchOptions -): - | { - limit: { id: string; url: string; release: () => void }; - } - | undefined => { - const checkMaxRequestLimitation = (options: { - url: string; - max: number; - }): { - id: string; - signal: AbortSignal; - release: () => void; - } => { - const { url, max } = options; - const id = getNanoid(); - const controller = new AbortController(); - const item = queue.get(url); - - const current = item ?? []; - if (current.length >= max) { - const first = current.shift()!; - first.controller.abort(); - } - - current.push({ id, controller }); - if (!item) queue.set(url, current); - - const release = () => { - const item = queue.get(url); - if (!item) return; - - const index = item.findIndex((item) => item.id === id); - if (index !== -1) { - item.splice(index, 1); - } - - if (item.length <= 0) { - queue.delete(url); - } - }; - - return { id, signal: controller.signal, release }; - }; - - const { max, ...args } = options; - if (!max || max <= 0) return; - - const { id, signal, release } = checkMaxRequestLimitation({ url: args.path, max }); - args.fetchOptions ??= {}; - args.fetchOptions.signal = signal; - - return { - limit: { id, url: args.path, release } - }; -}; - -const afterFetch = (response: Awaited>) => { - if (response.status === 200) { - try { - const data = AnyResponseSchema.parse(response.body); - - if (data === undefined) { - console.log('error->', data, 'data is empty'); - return Promise.reject('服务器异常'); - } else if (data.code < 200 || data.code >= 400) { - return Promise.reject(data); - } - - response.body = data.data; - - return response; - } catch (error) { - if (error instanceof ZodError) { - return Promise.reject(error.message); - } - - return Promise.reject('Unknown error while intercept response'); - } - } else { - return Promise.reject(response); - } -}; -const requestFinish = (prepare?: ReturnType) => { - prepare?.limit?.release?.(); -}; - const responseError = (err: any) => { console.log('error->', '请求错误', err); const isOutlinkPage = { @@ -150,66 +56,3 @@ const responseError = (err: any) => { } return Promise.reject(data); }; - -export const client = createFastGPTClient({ - baseUrl: getWebReqUrl('/api'), - throwOnUnknownStatus: true, - validateResponse: false, - credentials: 'include', - baseHeaders: { - 'Content-Type': 'application/json;charset=utf-8' - }, - api: tsRestFetchApi -}); - -// Simplified types to reduce TS computation overhead -type AnyEndpointFn = (options?: any) => Promise; - -// Helper to infer response body type -type InferResponseBody = - Awaited> extends { status: 200; body: infer B } ? B : never; - -// Helper to infer options type -type InferOptions = NonNullable[0]>; - -// Helper to extract body from options -type InferBody = InferOptions extends { body: infer B } ? B : never; - -// Helper to extract query from options -type InferQuery = InferOptions extends { query: infer Q } ? Q : never; - -// Combined params type -type Params = (InferBody extends never ? {} : InferBody) & - (InferQuery extends never ? {} : InferQuery); - -// Additional options (excluding body and query) -type Options = Omit, 'body' | 'query'>; - -const call = async ( - api: T, - options: InferOptions -): Promise> => { - const prepare = beforeFetch(options as any); - - const res = await api(options) - .then(afterFetch) - .catch(responseError) - .finally(() => requestFinish(prepare)); - - return res.body as InferResponseBody; -}; - -export const RestAPI = ( - endpoint: T, - transform?: (params: Params) => { - body?: InferBody extends never ? any : InferBody; - query?: InferQuery extends never ? any : InferQuery; - } -) => { - return (params?: Params, options?: Options): Promise> => { - const transformedData = params && transform ? transform(params) : {}; - const finalOptions = { ...options, ...transformedData } as InferOptions; - - return call(endpoint, finalOptions); - }; -}; diff --git a/projects/app/src/web/core/chat/api.ts b/projects/app/src/web/core/chat/api.ts index 626547591548..d34c8bf1ed5a 100644 --- a/projects/app/src/web/core/chat/api.ts +++ b/projects/app/src/web/core/chat/api.ts @@ -30,7 +30,12 @@ import type { GetCollectionQuoteProps, GetCollectionQuoteRes } from '@/pages/api/core/chat/quote/getCollectionQuote'; -import { RestAPI, client } from '../../common/api/client'; +import type { ChatSettingModelType, ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; +import type { + GetChatFavouriteListParamsType, + UpdateFavouriteAppParamsType +} from '@fastgpt/global/core/chat/favouriteApp/api'; +import type { ChatFavouriteAppType } from '@fastgpt/global/core/chat/favouriteApp/type'; /** * 获取初始化聊天内容 @@ -109,26 +114,22 @@ export const getCollectionQuote = (data: GetCollectionQuoteProps) => POST(`/core/chat/quote/getCollectionQuote`, data); /*---------- chat setting ------------*/ -export const getChatSetting = RestAPI(client.core.chat.setting.detail); -export const updateChatSetting = RestAPI(client.core.chat.setting.update, (params) => ({ - body: params -})); -export const getFavouriteApps = RestAPI(client.core.chat.setting.favourite.list); -export const updateFavouriteApps = RestAPI(client.core.chat.setting.favourite.update, (params) => ({ - body: params -})); -export const updateFavouriteAppOrder = RestAPI( - client.core.chat.setting.favourite.order, - (params) => ({ - body: params - }) -); -export const updateFavouriteAppTags = RestAPI( - client.core.chat.setting.favourite.tags, - (params) => ({ - body: params - }) -); -export const deleteFavouriteApp = RestAPI(client.core.chat.setting.favourite.delete, (params) => ({ - query: params -})); +export const getChatSetting = () => GET('/proApi/core/chat/setting/detail'); + +export const updateChatSetting = (data: Partial) => + POST>('/proApi/core/chat/setting/update', data); + +export const getFavouriteApps = (data?: GetChatFavouriteListParamsType) => + GET('/proApi/core/chat/setting/favourite/list', data); + +export const updateFavouriteApps = (data: UpdateFavouriteAppParamsType[]) => + POST('/proApi/core/chat/setting/favourite/update', data); + +export const updateFavouriteAppOrder = (data: { id: string; order: number }[]) => + PUT('/proApi/core/chat/setting/favourite/order', data); + +export const updateFavouriteAppTags = (data: { id: string; tags: string[] }[]) => + PUT('/proApi/core/chat/setting/favourite/tags', data); + +export const deleteFavouriteApp = (data: { id: string }) => + DELETE('/proApi/core/chat/setting/favourite/delete', data); diff --git a/projects/app/src/web/core/chat/context/chatSettingContext.tsx b/projects/app/src/web/core/chat/context/chatSettingContext.tsx index 55f49865cd19..fe47915f5610 100644 --- a/projects/app/src/web/core/chat/context/chatSettingContext.tsx +++ b/projects/app/src/web/core/chat/context/chatSettingContext.tsx @@ -7,7 +7,7 @@ import { } from '@/pageComponents/chat/constants'; import { getChatSetting } from '@/web/core/chat/api'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; -import type { ChatSettingResponseType } from '@fastgpt/global/core/chat/setting/type'; +import type { ChatSettingType } from '@fastgpt/global/core/chat/setting/type'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useRouter } from 'next/router'; import { useCallback, useEffect, useMemo, useState } from 'react'; @@ -22,8 +22,8 @@ export type ChatSettingContextValue = { ) => void; collapse: CollapseStatusType; onTriggerCollapse: () => void; - chatSettings: ChatSettingResponseType | undefined; - refreshChatSetting: () => Promise; + chatSettings: ChatSettingType | undefined; + refreshChatSetting: () => Promise; logos: { wideLogoUrl?: string; squareLogoUrl?: string }; }; @@ -34,7 +34,7 @@ export const ChatSettingContext = createContext({ onTriggerCollapse: () => {}, chatSettings: undefined, logos: { wideLogoUrl: '', squareLogoUrl: '' }, - refreshChatSetting: function (): Promise { + refreshChatSetting: function (): Promise { throw new Error('Function not implemented.'); } }); @@ -113,7 +113,7 @@ export const ChatSettingContextProvider = ({ children }: { children: React.React } }, [pane, handlePaneChange]); - const logos: Pick = useMemo( + const logos: Pick = useMemo( () => ({ wideLogoUrl: chatSettings?.wideLogoUrl, squareLogoUrl: chatSettings?.squareLogoUrl diff --git a/projects/app/src/web/support/user/api.ts b/projects/app/src/web/support/user/api.ts index 9325a10976a3..5b8af1df4efe 100644 --- a/projects/app/src/web/support/user/api.ts +++ b/projects/app/src/web/support/user/api.ts @@ -16,7 +16,6 @@ import type { } from '@fastgpt/global/support/user/login/api.d'; import type { preLoginResponse } from '@/pages/api/support/user/account/preLogin'; import type { WxLoginProps } from '@fastgpt/global/support/user/api.d'; -import { client, RestAPI } from '@/web/common/api/client'; export const sendAuthCode = (data: { username: string; @@ -95,7 +94,7 @@ export const postLogin = ({ password, ...props }: PostLoginProps) => password: hashStr(password) }); -export const loginOut = RestAPI(client.support.user.account.logout); +export const loginOut = () => GET('/support/user/account/loginout'); export const putUserInfo = (data: UserUpdateParams) => PUT('/support/user/account/update', data);