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,31 @@
import { mergeConfig } from 'vite';
import svgr from 'vite-plugin-svgr';
/** @type { import('@storybook/react-vite').StorybookConfig } */
const config = {
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.tsx'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-onboarding',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
docs: {
autodocs: 'tag',
},
viteFinal: config =>
mergeConfig(config, {
plugins: [
svgr({
svgrOptions: {
native: false,
},
}),
],
}),
};
export default config;

View File

@@ -0,0 +1,14 @@
/** @type { import('@storybook/react').Preview } */
const preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;

View File

@@ -0,0 +1,5 @@
const { defineConfig } = require('@coze-arch/stylelint-config');
module.exports = defineConfig({
extends: [],
});

View File

@@ -0,0 +1,66 @@
# @coze-foundation/space-store-adapter
基座中的空间store
## Overview
This package is part of the Coze Studio monorepo and provides state management functionality. It includes store.
## Getting Started
### Installation
Add this package to your `package.json`:
```json
{
"dependencies": {
"@coze-foundation/space-store-adapter": "workspace:*"
}
}
```
Then run:
```bash
rush update
```
### Usage
```typescript
import { /* exported functions/components */ } from '@coze-foundation/space-store-adapter';
// Example usage
// TODO: Add specific usage examples
```
## Features
- Store
## API Reference
### Exports
- `useSpaceStore`
For detailed API documentation, please refer to the TypeScript definitions.
## Development
This package is built with:
- TypeScript
- Modern JavaScript
- Vitest for testing
- ESLint for code quality
## Contributing
This package is part of the Coze Studio monorepo. Please follow the monorepo contribution guidelines.
## License
Apache-2.0

View File

@@ -0,0 +1,73 @@
/*
* 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.
*/
// eslint-disable-next-line @coze-arch/no-batch-import-or-export, @typescript-eslint/consistent-type-imports
import * as zustand from 'zustand';
import { act } from '@testing-library/react';
const { create: actualCreate, createStore: actualCreateStore } =
// @ts-expect-error -- UT 忽略
await vi.importActual<typeof zustand>('zustand');
// a variable to hold reset functions for all stores declared in the app
export const storeResetFns = new Set<() => void>();
const createUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
const store = actualCreate(stateCreator);
const initialState = store.getState();
storeResetFns.add(() => {
store.setState(initialState, true);
});
return store;
};
// when creating a store, we get its initial state, create a reset function and add it in the set
export const create = (<T>(stateCreator: zustand.StateCreator<T>) => {
console.log('zustand create mock');
// to support curried version of create
return typeof stateCreator === 'function'
? createUncurried(stateCreator)
: createUncurried;
}) as typeof zustand.create;
const createStoreUncurried = <T>(stateCreator: zustand.StateCreator<T>) => {
const store = actualCreateStore(stateCreator);
const initialState = store.getState();
storeResetFns.add(() => {
store.setState(initialState, true);
});
return store;
};
// when creating a store, we get its initial state, create a reset function and add it in the set
export const createStore = (<T>(stateCreator: zustand.StateCreator<T>) => {
console.log('zustand createStore mock');
// to support curried version of createStore
return typeof stateCreator === 'function'
? createStoreUncurried(stateCreator)
: createStoreUncurried;
}) as typeof zustand.createStore;
// reset all stores after each test run
afterEach(() => {
act(() => {
storeResetFns.forEach(resetFn => {
resetFn();
});
});
});

View File

