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,5 @@
const { defineConfig } = require('@coze-arch/stylelint-config');
module.exports = defineConfig({
extends: [],
});

View File

@@ -0,0 +1,10 @@
# Rspack & React App
应用项目初始化模板,已包含功能:
* react & react router
* slardar sdk
* semi
* less、tailwind
* vitest
## 启动项目
运行`rushx dev`

View File

@@ -0,0 +1,16 @@
{
"operationSettings": [
{
"operationName": "build",
"outputFolderNames": ["output"]
},
{
"operationName": "test:cov",
"outputFolderNames": ["coverage"]
},
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,9 @@
# 环境变量
## 配置
index.ts 文件中配置环境变量,可根据多环境(地区)的环境变量可分别设置相关变量。
# 注意事项
## dts 自动生成约定
- src/typings/env/index.d.ts 由脚本自动更新
- 类型来源env/index.ts 文件中的 envs 变量,请确保新增的环境变量都作为 envs 的一组 key-value

View File

@@ -0,0 +1,39 @@
/*
* 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.
*/
const { NODE_ENV } = process.env;
const IS_DEV_MODE = NODE_ENV === 'development'; // 本地环境
const IS_PRODUCT_MODE = NODE_ENV === 'production'; // 生产环境
const IS_CI = process.env.CI === 'true';
const IS_SCM = !!process.env.BUILD_PATH_SCM;
export const envs = {
IS_DEV_MODE,
IS_PRODUCT_MODE,
IS_CI,
IS_SCM,
};
const emptyVars = Object.entries({
...envs,
}).filter(([key, value]) => value === undefined);
if (emptyVars.length) {
throw Error(`以下环境变量值为空:${emptyVars.join('、')}`);
}

View File

@@ -0,0 +1,129 @@
/*
* 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 {
Project,
SyntaxKind,
PropertyAssignment,
ShorthandPropertyAssignment,
SpreadAssignment,
VariableDeclarationKind,
TypeFormatFlags,
type VariableDeclarationStructure,
type OptionalKind,
} from 'ts-morph';
interface TUpdateDTSParams {
inputFileName: string;
envVarName: string;
outputFileName: string;
}
export const updateDTS = (
{ inputFileName, envVarName, outputFileName }: TUpdateDTSParams = {
inputFileName: 'env/index.ts',
envVarName: 'envs',
outputFileName: 'src/typing/env/index.d.ts',
},
) => {
const start = Date.now();
// 初始化一个 ts-morph 项目
const project = new Project({
compilerOptions: {
incremental: true,
allowJs: false,
skipLibCheck: true,
strictNullChecks: true,
noEmitOnError: true,
},
});
// 添加想要解析的文件
const file = project.addSourceFileAtPath(inputFileName);
// 获取你想要解析的变量
const envs = file.getVariableDeclarationOrThrow(envVarName);
// 获取 envs 变量的初始值
const initializer = envs.getInitializerIfKindOrThrow(
SyntaxKind.ObjectLiteralExpression,
);
// 获取 envs 对象的属性
const properties = initializer.getProperties();
// 创建一个新的文件,用来保存生成的类型定义
const typeDefs = project.createSourceFile(
outputFileName,
`// 基于${inputFileName}自动生成,请勿手动修改`,
{
overwrite: true,
},
);
const declarations: OptionalKind<VariableDeclarationStructure>[] = [];
const addDeclaration = (name: string, type: string) => {
declarations.push({
name,
type,
});
};
// 遍历每一个属性
properties.forEach(property => {
if (
property instanceof PropertyAssignment ||
property instanceof ShorthandPropertyAssignment
) {
addDeclaration(property.getName(), property.getType().getText());
} else if (property instanceof SpreadAssignment) {
const expression = property.getExpression();
const type = expression.getType();
if (type.isObject()) {
// 如果类型是一个对象类型,获取其属性
const spreadProperties = type.getProperties();
// 遍历属性
for (const spreadProperty of spreadProperties) {
const declaration = spreadProperty.getDeclarations()?.[0];
if (declaration) {
addDeclaration(
spreadProperty.getName(),
declaration
.getType()
.getText(
undefined,
TypeFormatFlags.UseSingleQuotesForStringLiteralType,
),
);
}
}
}
}
});
// 保存文件
typeDefs.addVariableStatements(
declarations
.sort((a, b) => (a.name > b.name ? 1 : -1))
.map(d => ({
declarationKind: VariableDeclarationKind.Const,
hasDeclareKeyword: true,
declarations: [d],
})),
);
typeDefs.saveSync();
console.info(`DTS generated in ${Date.now() - start} ms`);
};

View File

@@ -0,0 +1,9 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"compilerOptions": {
"declaration": true,
"baseUrl": "./",
"strictNullChecks": true,
"emitDeclarationOnly": true
}
}

View File

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

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" data-bundler="rspack">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,28 @@
/*
* 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 type { IConfig } from '../../autoinstallers/plugins/node_modules/rush-init-project-plugin';
import SelectTeamPlugin from '../_plugins/SelectTeamPlugin';
import SetDefaultAuthorPlugin from '../_plugins/SetDefaultAuthorPlugin';
const config: IConfig = {
plugins: [new SetDefaultAuthorPlugin(), new SelectTeamPlugin()],
defaultProjectConfiguration: {
tags:['level-4']
}
};
export default config;

View File

@@ -0,0 +1,58 @@
{
"name": "{{ packageName }}",
"version": "0.0.1",
"private": true,
"description": "{{ description }}",
"keywords": [],
"license": "Apache-2.0",
"author": "{{ authorName }}",
"maintainers": [],
"sideEffects": false,
"scripts": {
"build": "NODE_ENV=production rspack build",
"dev": "NODE_ENV=development rspack serve",
"lint": "eslint ./ --cache --quiet",
"test": "vitest --run --passWithNoTests",
"test:cov": "npm run test -- --coverage"
},
"dependencies": {
"@douyinfe/semi-icons": "^2.36.0",
"@douyinfe/semi-ui": "2.61.0",
"immer": "^10.0.3",
"react": "~18.2.0",
"react-dom": "~18.2.0",
"react-error-boundary": "^4.0.9",
"react-router-dom": "^6.11.1",
"zustand": "^4.4.7",
"@coze-arch/logger": "workspace:*",
"@coze-arch/i18n": "workspace:*",
"@coze-arch/bot-api": "workspace:*"
},
"devDependencies": {
"@douyinfe/semi-rspack-plugin": "~2.48.0",
"@edenx/plugin-tailwind": "1.51.0",
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@coze-arch/vitest-config": "workspace:*",
"@coze-arch/stylelint-config": "workspace:*",
"@rspack/cli": "0.4.0",
"@rspack/core": "0.4.0",
"@rspack/plugin-react-refresh": "0.4.0",
"@slardar/web": "~1.12.1",
"@svgr/webpack": "^8.1.0",
"@types/node": "^18",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"@vitest/coverage-v8": "~3.0.5",
"autoprefixer": "^10.4.16",
"file-loader": "^6.2.0",
"less-loader": "~11.1.3",
"postcss": "^8.4.32",
"postcss-loader": "^7.3.3",
"tailwindcss": "~3.3.3",
"ts-morph": "^20.0.0",
"ts-node": "^10.9.1",
"vitest": "~3.0.5"
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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 path from 'path';
import refreshPlugin from '@rspack/plugin-react-refresh';
import rspack from '@rspack/core';
import { type Configuration } from '@rspack/cli';
import { updateDTS } from './env/scripts/index';
import { envs } from './env';
const { IS_DEV_MODE, IS_CI, IS_SCM } = envs;
const CDN_PATH = IS_SCM
? `//${process.env.CDN_INNER_CN}/${process.env.CDN_PATH_PREFIX}`
: '/';
if (IS_DEV_MODE) {
updateDTS();
}
const config: Configuration = {
mode: IS_DEV_MODE ? 'development' : 'production',
context: __dirname,
entry: { main: './src/index.tsx' },
output: { path: 'output', publicPath: CDN_PATH },
target: ['web'],
resolve: {
tsConfigPath: path.resolve(__dirname, 'tsconfig.json'), // https://www.rspack.dev/config/resolve.html#resolvetsconfigpath
},
devServer: {
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.svg$/,
issuer: /\.[jt]sx?$/,
use: [
{ loader: '@svgr/webpack', options: { native: false } },
'file-loader',
],
},
{
test: /\.(png|gif|jpg|jpeg|woff2)$/,
use: ['file-loader'],
},
{
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
},
},
},
],
type: 'css',
},
{
test: /\.module\.css$/i,
type: 'css/module',
},
{
test: /\.less$/,
use: [
{
loader: 'less-loader',
},
],
type: 'css/auto',
},
{
test: /\.(jsx?|tsx?)$/,
use: [
{
loader: 'builtin:swc-loader',
options: {
sourceMap: true,
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: true,
},
transform: {
react: {
runtime: 'automatic',
development: IS_DEV_MODE,
refresh: IS_DEV_MODE,
},
},
},
env: {
targets: [
'chrome >= 87',
'edge >= 88',
'firefox >= 78',
'safari >= 14',
],
},
},
},
],
},
],
},
builtins: {
treeShaking: !IS_DEV_MODE && !IS_CI,
},
plugins: [
new rspack.DefinePlugin({
...envs,
}),
new rspack.ProgressPlugin({}),
new rspack.HtmlRspackPlugin({
template: './index.html',
}),
IS_DEV_MODE ? new refreshPlugin() : null,
IS_DEV_MODE && new rspack.ProgressPlugin(),
].filter(Boolean),
/** module is too large now, we may need better way to tackle this in the future */
stats: IS_DEV_MODE
? false
: IS_CI
? {
all: false,
modules: true,
assets: true,
chunks: true,
warnings: true,
errors: true,
}
: {
modules: false,
all: false,
warnings: false,
errors: true,
timings: true,
},
optimization: {
splitChunks: {
chunks: 'all',
minChunks: 1,
minSize: 20000,
maxAsyncRequests: 30,
maxInitialRequests: 30,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
export default config;

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -ex
# Switch cwd to the project folder
cd $(dirname "$0")
# Import the utilities functions
source ../../scripts/scm_base.sh
# Clean up the build directory
rm -rf output
rm -rf "${ROOT_DIR}"/output
# Prepare
prepare_environment
# Install the dependencies
install_project_deps
build_project
mkdir -p ${ROOT_DIR}/output
cp -r ./output/* ${ROOT_DIR}/output/

View File

@@ -0,0 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.app {
/* */
}

View File

@@ -0,0 +1,54 @@
/*
* 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 { Link, Outlet } from 'react-router-dom';
import { Button, Layout } from '@douyinfe/semi-ui';
import './App.css';
const App = () => {
const { Header, Sider, Content, Footer } = Layout;
const commonStyle = {
height: 64,
lineHeight: '64px',
background: 'var(--semi-color-fill-0)',
};
return (
<Layout className="h-screen">
<Header style={commonStyle}>Header</Header>
<Layout>
<Sider
style=\{{ width: '120px', background: 'var(--semi-color-fill-2)' }}
>
<Link to="page1">
<Button>page1</Button>
</Link>
<br />
<Link to="page2">
<Button>page2</Button>
</Link>
</Sider>
<Content style=\{{ height: 'max-content', lineHeight: '300px' }}>
<Outlet />
</Content>
</Layout>
<Footer style={commonStyle}>Footer</Footer>
</Layout>
);
};
export default App;

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,33 @@
/*
* 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 { RouterProvider } from 'react-router-dom';
import { createRoot } from 'react-dom/client';
import browserClient from '@slardar/web'; // 默认引入的是CN地区的
import { reporter } from '@coze-arch/logger';
import { router } from '@/router';
browserClient('init', {
// TODO: your slardar bid
bid: '',
});
browserClient('start');
reporter.init(browserClient)
const root = createRoot(document.getElementById('root'));
root.render(<RouterProvider router={router} />);

View File

@@ -0,0 +1,4 @@
.page1 {
display: flex;
justify-content: center;
}

View File

@@ -0,0 +1,22 @@
/*
* 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 React from 'react';
import './index.less';
export function Page1() {
return <div className="page1">page1</div>;
}

View File

@@ -0,0 +1,33 @@
/*
* 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 React from 'react';
import { Button } from '@douyinfe/semi-ui';
import { usePage2Store } from '@/pages/page2/store';
export function Page2() {
const { count, updateCount } = usePage2Store();
return (
<div className="flex justify-center flex-col items-center">
<div>page2 with store</div>
<div>
<Button onClick={() => updateCount()}>count {count}</Button>
</div>
</div>
);
}

View File

@@ -0,0 +1,42 @@
/*
* 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 { immer } from 'zustand/middleware/immer';
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
interface Page1State {
count: number;
updateCount: () => void;
}
// only for page2
export const usePage2Store = create<Page1State>()(
devtools(
immer(set => ({
count: 1,
updateCount: () => {
set(it => {
it.count++;
});
},
})),
{
enabled: IS_DEV_MODE,
name: 'api-builder/page2',
},
),
);

View File

@@ -0,0 +1,39 @@
/*
* 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 { createBrowserRouter } from 'react-router-dom';
import { Page2 } from '@/pages/page2';
import { Page1 } from '@/pages/page1';
import App from '@/App';
export const router: ReturnType<typeof createBrowserRouter> =
createBrowserRouter([
{
path: '/',
element: <App />,
children: [
{
path: 'page1',
element: <Page1 />,
},
{
path: 'page2',
element: <Page2 />,
},
],
},
]);

View File

@@ -0,0 +1,35 @@
/*
* 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 } from 'zustand/middleware';
import { create } from 'zustand';
import {
type UserInfoSlice,
createUserInfoSlice,
} from '@/store/userinfo-slice';
export const useStore = create<UserInfoSlice>()(
devtools(
(...a) => ({
...createUserInfoSlice(...a),
}),
{
enabled: IS_DEV_MODE,
name: 'api-builder/app',
},
),
);

View File

@@ -0,0 +1,34 @@
/*
* 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 { type StateCreator } from 'zustand';
export interface UserInfoSlice {
userInfo: string;
iniUserInfo: () => void;
}
export const createUserInfoSlice: StateCreator<
UserInfoSlice,
[],
[],
UserInfoSlice
> = set => ({
userInfo: '',
iniUserInfo: () => {
// TODO: 用户信息相关方法获取
},
});

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.
*/
// 基于env/index.ts自动生成请勿手动修改
declare const IS_CI: boolean;
declare const IS_DEV_MODE: boolean;
declare const IS_PRODUCT_MODE: boolean;
declare const IS_SCM: boolean;

View File

@@ -0,0 +1,19 @@
/*
* 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 module '*.svg';
declare module '*.png';
declare module '*.less';

View File

@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,tsx}'],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -0,0 +1,15 @@
{
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"jsx": "react-jsx",
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"target": "ES2020",
"moduleResolution": "bundler"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

View File

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

View File

@@ -0,0 +1,20 @@
{
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"jsx": "react-jsx",
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"target": "ES2020",
"moduleResolution": "bundler"
},
"include": ["__tests__", "vitest.config.ts"],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,22 @@
/*
* 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',
});