feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { vi, describe, it, expect, beforeEach, type Mock } from 'vitest';
import { DeveloperApi, PlaygroundApi } from '@coze-arch/bot-api';
import { useUserStore, defaultState } from '../user';
vi.mock('@coze-arch/bot-api', () => ({
DeveloperApi: {
GetUserAuthList: vi.fn(),
},
PlaygroundApi: {
MGetUserBasicInfo: vi.fn(),
},
}));
describe('useUserStore', () => {
beforeEach(() => {
useUserStore.setState(defaultState);
vi.clearAllMocks();
});
it('should have the correct default state', () => {
const state = useUserStore.getState();
expect(state.isSettled).toBe(false);
expect(state.userInfo).toBeNull();
expect(state.hasError).toBe(false);
expect(state.userAuthInfos).toEqual([]);
expect(state.userLabel).toBeNull();
});
describe('actions', () => {
it('reset should reset state to default and set isSettled to true', () => {
useUserStore.setState({
userInfo: { user_id_str: '123' } as any,
isSettled: false,
});
useUserStore.getState().reset();
const state = useUserStore.getState();
expect(state.userInfo).toBeNull();
expect(state.userAuthInfos).toEqual([]);
expect(state.userLabel).toBeNull();
expect(state.isSettled).toBe(true);
expect(state.hasError).toBe(false);
});
it('setIsSettled should update isSettled', () => {
useUserStore.getState().setIsSettled(true);
expect(useUserStore.getState().isSettled).toBe(true);
useUserStore.getState().setIsSettled(false);
expect(useUserStore.getState().isSettled).toBe(false);
});
describe('setUserInfo', () => {
it('should update userInfo', () => {
const newUserInfo = {
user_id_str: 'testUser',
name: 'Test User',
} as any;
useUserStore.getState().setUserInfo(newUserInfo);
expect(useUserStore.getState().userInfo).toEqual(newUserInfo);
});
it('should call fetchUserLabel if user_id_str changes', async () => {
const newUserInfo = {
user_id_str: 'newUser123',
name: 'New User',
} as any;
const initialUserInfo = {
user_id_str: 'oldUser456',
name: 'Old User',
} as any;
// Set an initial user
useUserStore.setState({ userInfo: initialUserInfo });
(PlaygroundApi.MGetUserBasicInfo as Mock).mockResolvedValueOnce({
id_user_info_map: {
[newUserInfo.user_id_str]: {
user_label: { label_type: 1, text: 'Test Label' },
},
},
});
useUserStore.getState().setUserInfo(newUserInfo);
expect(useUserStore.getState().userInfo).toEqual(newUserInfo);
await vi.waitFor(() => {
expect(PlaygroundApi.MGetUserBasicInfo).toHaveBeenCalledWith({
user_ids: [newUserInfo.user_id_str],
});
});
await vi.waitFor(() => {
expect(useUserStore.getState().userLabel).toEqual({
label_type: 1,
text: 'Test Label',
});
});
});
it('should not call fetchUserLabel if user_id_str is the same', () => {
const userInfo = { user_id_str: 'user123', name: 'Test User' } as any;
useUserStore.setState({ userInfo });
useUserStore.getState().setUserInfo(userInfo);
expect(PlaygroundApi.MGetUserBasicInfo).not.toHaveBeenCalled();
});
});
describe('getUserAuthInfos', () => {
it('should fetch and set userAuthInfos on success', async () => {
const mockAuthInfos = [
{ auth_type: 'email', auth_key: 'test@example.com' },
];
(DeveloperApi.GetUserAuthList as Mock).mockResolvedValueOnce({
data: mockAuthInfos,
});
await useUserStore.getState().getUserAuthInfos();
expect(DeveloperApi.GetUserAuthList).toHaveBeenCalledTimes(1);
expect(useUserStore.getState().userAuthInfos).toEqual(mockAuthInfos);
});
});
});
});

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools, subscribeWithSelector } from 'zustand/middleware';
import { create } from 'zustand';
import {
type UserAuthInfo,
type UserLabel,
} from '@coze-arch/bot-api/developer_api';
import { DeveloperApi, PlaygroundApi } from '@coze-arch/bot-api';
import { type UserInfo } from '../types';
export interface UserStoreState {
isSettled: boolean;
hasError: boolean;
userInfo: UserInfo | null;
userAuthInfos: UserAuthInfo[];
userLabel: UserLabel | null;
}
export interface UserStoreAction {
reset: () => void;
setIsSettled: (isSettled: boolean) => void;
setUserInfo: (userInfo: UserInfo | null) => void;
getUserAuthInfos: () => Promise<void>;
}
export const defaultState: UserStoreState = {
isSettled: false,
userInfo: null,
hasError: false,
userAuthInfos: [],
userLabel: null,
};
export const useUserStore = create<UserStoreState & UserStoreAction>()(
devtools(
subscribeWithSelector((set, get) => ({
...defaultState,
reset: () => {
set({ ...defaultState, isSettled: true });
},
setIsSettled: isSettled => {
set({
isSettled,
});
},
setUserInfo: (userInfo: UserInfo | null) => {
if (
userInfo?.user_id_str &&
userInfo?.user_id_str !== get().userInfo?.user_id_str
) {
fetchUserLabel(userInfo?.user_id_str);
}
set({
userInfo,
});
},
getUserAuthInfos: async () => {
const { data = [] } = await DeveloperApi.GetUserAuthList();
set({ userAuthInfos: data });
},
})),
{
enabled: IS_DEV_MODE,
name: 'botStudio.userStore',
},
),
);
const fetchUserLabel = async (id: string) => {
const res = await PlaygroundApi.MGetUserBasicInfo({ user_ids: [id] });
const userLabel = res?.id_user_info_map?.[id]?.user_label;
useUserStore.setState({ userLabel });
};