@@ -0,0 +1,259 @@
/*
* 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 { SpaceType } from '@coze-arch/bot-api/playground_api';
import { PlaygroundApi } from '@coze-arch/bot-api';
import { useSpaceStore, defaultState } from '../src/space';
vi.mock('@coze-arch/bot-flags', () => ({
getFlags: vi.fn(),
}));
vi.mock('@coze-arch/bot-error', () => ({
CustomError: vi.fn(),
}));
// FIXME 改为按需 mock
vi.mock('@coze-arch/bot-api', () => ({
DeveloperApi: {
GetUserAuthList: vi
.fn()
.mockResolvedValueOnce({ data: [{ foo: 1 }] })
.mockRejectedValueOnce('error'),
ExitSpace: vi
.fn()
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 1 }),
TransferSpace: vi
.fn()
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 1 }),
},
PlaygroundApi: {
GetSpaceListV2: vi
.fn()
// .mockResolvedValueOnce({ code: 0 })
// .mockResolvedValueOnce({ code: 1 })
// .mockResolvedValueOnce({ code: 0 })
// .mockResolvedValueOnce({ code: 0 })
// mock 缺失 personal store && 轮询失败
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({
code: 0,
data: {
bot_space_list: [
{
id: '123',
app_ids: null,
name: 'Personal',
description: 'Personal',
icon_url:
'https://lf16-alice-tos-sign.oceanapi-i18n.com/obj/ocean-cloud-tos-sg/FileBizType.BIZ_BOT_SPACE/personal.png?lk3s=50ccb0c5\u0026x-expires=1707120346\u0026x-signature=vvsdzfbTwD2qIYxXa%2BcjGo1H%2Beg%3D',
space_type: 1,
connectors: [
{
id: '123',
name: 'Cici',
icon: 'FileBizType.BIZ_BOT_ICON/7269764022575842322_1700191555077003149.jpg',
connector_status: 0,
},
],
hide_operation: false,
},
],
has_personal_space: true,
team_space_num: 0,
},
})
.mockRejectedValueOnce(new Error()),
SaveSpaceV2: vi
.fn()
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 1 })
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 1 }),
DeleteSpaceV2: vi.fn(),
ExitSpaceV2: vi.fn(),
TransferSpaceV2: vi
.fn()
.mockResolvedValueOnce({ code: 0 })
.mockResolvedValueOnce({ code: 1 }),
},
}));
vi.mock('@coze-arch/logger', () => ({
reporter: {
errorEvent: vi.fn(),
},
}));
describe('useSpaceStore', () => {
it('should init with default state', () => {
const state = useSpaceStore.getState();
expect(state).toMatchObject(defaultState);
});
it('reset', () => {
useSpaceStore.setState({
space: {
id: '1',
},
});
useSpaceStore.getState().reset();
expect(useSpaceStore.getState()).toMatchObject(defaultState);
});
it('getSpaceId', () => {
expect(() => useSpaceStore.getState().getSpaceId()).throw();
useSpaceStore.setState({
space: {
id: '1',
},
});
expect(useSpaceStore.getState().getSpaceId()).toBe('1');
});
it('getPersonalSpaceID', () => {
expect(useSpaceStore.getState().getPersonalSpaceID()).toBeUndefined();
useSpaceStore.setState({
spaces: {
...useSpaceStore.getState().spaces,
bot_space_list: [
{ id: '1', space_type: SpaceType.Personal },
{ id: '2', space_type: SpaceType.Team },
],
},
});
expect(useSpaceStore.getState().getPersonalSpaceID()).toBe('1');
});
it('checkSpaceID', () => {
expect(useSpaceStore.getState().checkSpaceID('')).toBe(false);
useSpaceStore.setState({
spaces: {
...useSpaceStore.getState().spaces,
bot_space_list: [{ id: '1' }],
},
});
expect(useSpaceStore.getState().checkSpaceID('1')).toBe(true);
});
it('setSpace', () => {
useSpaceStore.getState().setSpace('');
expect(useSpaceStore.getState().space).toEqual({ id: '' });
useSpaceStore.setState({
spaces: {
...useSpaceStore.getState().spaces,
bot_space_list: [{ id: '1' }],
},
});
useSpaceStore.getState().setSpace('1');
expect(useSpaceStore.getState().space).toEqual({ id: '1' });
useSpaceStore.setState({
spaces: {
...useSpaceStore.getState().spaces,
bot_space_list: [{ id: '2' }],
},
});
expect(() => useSpaceStore.getState().setSpace('1')).toThrow(
'can not find space: ',
);
});
it('createSpace', async () => {
const res = await useSpaceStore.getState().createSpace({} as any);
expect(res).toBeUndefined();
expect(useSpaceStore.getState().createSpace({} as any)).rejects.toThrow(
'create error:',
);
});
it('exitSpace', async () => {
const mockExitSpace = vi.mocked(PlaygroundApi.ExitSpaceV2);
mockExitSpace.mockResolvedValueOnce({ code: 0, msg: '' });
const res = await useSpaceStore.getState().exitSpace({} as any);
expect(res).toBeUndefined();
});
it('deleteSpace', async () => {
const mockDeleteSpace = vi.mocked(PlaygroundApi.DeleteSpaceV2);
mockDeleteSpace.mockResolvedValueOnce({ code: 0, msg: '' });
const res = await useSpaceStore.getState().deleteSpace('');
expect(res).toBeUndefined();
});
it('fetchSpaces', async () => {
useSpaceStore.setState({
createSpace: vi.fn(),
});
await useSpaceStore.getState().fetchSpaces();
expect(useSpaceStore.getState().spaces).toEqual({
bot_space_list: [],
has_personal_space: true,
team_space_num: 0,
max_team_space_num: 3,
});
const prePromise = useSpaceStore.getState().fetchSpaces(true);
await useSpaceStore.getState().fetchSpaces();
await prePromise;
const expectedValue = {
bot_space_list: [
{
id: '123',
app_ids: null,
name: 'Personal',
description: 'Personal',
icon_url:
'https://lf16-alice-tos-sign.oceanapi-i18n.com/obj/ocean-cloud-tos-sg/FileBizType.BIZ_BOT_SPACE/personal.png?lk3s=50ccb0c5\u0026x-expires=1707120346\u0026x-signature=vvsdzfbTwD2qIYxXa%2BcjGo1H%2Beg%3D',
space_type: 1,
connectors: [
{
id: '123',
name: 'Cici',
icon: 'FileBizType.BIZ_BOT_ICON/7269764022575842322_1700191555077003149.jpg',
connector_status: 0,
},
],
hide_operation: false,
},
],
has_personal_space: true,
team_space_num: 0,
max_team_space_num: 3,
};
expect(useSpaceStore.getState().spaces).toEqual(expectedValue);
expect(useSpaceStore.getState().createSpace).toHaveBeenCalledTimes(2);
expect(useSpaceStore.getState().fetchSpaces()).rejects.toThrow();
});
});

View File

@@ -0,0 +1,12 @@
{
"operationSettings": [
{
"operationName": "test:cov",
"outputFolderNames": ["coverage"]
},
{
"operationName": "ts-check",
"outputFolderNames": ["./dist"]
}
]
}

View File

@@ -0,0 +1,6 @@
{
"codecov": {
"coverage": 0,
"incrementCoverage": 0
}
}

View File

@@ -0,0 +1,7 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web',
rules: {},
});

View File

@@ -0,0 +1,50 @@
{
"name": "@coze-foundation/space-store-adapter",
"version": "0.0.1",
"description": "基座中的空间store",
"license": "Apache-2.0",
"author": "yuwenbinjie@bytedance.com",
"maintainers": [],
"main": "src/index.ts",
"scripts": {
"build": "exit 0",
"lint": "eslint ./ --cache",
"test": "vitest --run --passWithNoTests",
"test:cov": "npm run test -- --coverage"
},
"dependencies": {
"@coze-arch/bot-api": "workspace:*",
"@coze-arch/bot-error": "workspace:*",
"@coze-arch/bot-flags": "workspace:*",
"@coze-arch/logger": "workspace:*",
"@coze-arch/report-events": "workspace:*",
"@coze-foundation/enterprise-store-adapter": "workspace:*",
"classnames": "^2.3.2",
"immer": "^10.0.3",
"zustand": "^4.4.7"
},
"devDependencies": {
"@coze-arch/bot-typings": "workspace:*",
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/stylelint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@coze-arch/vitest-config": "workspace:*",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react": "^14.1.2",
"@testing-library/react-hooks": "^8.0.1",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"@vitest/coverage-v8": "~3.0.5",
"react": "~18.2.0",
"react-dom": "~18.2.0",
"stylelint": "^15.11.0",
"vite-plugin-svgr": "~3.3.0",
"vitest": "~3.0.5"
},
"peerDependencies": {
"react": ">=18.2.0",
"react-dom": ">=18.2.0"
},
"// deps": "immer@^10.0.3 为脚本自动补齐,请勿改动"
}

View File

@@ -0,0 +1,18 @@
/*
* 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.
*/
vi.stubGlobal('IS_DEV_MODE', false);
vi.mock('zustand');

View File

@@ -0,0 +1,17 @@
/*
* 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.
*/
export { useSpaceStore } from './space';

View File

@@ -0,0 +1,21 @@
/*
* 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.
*/
export enum ReportEventNames {
EmptySpaceList = 'empty_space_List', // 空间列表为空
PollingSpaceList = 'polling_space_list', // 轮训空间列表
}

View File

@@ -0,0 +1,228 @@
/*
* 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.
*/
/* eslint-disable @coze-arch/max-line-per-function */
/* eslint-disable max-lines-per-function */
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { REPORT_EVENTS } from '@coze-arch/report-events';
import { CustomError } from '@coze-arch/bot-error';
import {
type SaveSpaceRet,
type SaveSpaceV2Request,
type TransferSpaceV2Request,
type ExitSpaceV2Request,
type SpaceInfo,
} from '@coze-arch/bot-api/playground_api';
import { type BotSpace, SpaceType } from '@coze-arch/bot-api/developer_api';
import { PlaygroundApi } from '@coze-arch/bot-api';
import { polling, reportSpaceListPollingRes } from './utils';
interface SpaceStoreState {
/** @deprecated try useSpace instead */
space: BotSpace;
spaceList: BotSpace[];
recentlyUsedSpaceList: BotSpace[];
loading: false | Promise<SpaceInfo | undefined>;
inited?: boolean;
createdTeamSpaceNum: number; // 个人创建的团队空间计数
maxTeamSpaceNum: number;
/** @deprecated 使用 spaceList & maxTeamSpaceNum */
spaces: {
bot_space_list: BotSpace[];
has_personal_space: boolean;
team_space_num: number;
max_team_space_num: number;
};
}
interface SpaceStoreAction {
reset: () => void;
/** @deprecated get id from url */
getSpaceId: () => string;
getPersonalSpaceID: () => string | undefined;
checkSpaceID: (spaceID: string) => boolean;
/** @deprecated 通过 id 索引 */
setSpace: (spaceId?: string, isBotDetailIframe?: boolean) => void | never;
createSpace: (
request: SaveSpaceV2Request,
) => Promise<SaveSpaceRet | undefined>;
exitSpace: (request: ExitSpaceV2Request) => Promise<string | undefined>;
deleteSpace: (id: string) => Promise<string | undefined>;
updateSpace: (request: SaveSpaceV2Request) => Promise<{
id?: string;
check_not_pass?: boolean;
}>;
transferSpace: (
request: TransferSpaceV2Request,
) => Promise<string | undefined>;
fetchSpaces: (force?: boolean) => Promise<SpaceInfo | undefined>;
}
const DEFAULT_MAXIMUM_SPACE = 3;
export const defaultState: SpaceStoreState = {
space: {},
spaceList: [],
recentlyUsedSpaceList: [],
loading: false,
maxTeamSpaceNum: DEFAULT_MAXIMUM_SPACE,
createdTeamSpaceNum: 0,
inited: false,
spaces: {
bot_space_list: [],
has_personal_space: true,
team_space_num: 0,
max_team_space_num: DEFAULT_MAXIMUM_SPACE,
},
};
export const useSpaceStore = create<SpaceStoreState & SpaceStoreAction>()(
devtools(
(set, get) => ({
...defaultState,
reset: () => {
set(defaultState, false, 'reset');
},
getSpaceId: () => {
const { id } = get().space;
if (!id) {
throw new CustomError(
REPORT_EVENTS.parmasValidation,
'lack space_id',
);
}
return id;
},
getPersonalSpaceID: () =>
get().spaces.bot_space_list?.find(
space => space.space_type === SpaceType.Personal,
)?.id,
checkSpaceID: spaceID =>
!!get().spaces.bot_space_list?.find(space => space.id === spaceID),
setSpace: id => {
const { space, spaces } = get();
if (id) {
const targetSapce = spaces.bot_space_list.find(s => s.id === id);
if (targetSapce) {
set({ space: targetSapce }, false, 'setSpace');
} else {
throw Error(`can not find space: ${id}`);
}
} else {
set(
{
space: {
...space,
id: '',
},
},
false,
'setSpace',
);
}
},
createSpace: async payload => {
const res = await PlaygroundApi.SaveSpaceV2(payload);
if (res.code === 0) {
return res.data;
} else {
throw Error(`create error: ${res.msg}`);
}
},
exitSpace: _ => Promise.resolve(undefined),
deleteSpace: _ => Promise.resolve(undefined),
updateSpace: _ => Promise.resolve({}),
transferSpace: () => Promise.resolve(undefined),
// eslint-disable-next-line complexity
fetchSpaces: async (force?: boolean) => {
const request = async () => {
const { data } = await PlaygroundApi.GetSpaceListV2({});
return data;
};
const prePromise = get().loading;
const currentPromise = force ? request() : prePromise || request();
if (currentPromise !== prePromise) {
set(
{
loading: currentPromise,
},
false,
'fetchSpaces',
);
} else {
return prePromise;
}
let res = await currentPromise;
if (!res?.has_personal_space) {
await get().createSpace({
name: 'Personal',
description: 'Personal Space',
icon_uri: '',
space_type: SpaceType.Personal,
});
const pollingRes = await polling({
request,
isValid: data => (data?.bot_space_list?.length ?? 0) > 0,
});
reportSpaceListPollingRes(pollingRes);
res = pollingRes.data;
}
const spaceInfo: SpaceStoreState['spaces'] = {
bot_space_list: res?.bot_space_list ?? [],
has_personal_space: res?.has_personal_space ?? true,
team_space_num: res?.team_space_num ?? 0,
max_team_space_num: res?.max_team_space_num ?? DEFAULT_MAXIMUM_SPACE,
};
set(
{
spaceList: spaceInfo.bot_space_list,
recentlyUsedSpaceList: res?.recently_used_space_list ?? [],
createdTeamSpaceNum: spaceInfo.team_space_num,
maxTeamSpaceNum: spaceInfo.max_team_space_num,
loading: false,
inited: true,
spaces: spaceInfo,
},
false,
'fetchSpaces',
);
return res;
},
}),
{
enabled: IS_DEV_MODE,
name: 'botStudio.spaceStore',
},
),
);

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 { reporter } from '@coze-arch/logger';
import { CustomError } from '@coze-arch/bot-error';
import { ReportEventNames } from './const';
const MAX_RETRY = 4;
const INTERVAL = 800;
interface PollingResponse<T = unknown> {
data: T;
isSuccess: boolean;
tryCount: number;
}
export const polling = <T>({
request,
isValid,
maxRetry = MAX_RETRY,
interval = INTERVAL,
}: {
request: () => Promise<T>;
isValid: (data: T) => boolean;
maxRetry?: number;
interval?: number;
}): Promise<PollingResponse<T>> => {
let tryCount = 0;
return new Promise(resolve => {
const go = async () => {
const data = await request();
if (!isValid(data)) {
if (++tryCount < maxRetry) {
setTimeout(go, interval);
} else {
resolve({
data,
isSuccess: false,
tryCount,
});
}
} else {
resolve({
data,
isSuccess: true,
tryCount,
});
}
};
go();
});
};
export const reportSpaceListPollingRes = ({
isSuccess,
tryCount,
}: PollingResponse) => {
reporter.errorEvent(
isSuccess
? {
eventName: ReportEventNames.PollingSpaceList,
error: new CustomError(
ReportEventNames.PollingSpaceList,
tryCount.toString(),
),
}
: {
eventName: ReportEventNames.EmptySpaceList,
error: new CustomError(
ReportEventNames.EmptySpaceList,
'space list is empty',
),
},
);
};

View File

@@ -0,0 +1,17 @@
/*
* 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.
*/
declare const IS_DEV_MODE: boolean;

View File

@@ -0,0 +1,34 @@
import { Meta } from "@storybook/blocks";
<Meta title="Hello world" />
<div className="sb-container">
<div className='sb-section-title'>
# Hello world
Hello world
</div>
</div>
<style>
{`
.sb-container {
margin-bottom: 48px;
}
.sb-section {
width: 100%;
display: flex;
flex-direction: row;
gap: 20px;
}
img {
object-fit: cover;
}
.sb-section-title {
margin-bottom: 32px;
}
`}
</style>

View File

@@ -0,0 +1,48 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"compilerOptions": {
"types": [],
"strictNullChecks": true,
"noImplicitAny": true,
"rootDir": "./src",
"outDir": "./dist",
"tsBuildInfoFile": "./dist/tsconfig.build.tsbuildinfo"
},
"include": ["src"],
"references": [
{
"path": "../../arch/bot-api/tsconfig.build.json"
},
{
"path": "../../arch/bot-error/tsconfig.build.json"
},
{
"path": "../../arch/bot-flags/tsconfig.build.json"
},
{
"path": "../../arch/bot-typings/tsconfig.build.json"
},
{
"path": "../../arch/logger/tsconfig.build.json"
},
{
"path": "../../arch/report-events/tsconfig.build.json"
},
{
"path": "../../../config/eslint-config/tsconfig.build.json"
},
{
"path": "../../../config/stylelint-config/tsconfig.build.json"
},
{
"path": "../../../config/ts-config/tsconfig.build.json"
},
{
"path": "../../../config/vitest-config/tsconfig.build.json"
},
{
"path": "../enterprise-store-adapter/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
],
"exclude": ["**/*"]
}

View File

@@ -0,0 +1,25 @@
{
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"$schema": "https://json.schemastore.org/tsconfig",
"include": [
"__tests__",
"__mocks__",
"stories",
"vitest.config.ts",
"tailwind.config.ts",
"setup-vitest.ts"
],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
],
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"types": ["vitest/globals"],
"strictNullChecks": true,
"noImplicitAny": true
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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 { defineConfig } from '@coze-arch/vitest-config';
export default defineConfig({
dirname: __dirname,
preset: 'web',
test: {
coverage: {
all: true,
exclude: ['src/index.ts'],
},
setupFiles: ['./setup-vitest.ts'],
},
});