chore: replace all cn comments of fe to en version by volc api (#320)

This commit is contained in:
tecvan 2025-07-31 10:32:15 +08:00 committed by GitHub
parent 716ec0cba8
commit 71f6245a01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2960 changed files with 15545 additions and 15545 deletions

View File

@ -83,7 +83,7 @@ const mergedConfig = defineConfig({
source: {
define: {
'process.env.IS_REACT18': JSON.stringify(true),
// arcosite editor sdk 内部使用
// Arcosite editor sdk internal use
'process.env.ARCOSITE_SDK_REGION': JSON.stringify(
GLOBAL_ENVS.IS_OVERSEA ? 'VA' : 'CN',
),
@ -99,7 +99,7 @@ const mergedConfig = defineConfig({
include: [
path.resolve(__dirname, '../../packages'),
path.resolve(__dirname, '../../infra/flags-devtool'),
// 以下几个包包含未降级的 ES 2022 语法private methods需要参与打包
// The following packages contain undegraded ES 2022 syntax (private methods) that need to be packaged
/\/node_modules\/(marked|@dagrejs|@tanstack)\//,
],
alias: {

View File

@ -31,15 +31,15 @@ const initFlags = () => {
};
const main = () => {
// 初始化功能开关的值
// Initialize the value of the function switch
initFlags();
// 初始化i18n
// Initialize i18n
initI18nInstance({
lng: (localStorage.getItem('i18next') ?? (IS_OVERSEA ? 'en' : 'zh-CN')) as
| 'en'
| 'zh-CN',
});
// 动态导入mdbox 样式
// Import mdbox styles dynamically
dynamicImportMdBoxStyle();
const $root = document.getElementById('root');

View File

@ -16,128 +16,128 @@
import { lazy } from 'react';
// 登录页面
// login page
export const LoginPage = lazy(() =>
import('@coze-foundation/account-ui-adapter').then(res => ({
default: res.LoginPage,
})),
);
// 文档页面
// documentation page
export const Redirect = lazy(() => import('../pages/redirect'));
// 工作空间侧边栏组件
// Workspace Sidebar Component
export const spaceSubMenu = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.WorkspaceSubMenu,
})),
);
// 工作空间布局组件
// Workspace Layout Component
export const SpaceLayout = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.SpaceLayout,
})),
);
// 某个具体的工作空间布局组件
// A specific workspace layout component
export const SpaceIdLayout = lazy(() =>
import('@coze-foundation/space-ui-base').then(exps => ({
default: exps.SpaceIdLayout,
})),
);
// 项目开发页面
// project development page
export const Develop = lazy(() => import('../pages/develop'));
// 资源库页面
// resource library page
export const Library = lazy(() => import('../pages/library'));
// Agent IDE布局组件
// Agent IDE Layout Component
export const AgentIDELayout = lazy(
() => import('@coze-agent-ide/layout-adapter'),
);
// Agent IDE页面
// Agent IDE page
export const AgentIDE = lazy(() =>
import('@coze-agent-ide/entry-adapter').then(res => ({
default: res.BotEditor,
})),
);
// Agent IDE发布页面
// Agent IDE Release Page
export const AgentPublishPage = lazy(() =>
import('@coze-agent-ide/agent-publish').then(exps => ({
default: exps.AgentPublishPage,
})),
);
// Project IDE页面
// Project IDE Page
export const ProjectIDE = lazy(() =>
import('@coze-project-ide/main').then(exps => ({
default: exps.IDELayout,
})),
);
// Project IDE发布页面
// Project IDE Release Page
export const ProjectIDEPublish = lazy(() =>
import('@coze-studio/project-publish').then(exps => ({
default: exps.ProjectPublish,
})),
);
// 知识库预览页面
// Knowledge Base Preview Page
export const KnowledgePreview = lazy(() =>
import('@coze-studio/workspace-base/knowledge-preview').then(exps => ({
default: exps.KnowledgePreviewPage,
})),
);
// 知识库上传页面
// Knowledge base upload page
export const KnowledgeUpload = lazy(() =>
import('@coze-studio/workspace-base/knowledge-upload').then(exps => ({
default: exps.KnowledgeUploadPage,
})),
);
// 数据库资源页面
// database resource page
export const DatabaseDetail = lazy(() =>
import('@coze-studio/workspace-base').then(exps => ({
default: exps.DatabaseDetailPage,
})),
);
// 工作流页面
// workflow page
export const WorkflowPage = lazy(() =>
import('@coze-workflow/playground-adapter').then(res => ({
default: res.WorkflowPage,
})),
);
// 插件资源页面布局组件
// plugin resource page layout component
export const PluginLayout = lazy(() => import('../pages/plugin/layout'));
// 插件资源页面
// plugin resource page
export const PluginPage = lazy(() => import('../pages/plugin/page'));
// 插件工具页面
// plugin tool page
export const PluginToolPage = lazy(() => import('../pages/plugin/tool/page'));
// 探索体验页面二级导航组件
// Explore the experience page secondary navigation component
export const exploreSubMenu = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.ExploreSubMenu,
})),
);
// 模版页面
// template page
export const ExploreTemplatePage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.TemplatePage,
})),
);
// 插件商店页面
// plugin store page
export const ExplorePluginPage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.PluginPage,

View File

@ -48,7 +48,7 @@ import {
export const router: ReturnType<typeof createBrowserRouter> =
createBrowserRouter([
// 文档路由
// Document routing
{
path: '/open/docs/*',
Component: Redirect,
@ -73,7 +73,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
requireAuth: false,
}),
},
// 主应用路由
// main application route
{
path: '/',
Component: Layout,
@ -83,7 +83,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
index: true,
element: <Navigate to="/space" replace />,
},
// 登录页路由
// login page routing
{
path: 'sign',
Component: LoginPage,
@ -94,7 +94,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 工作空间路由
// Workspace Routing
{
path: 'space',
Component: SpaceLayout,
@ -114,7 +114,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
element: <Navigate to="develop" replace />,
},
// 项目开发
// Project Development
{
path: 'develop',
Component: Develop,
@ -171,7 +171,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 资源库
// resource library
{
path: 'library',
Component: Library,
@ -180,7 +180,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 知识库资源
// Knowledge Base Resources
{
path: 'knowledge',
children: [
@ -198,7 +198,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 数据库资源
// database resources
{
path: 'database',
children: [
@ -213,7 +213,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 插件资源
// plugin resources
{
path: 'plugin/:plugin_id',
Component: PluginLayout,
@ -238,7 +238,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
],
},
// 工作流路由
// workflow routing
{
path: 'work_flow',
Component: WorkflowPage,
@ -248,7 +248,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
}),
},
// 探索
// explore
{
path: 'explore',
Component: null,
@ -263,7 +263,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
index: true,
element: <Navigate to="plugin" replace />,
},
// 插件商店
// plugin store
{
path: 'plugin',
element: <ExplorePluginPage />,
@ -271,7 +271,7 @@ export const router: ReturnType<typeof createBrowserRouter> =
type: 'plugin',
}),
},
// 模版
// template
{
path: 'template',
element: <ExploreTemplatePage />,

View File

@ -27,7 +27,7 @@ console.log(`Got ${contents.length} contents for tailwind`);
export default {
content: contents,
// safelist的内容可以允许动态生成tailwind className
// Safelist content can allow dynamic tailwind className
safelist: [
{
pattern: /(gap-|grid-).+/,
@ -47,7 +47,7 @@ export default {
},
},
corePlugins: {
preflight: false, // 关闭@tailwind base默认样式避免对现有样式影响
preflight: false, // Turn off @tailwind base default styles to avoid affecting existing styles
},
// eslint-disable-next-line @typescript-eslint/no-require-imports
plugins: [require('@coze-arch/tailwind-config/coze')],

View File

@ -5,7 +5,7 @@ module.exports = [
...require('./eslint.config.base.js'),
{
plugins: {
// TODO: 需要根据不同类型配置plugin需要阅读源码确认是否影响性能
// TODO: Need to configure plugins according to different types? You need to read the source code to confirm whether it affects performance
'react-hooks': require('eslint-plugin-react-hooks'),
react: require('eslint-plugin-react'),
risxss: require('eslint-plugin-risxss'),

View File

@ -28,7 +28,7 @@ const readBlockList = () =>
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
// NOTE: 不能和下一项配置合并
// NOTE: Cannot be merged with the next configuration
{
ignores: [
'**/*.d.ts',
@ -68,7 +68,7 @@ module.exports = [
...require('@coze-arch/eslint-plugin').configs.recommended,
require('@coze-arch/eslint-plugin/zustand').configs.recommended,
{
files: ['**/*.?(m|c)?(j|t)s?(x)'], // 排除规则对package.json生效
files: ['**/*.?(m|c)?(j|t)s?(x)'], // Exclusion rules take effect for package.json
plugins: {
prettier: require('eslint-plugin-prettier'),
'@babel': require('@babel/eslint-plugin'),

View File

@ -5,7 +5,7 @@ module.exports = [
{
files: ['**/*.?(m|c)?(j|t)s?(x)'],
settings: {
// TODO: 全局保留一份配置
// TODO: Keep a configuration globally
'import/resolver': {
node: {
moduleDirectory: ['node_modules', 'src'],
@ -72,8 +72,8 @@ module.exports = [
},
},
rules: {
// TODO: 目前由于 edenx 会动态生成一些插件模块,因此启动会报错
// 后续需要修复问题,启动下述规则
// TODO: At present, because edenx will dynamically generate some plug-in modules, an error will be reported when starting.
// You need to fix the problem later, and start the following rules.
// "import/no-unresolved": "error"
},
},

View File

@ -59,9 +59,9 @@ module.exports = [
{
vars: 'all',
args: 'none', // function arguments should not force to match this rule.
argsIgnorePattern: '^_', // 规范允许下划线
ignoreRestSiblings: true, //使用rest语法如 `var { foo, ...rest } = data`) 忽略foo。
destructuredArrayIgnorePattern: '^_', //结构数组允许使用_
argsIgnorePattern: '^_', // Specifications allow underlining
ignoreRestSiblings: true, //Use rest syntax (such as'var {foo,... rest} = data ') to ignore foo.
destructuredArrayIgnorePattern: '^_', //Structural arrays allow _
caughtErrors: 'none',
// "caughtErrorsIgnorePattern": "^e$"
},
@ -314,7 +314,7 @@ module.exports = [
},
},
// TODO: 之前overides的内容后需可考虑直接合入上面标准配置
// TODO: The content of overides before can be considered to be directly integrated into the above standard configuration later
{
files: ['**/*.?(m|c)ts?(x)'],
rules: {
@ -324,8 +324,8 @@ module.exports = [
fixStyle: 'inline-type-imports',
},
],
// 这些规则都是从 packages/config/.eslintrc.react.js 复制迁移过来
// 后续在做调整
// These rules are copied and migrated from packages/config/.eslintrc.react.js
// Adjustments are being made later.
'@typescript-eslint/no-redundant-type-constituents': 0,
'@typescript-eslint/no-throw-literal': 'off',
'@typescript-eslint/no-unnecessary-condition': 0,
@ -335,14 +335,14 @@ module.exports = [
'@typescript-eslint/explicit-function-return-type': 'off',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
// TODO: 后续开启
// TODO: Follow-up opening
// 'import/no-cycle': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 0,
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 0,
'@typescript-eslint/no-implied-eval': 0, // warning
// TODO: 打开下面这些配置
// TODO: Open the following configurations
// fix: https://stackoverflow.com/questions/63961803/eslint-says-all-enums-in-typescript-app-are-already-declared-in-the-upper-scope
// 'no-shadow': 'off',
// '@typescript-eslint/no-shadow': ['error'],
@ -364,7 +364,7 @@ module.exports = [
// },
// ],
// complexity: ['error', { max: 15 }],
// 后面统一使用CustomError后 再开启
// After using CustomError uniformly later, open it again.
'@coze-arch/no-new-error': 'off',
},
},

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
BASE_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# 某些系统可能没有 realpath 命令,
# Some systems may not have the realpath command.
if ! command -v realpath &>/dev/null; then
echo "未找到 realpath 命令"
echo "请执行以下命令安装必要依赖"

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
BASE_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# 某些系统可能没有 realpath 命令,
# Some systems may not have the realpath command.
if ! command -v realpath &>/dev/null; then
echo "未找到 realpath 命令"
echo "请执行以下命令安装必要依赖"

View File

@ -2,9 +2,9 @@ require('sucrase/register/ts');
const { defineConfig } = require('./define-config');
// node@16 没有 structuredClone 方法导致报错:
// node@16 no structuredClone method causes an error:
// ReferenceError: Error while loading rule '@typescript-eslint/naming-convention': structuredClone is not defined
// 此处做个简单 polyfill
// Make a simple polyfill here
if (typeof structuredClone === 'undefined') {
global.structuredClone = obj => JSON.parse(JSON.stringify(obj));
}

View File

@ -28,7 +28,7 @@ import { SemiRspackPlugin } from '@douyinfe/semi-rspack-plugin';
const getDefine = () => {
const define = {};
Object.keys(GLOBAL_ENVS).forEach(key => {
// 在rspack的define中字符串需要前后拼接上双引号才能在代码中作为字符串使用。
// In the definition of rspack, strings need to be enclosed in double quotes before they can be used as strings in code.
if (typeof GLOBAL_ENVS[key] === 'string') {
define[key] = `"${GLOBAL_ENVS[key]}"`;
} else {
@ -115,7 +115,7 @@ export const defineConfig = (options: Partial<RsbuildConfig>) => {
),
},
include: [
// 以下几个包包含未降级的 ES 2022 语法private methods需要参与打包
// The following packages contain undegraded ES 2022 syntax (private methods) that need to be packaged
/\/node_modules\/(marked|@dagrejs|@tanstack)\//,
],
},

View File

@ -6,9 +6,9 @@ module.exports = {
],
plugins: ['./plugins/plugin-disallow-nesting-level-one-global.js'],
rules: {
// 变量命名规则,适应仓库内的代码风格
// Variable naming rules to adapt to the code style in the warehouse
'custom-property-pattern': '^([A-Za-z0-9]*)([-_]+[A-Za-z0-9]+)*$',
// 对于less函数判断有问题
// There is a problem with judging the less function
'less/no-duplicate-variables': null,
'media-feature-range-notation': null,
'max-nesting-depth': [

View File

@ -5,7 +5,7 @@ const plugin = require('tailwindcss/plugin');
const lightModeVariables = require('./light');
const darkModeVariables = require('./dark');
// 用于生成 CSS 变量的帮助函数
// Helper functions for generating CSS variables
function generateCssVariables(variables, theme) {
return Object.entries(variables).reduce((acc, [key, value]) => {
acc[`--${key}`] = theme ? theme(value) : value;
@ -13,7 +13,7 @@ function generateCssVariables(variables, theme) {
}, {});
}
// 样式语义化
// style semantics
function generateSemanticVariables(semantics, theme, property) {
return Object.entries(semantics).map(([key, value]) => ({
[`.${key}`]: {

View File

@ -1,4 +1,4 @@
// 暗色模式的 CSS 变量
// CSS Variables for Dark Mode
const darkModeVariables = {
background: '2, 8, 23',
foreground: '249, 249, 249',

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
// 消费者和生产者公共的 tailwind 配置和工具函数
// Common tailwind configurations and tool functions for consumers and producers
export function designTokenToTailwindConfig(
tokenJson: Record<string, unknown>,
@ -103,6 +103,6 @@ function borderRadiusTransformer(borderRadiusObj: Record<string, string>) {
return res;
}
// 获取其他packages并且拼接上 /src/**/*.{ts,tsx}
// Get other packages and splice /src /**/*.{ ts, tsx}
export { getTailwindContents } from './tailwind-contents';

View File

@ -1,4 +1,4 @@
// 浅色模式的 CSS 变量
// CSS Variables for Light Mode
const lightModeVariables = {
background: '255, 255, 255',
foreground: '28, 28, 35',
@ -27,7 +27,7 @@ const lightModeVariables = {
'coze-fg-3': '15, 21, 40',
'coze-fg-2': '32, 41, 69',
'coze-fg-1': '55, 67, 106',
// TODO: 需要删除bg9
// TODO: need to remove bg9
'coze-bg-9': '6, 7, 9',
'coze-bg-8': '68, 83, 130',
'coze-bg-7': '75, 90, 140',
@ -151,7 +151,7 @@ const lightModeVariables = {
'coze-3': '3px',
'coze-2': '2px',
'coze-1': '1px',
// TODO: rspress编译不出来,需要通过一些工具处理,目前没有用到,暂时注释处理
// TODO: rspress cannot be compiled, and it needs to be processed by some tools. It is not used at present. Temporary comment processing
// 'coze-0.5': '0.5px',
'coze-0-5': '0.5px',
@ -174,7 +174,7 @@ const lightModeVariables = {
'coze-bg-6-alpha': '0.13',
'coze-bg-7-alpha': '0.19',
'coze-bg-8-alpha': '0.25',
// TODO: 需要删除bg9
// TODO: need to remove bg9
'coze-bg-9-alpha': '0.16',
'coze-stroke-5-alpha': '0.13',
'coze-stroke-6-alpha': '0.25',

View File

@ -46,7 +46,7 @@ export const getTailwindContents = (projectRoot: string) => {
.map(location => path.resolve(location, 'src/**/*.{ts,tsx}')),
);
// 兼容 coze-design 内部 tailwind 样式
// Compatible with coze-design internal tailwind style
contents.push('./node_modules/@coze-arch/coze-design/**/*.{js,jsx}');
return contents;

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
BASE_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# 某些系统可能没有 realpath 命令,
# Some systems may not have the realpath command.
if ! command -v realpath &>/dev/null; then
echo "未找到 realpath 命令"
echo "请执行以下命令安装必要依赖"

View File

@ -16,7 +16,7 @@
"moduleResolution": "node",
"module": "CommonJS",
"noFallthroughCasesInSwitch": true,
// bot
// This general feedback will make the code verbose, tentatively follow the original bot's settings, close
"noImplicitReturns": false,
"removeComments": false,
"resolveJsonModule": true,

View File

@ -46,7 +46,7 @@ const calBasePreset = (preset: string) => {
export interface OtherConfig {
/**
* semi的package.json导出的配置问题
* Used to fix the configuration issue of semi's package.json export
*/
fixSemi: boolean;
}

View File

@ -20,7 +20,7 @@ import tsconfigPaths from 'vite-tsconfig-paths';
export const defaultVitestConfig: UserConfig = {
plugins: [tsconfigPaths()],
resolve: {
// 优先识别 main如果没有配置 main则识别 module
// Priority to identify main, if main is not configured, identify the module
mainFields: ['main', 'module', 'exports'],
},
server: {
@ -38,14 +38,14 @@ export const defaultVitestConfig: UserConfig = {
},
},
sequence: {
// vitest 2.0之后,所有钩子默认串行运行
// After vitest 2.0, all hooks run serially by default
hooks: 'parallel',
},
globals: true,
mockReset: false,
silent: process.env.CI === 'true',
coverage: {
// 逐步对各包开启
// Gradually open each package
all: false,
include: ['src/**/*.ts', 'src/**/*.tsx'],
exclude: coverageConfigDefaults.exclude,

View File

@ -1,16 +1,16 @@
[
// 使 @vitest/coverage-v8
// Can be replaced by @vitest/coverage-v8
["@vitest/coverage-c8", null, "请使用 @vitest/coverage-v8"],
"husky",
"lint-staged",
"jest",
["jsdom", null, "请使用 happy-dom 代替"],
// TODO: @tanjizhen
// TODO: Open @tanjizhen after waiting for full repair
// "@oceanos/logger",
["inquirer", null, "请使用 @inquirer/prompts 代替"],
["pdfjs-dist", null, "请使用 @coze-arch/pdfjs-shadow 代替"],
// todo: should turn on this
// ["valtio", null, "请使用 zustand"],
// ["jotai", null, "请使用 zustand"]
// ["Valtio", null, "Please use zustand"],
// ["Jotai", null, "Please use zustand"]
["@flow-web/md-box", null, "请使用 @coze-arch/bot-md-box-adapter 代替"]
]

View File

@ -48,7 +48,7 @@ export const flowPreset = {
'@coze-arch/tsx-no-leaked-render': 'warn',
'@coze-arch/no-pkg-dir-import': 'error',
'@coze-arch/no-duplicated-deps': 'error',
// 不允许超过 4 层的相对应用
// Relative applications with more than 4 layers are not allowed
'@coze-arch/no-deep-relative-import': [
'error',
{
@ -56,7 +56,7 @@ export const flowPreset = {
},
],
'@coze-arch/package-require-author': 'error',
// 函数代码行不要超过 150
// Function code lines should not exceed 150.
'@coze-arch/max-line-per-function': [
'error',
{
@ -73,11 +73,11 @@ export const flowPreset = {
files: ['package.json'],
processor: '@coze-arch/json-processor',
rules: {
// TODO: 需要重构为直接解析json否则全局规则都会对processor处理后的文件`package.js`生效.
// TODO: It needs to be refactored to parse json directly, otherwise the global rules will take effect on the file'package.js' processed by the processor.
//https://github.com/eslint/json
'@coze-arch/package-require-author': 'error',
'@coze-arch/package-disallow-deps': 'error',
// 关闭prettier规则因为该规则lint package.js存在bug
// Close the prettier rule because there is a bug in the rule lint package.js
'prettier/prettier': 'off',
},
},

View File

@ -36,7 +36,7 @@ const getStaticStringValue = node => {
*
* @param node
* @returns
*
* Why is this judgment necessary for a function such as
* ```
* var obj1 = {
* set
@ -46,9 +46,9 @@ const getStaticStringValue = node => {
* }
* }
*```
* 35.
* If you don't use the following judgment, the function judgment will get 3, which should actually be 5. Similarly, there are
* ```
* //如果不采用下面这个判断函数判断将得到3实际应该为8
* //If the following judgment is not used, the function judgment will get 3, which should actually be 8ing judgment, the function judgment will get 3, which should actually be 8.
* class A {
static
[
@ -85,14 +85,14 @@ const isEmbedded = node => {
*
* @param node
* @returns function name
* Q node.id.value获取函数名称 ?
* A
* Q: Why not get the function name directly with node.id?
* A: This method is fine for traditional function writing, but for
* const tips = {
* fun: () => {}
* };
*
* or
* const fun2 = () => {}
* null
* The name of the function written in the following way is null, so it is obtained in the following way.
*
*/
@ -192,7 +192,7 @@ const getStaticPropertyName = node => {
case 'VariableDeclarator':
prop = node.id;
break;
//TODO CallExpression 场景较为复杂,目前应该没有完全覆盖
//TODO: The CallExpression scenario is more complex and should not be fully covered at present
case 'CallExpression':
prop = node.callee;
break;
@ -240,7 +240,7 @@ export const maxLinePerFunctionRule: Rule.RuleModule = {
function checkFunctionLength(funcNode) {
const node = isEmbedded(funcNode) ? funcNode.parent : funcNode;
// 针对函数声明,函数表达式,箭头函数,函数定义四种类型
// Four types of function declarations, function expressions, arrow functions, and function definitions
if (
node.type === 'FunctionDeclaration' ||
node.type === 'FunctionExpression' ||

View File

@ -40,7 +40,7 @@ export const noDuplicatedDepsRule: Rule.RuleModule = {
if (!properties) {
return;
}
// 对比 dependencies 与 devDependencies 之间是否存在重复依赖
// Compare dependencies with devDependencies for duplicate dependencies
const dependencies = properties.find(
p => p.key.value === 'dependencies',
);

View File

@ -40,7 +40,7 @@ export const noPkgDirImport: Rule.RuleModule = {
const modulePath = resolve(importPath, context);
if (!modulePath) {
// 解析不到的情况,暂不处理
// If it cannot be resolved, it will not be dealt with for the time being.
return;
}
@ -56,15 +56,15 @@ export const noPkgDirImport: Rule.RuleModule = {
return;
}
// 本地link会解析到node_modules目录需要拿到pkg name再次解析。
// The local link will resolve to the node_modules directory, and you need to get the pkg name to resolve it again.
const moduleRealPath = resolve(pkg.name, context);
if (
// 包名称就是引用路径
// The package name is the reference path
pkg.name === importPath ||
// 解析到其他包,如@type
// Parse to other packages, such as @type
!importPath.startsWith(pkg.name) ||
// 解析到自己包的文件
// Parse to the file of your own package
currentPkgPath === importPkgPath ||
!moduleRealPath ||
moduleRealPath.includes('node_modules')

View File

@ -32,7 +32,7 @@ vi.mock('eslint-module-utils/readPkgUp', () => ({
const validCases = [
{
code: 'import "xxx"',
modulePath: undefined, // modulePath 为 空
modulePath: undefined, // modulePath is empty
moduleRealPath: undefined,
importPkgPath: 'path/to/import/pkg',
currentPkgPath: 'path/to/current/pkg',
@ -48,7 +48,7 @@ const validCases = [
importPkgPath: 'path/to/import/pkg',
currentPkgPath: 'path/to/current/pkg',
pkg: {
name: 'some/pkg', // 包名称与引用路径相同
name: 'some/pkg', // The package name is the same as the reference path
exports: {},
},
},
@ -59,7 +59,7 @@ const validCases = [
importPkgPath: 'path/to/import/pkg',
currentPkgPath: 'path/to/current/pkg',
pkg: {
name: undefined, // 解析到不规范配置的package.json
name: undefined, // Parse to the non-canonical package.json
},
},
{
@ -69,7 +69,7 @@ const validCases = [
importPkgPath: 'path/to/import/pkg',
currentPkgPath: 'path/to/current/pkg',
pkg: {
name: '@types/pkg', // 解析到类型包
name: '@types/pkg', // Parse to type package
exports: {},
},
},
@ -77,7 +77,7 @@ const validCases = [
code: "import pkg from 'pkg';",
modulePath: 'path/to/module',
moduleRealPath: 'path/to/module',
importPkgPath: 'path/to/same/pkg', // 相同路径
importPkgPath: 'path/to/same/pkg', // same path
currentPkgPath: 'path/to/same/pkg',
pkg: {
name: '@types/pkg',
@ -98,7 +98,7 @@ const validCases = [
{
code: "import pkg from 'pkg';",
modulePath: 'path/to/module',
moduleRealPath: 'path/to/node_modules/pkg', // 解析到node_modules
moduleRealPath: 'path/to/node_modules/pkg', // Parse to node_modules
importPkgPath: 'path/to/import/pkg',
currentPkgPath: 'path/to/current/pkg',
pkg: {
@ -134,7 +134,7 @@ const validCases = [
if (!c.modulePath) {
return {
code: c.code,
// TODO: 避免eslint duplication检测。可能需要改为其他方式
// TODO: Avoid eslint duplication. It may need to be changed to another way
settings: c,
};
}
@ -167,7 +167,7 @@ const invalidCases = [
currentPkgPath: 'path/to/current/pkg',
pkg: {
name: 'pkg',
exports: undefined, // 为空
exports: undefined, // empty
},
messageId: 'noExportsCfg',
},

View File

@ -56,7 +56,7 @@ export const disallowDepRule: Rule.RuleModule = {
return;
}
const [, blockVersion, tips] = definition;
// 没有提供 version 参数,判定为不允许所有版本号
// No version parameter is provided, and it is determined that all version numbers are not allowed
if (typeof blockVersion !== 'string' || blockVersion.length <= 0) {
context.report({
node,

View File

@ -20,12 +20,12 @@ import reactPlugin from 'eslint-plugin-react';
const originRule = reactPlugin.rules['jsx-no-leaked-render'];
// 扩展react/jsx-no-leaked-render。增加判断 「&&」 表达式左边为 boolean 、 null 、 undefined TS类型则不报错。
// Expand the react/jsx-no-leaked-render. If the left side of the "& &" expression is boolean, null, undefined TS type, no error will be reported.
export const tsxNoLeakedRender = ruleComposer.filterReports(
originRule,
problem => {
const { parent } = problem.node;
// 如果表达式是用于jsx属性则不需要修复。 如 <Comp prop={ { foo: 1 } && obj } />
// If the expression is used for jsx properties, it does not need to be fixed. Such as < Comp prop = {{foo: 1} & & obj}/>
if (
parent?.type === AST_NODE_TYPES.JSXExpressionContainer &&
parent?.parent?.type === AST_NODE_TYPES.JSXAttribute

View File

@ -25,7 +25,7 @@ ruleTester.run('prefer-shallow', preferShallow, {
'new Foo()',
'useShallowedFooStore()',
'useFooStore((s) => s.value)',
'useFooStore(selector)', // 暂时豁免
'useFooStore(selector)', // Temporary exemption
'useShallowFooStore(() => ({}))',
'useFooStore(useShallow(() => ({})))',
'useFooStore(useShallow(() => ([])))',

View File

@ -32,8 +32,8 @@ struct UserDeleteDataMap {
We
*/
enum AvatarMetaType {
UNKNOWN = 0, // 没有数据, 错误数据或者系统错误降级
RANDOM = 1, // 在修改 or 创建时,用户未指定 name 或者选中推荐的文字时,程序随机选择的头像
UNKNOWN = 0, // No data, incorrect data, or system error downgrade
RANDOM = 1, // When modifying or creating, the user does not specify a name or select the recommended text, the program randomly selects the avatar
}
`;

View File

@ -46,8 +46,8 @@ enum Gender {
}
// const map<Gender, string> genderMap = {
// Gender.Male: '男性',
// Gender.Female: '女性',
// Gender. Male: 'Male',
// Gender. Female: 'Female',
// }
union FuncRequest {

View File

@ -686,7 +686,7 @@ function convertFieldDefinition(
if (!isProto3) {
requiredness = optional ? 'optional' : 'required';
} else if (rule === 'required') {
// TODO: 处理 optional 的情况,需要修改 proto-parser
// TODO: Handle optional cases, need to modify proto-parser
requiredness = 'required';
}

View File

@ -25,7 +25,7 @@ function requiredWithoutCache(src, onError?) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { Module } = require('module');
try {
// disable 了 require 的缓存,这样可以改变了 mock 数据后,无需重启服务。
// Disable the required cache so that you can change the mock data without restarting the service.
const originCache = Module._cache;
Module._cache = {};
// eslint-disable-next-line security/detect-non-literal-require, @typescript-eslint/no-require-imports

View File

@ -186,7 +186,7 @@ export class FilterTypesPlugin {
} else if (isIdentifier(fieldType)) {
const statement = getStatementById(fieldType, current);
if (isEnumDefinition(statement)) {
// 强制转位 number
// Forced indexing number
// @ts-expect-error fixme late
fieldType.type = SyntaxType.I32Keyword;
let namespace = current.unifyNamespace;

View File

@ -55,15 +55,15 @@ export class MockPlugin implements IPlugin {
if (context) {
const { fieldDefinition } = context;
const fieldName = fieldDefinition.name.value;
// 各类 ID
// various types of ID
if (fieldName.toLocaleUpperCase().endsWith('ID')) {
value = String(faker.number.int());
}
// email 处理
// Email processing
if (fieldName.includes('Email')) {
value = `${faker.person.lastName()}@foo.com`;
}
// 直接映射值
// direct mapping value
value = StrMapper[fieldName] || value;
}
ctx.output = t.stringLiteral(value);
@ -76,20 +76,20 @@ export class MockPlugin implements IPlugin {
const { fieldDefinition } = context;
const fieldName = fieldDefinition.name.value;
const formatName = fieldName.toLocaleUpperCase();
// 各类 ID
// various types of ID
if (formatName.endsWith('ID')) {
value = faker.number.int();
}
// 时间戳
// timestamp
if (formatName.endsWith('TIME') || formatName.includes('TIMESTAMP')) {
value = dayjs(faker.date.anytime()).valueOf();
}
// 类型状态
// type state
if (formatName.endsWith('STATUS') || formatName.includes('TYPE')) {
value = faker.number.int({ min: 0, max: 1 });
}
// 直接映射值
// direct mapping value
const mapVal = NumMapper[fieldName];
value = typeof mapVal !== 'undefined' ? mapVal : value;
}

View File

@ -17,27 +17,27 @@
import { type IPlugin } from '@coze-arch/idl2ts-generator';
export interface ApiConfig {
// idl 入口
// IDL entrance
entries: Record<string, string>;
// idl 根目录
// IDL root directory
idlRoot: string;
// 服务别名
// 自定义 api 方法
// service alias
// Custom API method
commonCodePath: string;
// api 产物目录
// API Product Catalog
output: string;
// 仓库信息设置
// Warehouse information settings
repository?: {
// 仓库地址
// Warehouse address
url: string;
// clone 到本地的位置
// Clone to local location
dest: string;
};
// 插件
// plugin
plugins?: IPlugin[];
// 聚合导出的文件名
// aggregate exported filename
aggregationExport?: string;
// 格式化文件
// Format file
formatter: (name: string, content: string) => string;
idlFetchConfig?: {
source: string;
@ -48,6 +48,6 @@ export interface ApiConfig {
}
export interface ApiTypeConfig extends ApiConfig {
// 需要过滤的方法
// Methods that require filtering
filters: Record<string, string[]>;
}

View File

@ -163,7 +163,7 @@ export class ClientGenerator {
private processIdlAst(ast: IParseResultItem) {
try {
// 新的解析器貌似不是按原来位置排序的,这里要重新排序
// The new parser doesn't seem to be sorted by the original position, so it needs to be reordered here.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ast.statements.sort((a, b) => a.loc!.start.line - b.loc!.start.line);
} catch (error) {

View File

@ -139,14 +139,14 @@ export class AdapterPlugin implements IPlugin {
getAnnotation(f.annotations, 'api.converter') === 'atoi_comp_empty'
) {
if (isInt(f.fieldType)) {
// 类型转换为 string
// Type conversion to string
f.fieldType.type = SyntaxType.StringKeyword;
}
}
// api.converter 对 int 以及 map 类型生效
// Api.converter works for int and map types
if (getAnnotation(f.annotations, 'api.converter') === 'itoa') {
if (isInt(f.fieldType)) {
// 类型转换为 string
// Type conversion to string
f.fieldType.type = SyntaxType.StringKeyword;
}
if (isMapType(f.fieldType)) {
@ -156,7 +156,7 @@ export class AdapterPlugin implements IPlugin {
}
}
}
// item_converter 对 list 类型生效
// item_converter for list types
if (
['atoi_comp_empty', 'itoa'].includes(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@ -168,24 +168,24 @@ export class AdapterPlugin implements IPlugin {
}
}
// 收集 decode encode 注解处理
// Collection decoding encoding annotation processing
if (getTypeFromDynamicJsonAnnotation(f.annotations)) {
decodeEncodeFields.push(f.name.value);
}
// api.json 注解处理
// api.json annotation processing
const jsonAnnotation = getAnnotation(f.annotations, 'api.json');
if (jsonAnnotation) {
f.extensionConfig = f.extensionConfig || {};
f.extensionConfig.key = jsonAnnotation;
}
// api.json_string 注解处理
// API. json_string annotation handling
const jsonStrAnnotation = getAnnotation(
f.annotations,
'api.json_string',
);
if (jsonStrAnnotation) {
if (isInt(f.fieldType)) {
// 类型转换为 string
// Type conversion to string
f.fieldType.type = SyntaxType.StringKeyword;
f.extensionConfig = f.extensionConfig || {};
f.extensionConfig.key = jsonStrAnnotation;

View File

@ -403,7 +403,7 @@ export class ClientPlugin implements IPlugin {
});
const enumAst = t.tsEnumDeclaration(t.identifier(name.value), enumArr);
// 从后向前删除枚举项,避免索引变化影响
// Delete enumeration items from back to front to avoid the impact of index changes
enumItemIndexArray
.sort((a, b) => b - a)
.forEach(index => {

View File

@ -21,7 +21,7 @@ import { type Contexts, HOOK } from '../context';
const MAGIC_COMMENT_KEY = '\n*@magic-comment';
// 忽略 struct 中的字段
// Ignore fields in struct
export class CommentFormatPlugin {
apply(p: Program<Contexts>) {
p.register(after('PARSE_ENTRY'), ctx => {

View File

@ -26,7 +26,7 @@ interface IPops {
filter: Filter;
}
// 忽略 struct 中的字段
// Ignore fields in struct
export class IgnoreStructFiledPlugin {
private filter: Filter;
constructor({ filter }: IPops) {

View File

@ -56,7 +56,7 @@ export class MetaPlugin implements IPlugin {
ctx => {
const node = ctx.node as ServiceDefinition;
node.functions.forEach(fun => {
// 过滤非泛化接口
// Filtering non-generalized interfaces
if (!fun.extensionConfig?.method) {
return;
}
@ -103,7 +103,7 @@ export class MetaPlugin implements IPlugin {
schemaRoot: getSchemaRootByPath(ast.idlPath, this.options.idlRoot),
service,
} as IMeta;
// 不是 json 时,需要加上 serializer 标识
// When not json, you need to add the serializer flag.
if (extensionConfig?.serializer && extensionConfig?.serializer !== 'json') {
res.serializer = extensionConfig?.serializer;
}
@ -117,7 +117,7 @@ export class MetaPlugin implements IPlugin {
if (isStructDefinition(statement)) {
const wholeBody = statement.fields.find(isFullBody);
if (wholeBody) {
// 处理 api.body="." 以及 api.full_body=''
// Handle api.body = "." and api.full_body = "
return `${id.value}['${getFieldsAlias(wholeBody)}']`;
} else {
return id.value;
@ -184,7 +184,7 @@ export class MetaPlugin implements IPlugin {
}
});
}
// 如果没有指定根据method默认指定为query 或者 body
// If not specified, it is specified as query or body by default according to method.
if (!specificPositionFiled.has(alias)) {
const filedMapping = mapping[defaultPosition];
mapping[defaultPosition] = filedMapping

View File

@ -110,7 +110,7 @@ export class MockTransformerPlugin implements IPlugin {
nextOrder[name] = index;
}
});
// 按照 mock 文件中的顺序优先排序
// Prioritize in order in the mock file
const getOrder = (name: string) =>
typeof mockVarOrder[name] !== 'undefined'
? mockVarOrder[name]
@ -210,7 +210,7 @@ export class MockTransformerPlugin implements IPlugin {
if (isStructDefinition(statement)) {
const wholeBody = statement.fields.find(isFullBody);
if (wholeBody) {
// 处理 api.body="."
// Processing api.body = "."
const { annotations } = wholeBody;
if (hasDynamicJsonAnnotation(annotations)) {
return '{}';
@ -273,7 +273,7 @@ export class MockTransformerPlugin implements IPlugin {
if (!fieldNames.has(fieldName)) {
return;
}
// 没有的,需要重新生成
// No, it needs to be regenerated.
newPros.push(
t.objectProperty(
fieldName.includes('-')
@ -351,11 +351,11 @@ export class MockTransformerPlugin implements IPlugin {
const { valueType } = fieldType;
output = t.arrayExpression([this.processValue(valueType)]);
} else if (isSetType(fieldType)) {
// set 处理成array校验
// Set to array validation
const { valueType } = fieldType;
output = t.arrayExpression([this.processValue(valueType)]);
} else if (isIdentifier(fieldType)) {
// 引用类型
// reference type
const { refName, namespace } = parseIdFiledType(fieldType);
if (!namespace) {
output = t.callExpression(t.identifier(refName), []);
@ -375,7 +375,7 @@ export class MockTransformerPlugin implements IPlugin {
throw new Error(`can not process fieldType : ${fieldType.type}`);
}
private processConst(constVal: ConstValue) {
// 暂时统一处理成0
// Temporarily unified processing to 0
if (isStringLiteral(constVal)) {
return t.stringLiteral(constVal.value);
}
@ -410,11 +410,11 @@ export class MockTransformerPlugin implements IPlugin {
const comment = { type: 'CommentLine', value: commentValues } as any;
const target = this.findTarget(name.value, ctx);
if (target) {
// 需要更新注释
// Comments need to be updated
// target.trailingComments = [comment];
return;
}
// 枚举类型统一处理成常量
// Enumeration types are uniformly processed into constants
const builder = template(`var ${name.value}= () => %%value%% `);
const node = builder({
value: t.numericLiteral(values[0] || 0),
@ -437,7 +437,7 @@ export class MockTransformerPlugin implements IPlugin {
// const variableDeclaration = t.addComment(
// ,
// 'leading',
// '暂时对const默认处理为0如有需要请自行重新赋值'
// 'Temporarily, the default processing for const is 0, please reassign it yourself if necessary '
// );
return node;
}

View File

@ -29,7 +29,7 @@ import { type Options } from '../types';
import { type Contexts, HOOK } from '../context';
/**
* api
* Provide unified API entry
*/
export class PkgEntryPlugin implements IPlugin {
private options: Options;
@ -52,7 +52,7 @@ export class PkgEntryPlugin implements IPlugin {
);
this.funcs.set(
relativePath,
// 只支持单 service
// Only single service supported
meta[0].service,
);
return ctx;

View File

@ -223,7 +223,7 @@ export class SchemaPlugin implements IPlugin {
};
return schema;
} else if (isSetType(fieldType)) {
// set 处理成array校验
// Set to array validation
const { valueType } = fieldType;
const schema: ListType = {
type: 'array',
@ -231,7 +231,7 @@ export class SchemaPlugin implements IPlugin {
};
return schema;
} else if (isIdentifier(fieldType)) {
// 引用类型
// reference type
const { refName, namespace } = parseIdFiledType(fieldType);
if (!namespace) {
const schema: RefType = { $ref: `#/definitions/${refName}` };
@ -249,7 +249,7 @@ export class SchemaPlugin implements IPlugin {
throw new Error(`can not process fieldType : ${fieldType.type}`);
}
private processConst(constVal: ConstValue) {
// 暂时统一处理成0
// Temporarily unified processing to 0
const schema = {} as ConstType;
if (isStringLiteral(constVal)) {
schema.const = constVal.value;

View File

@ -29,11 +29,11 @@ export interface Options {
genMock: boolean;
genClient: boolean;
entryName?: string;
// createAPI 所在文件路径
// createAPI file path
commonCodePath?: string;
// decode encode 会丢失类型,这里提供一种方式,业务手动补充上对应的类型
// Decoding encoding will lose the type, here provides a way to manually add the corresponding type
patchTypesOutput?: string;
// patchTypesOutput 的别名patch type 需要使用额外的 pkg 组织时需要提供
// PatchTypesOutput alias, patch type needs to be provided when using additional pkg organization
patchTypesAliasOutput?: string;
}

View File

@ -42,11 +42,11 @@ export interface IMeta {
type Fields = string[];
export interface IHttpRpcMapping {
path?: Fields; // path参数
query?: Fields; // query参数
body?: Fields; // body 参数
header?: Fields; // header 参数
status_code?: Fields; // http状态码
path?: Fields; // path parameter
query?: Fields; // query parameters
body?: Fields; // Body parameters
header?: Fields; // header parameter
status_code?: Fields; // HTTP status code
cookie?: Fields; // cookie
entire_body?: Fields;
raw_body?: Fields;

View File

@ -68,7 +68,7 @@ export function formatCode(code: string, root = '.') {
printWidth: 120,
singleQuote: true,
};
const file = path.resolve(process.cwd(), root, './for-prettier-bug'); // 这里一定要加多一级目录
const file = path.resolve(process.cwd(), root, './for-prettier-bug'); // Be sure to add an extra level catalog here.
const config = prettier.resolveConfig(file, { editorconfig: true });
return prettier.format(code, {
...(config || defaultConfig),
@ -166,7 +166,7 @@ export function parseId(id: string) {
export function uniformNs(ns: string) {
if (ReservedKeyWord.includes(ns)) {
// 命中保留字,处理为下划线开头
// Hit the reserved word, treated as an underscore
return `_${ns}`;
}
return ns.replace(/\./g, '_');
@ -182,7 +182,7 @@ export function getValuesFromEnum(params: h.EnumDefinition) {
if (h.isIntegerLiteral(initializer.value)) {
currentVal = Number(initializer.value.value);
} else if (h.isHexLiteral(initializer.value)) {
// 16进制
// hexadecimal
currentVal = Number(initializer.value.value);
}
enumArr.push(currentVal);
@ -322,8 +322,8 @@ export function hasDynamicJsonAnnotation(annotations?: h.Annotations) {
}
/**
* api.(request|response).converter
* 😭
* Parse the real type between the front end and the gateway from api. (request | response).converter.
* To be able to come up with these two annotations, this protocol is disgusting😭
* @param annotations
* @returns
*/

View File

@ -42,7 +42,7 @@ export class Program<C extends Ctxs = any> {
} = {};
/**
*
* Load plugin
* @param plugins
*/
loadPlugins(plugins: IPlugin[]) {
@ -51,10 +51,10 @@ export class Program<C extends Ctxs = any> {
}
}
/**
*
* @param event
* @param handler
* @param priority
* registration hook
* @param event name
* @param handler hook
* @Param priority, the smaller the value, the higher the priority
*/
register<
K extends keyof C,
@ -87,7 +87,7 @@ export class Program<C extends Ctxs = any> {
}
}
/**
*
* trigger event
* @param event
* @param args
* @returns

View File

@ -20,20 +20,20 @@ import type { IMeta, CustomAPIMeta } from './types';
export interface ApiLike<T, K, O = unknown, B extends boolean = false> {
(req: T, option?: O extends object ? IOptions & O : IOptions): Promise<K>;
meta: IMeta;
/** fork 一份实例,该实例具有可中止请求的能力 */
/** Fork an instance that has the ability to abort requests */
withAbort: () => CancelAbleApi<T, K, O, B>;
}
export interface CancelAbleApi<T, K, O = unknown, B extends boolean = false>
extends ApiLike<T, K, O, B> {
// 中止请求
// abort request
abort: () => void;
// 是否是取消
// Is it cancelled?
isAborted: () => boolean;
}
/**
* api
* Custom build API method
* @param meta
* @param cancelable
* @param useCustom
@ -56,7 +56,7 @@ export function createAPI<T extends {}, K, O = unknown, B extends boolean = fals
option = { ...(option || {}), ...customOption };
// 这里可以使用传进来的 req 作为默认映射,减少需要在 customAPI 中,需要手动绑定的情况
// Here, you can use the incoming req as the default mapping to reduce the need for manual binding in the customAPI
if (useCustom) {
const mappingKeys: string[] = Object.keys(meta.reqMapping)
.map(key => meta.reqMapping[key])
@ -98,12 +98,12 @@ export function createAPI<T extends {}, K, O = unknown, B extends boolean = fals
function abort() {
/**
* pending abortController.signal abortController.abort()
* abortController.abort(), abortController.signal.aborted true
* aborted
* The reason for adding the pending state here is that the state value of abortController.signal is only controlled by the abortController.abort () method;
* No matter whether the request is completed or abnormal, as long as abortController.abort () is called, abortController.signal.aborted must be true.
* This makes it difficult to determine whether the request is really aborted.
*
* pending abort()
* isAborted === true abort
* This is changed to abort () only if the request is pending.
* When isAborted === true, the request exception must be caused by manual abort
*/
if (pending === true && cancelable && abortController) {
abortController.abort();
@ -128,7 +128,7 @@ export function createAPI<T extends {}, K, O = unknown, B extends boolean = fals
}
/**
* 使便
* Some non-generalized interfaces can be built using modified methods to facilitate unified management of interfaces
* @param customAPIMeta
* @param cancelable
* @returns

View File

@ -30,11 +30,11 @@ export interface IMeta {
type Fields = string[];
export interface IHttpRpcMapping {
path?: Fields; // path参数
query?: Fields; // query参数
body?: Fields; // body 参数
header?: Fields; // header 参数
status_code?: Fields; // http状态码
path?: Fields; // path parameter
query?: Fields; // query parameters
body?: Fields; // Body parameters
header?: Fields; // header parameter
status_code?: Fields; // HTTP status code
cookie?: Fields; // cookie
entire_body?: Fields;
raw_body?: Fields;

View File

@ -27,22 +27,22 @@ export interface ServiceConfig {
} & Omit<IdlConfig, 'clientFactory'>;
}
export interface IdlConfig {
// client 工厂方法,要求返回一个 fetchClient 函数,使用 meta 总的信息,可实现灵活的 client 配置
// The client factory method requires a fetchClient function to be returned, which uses the meta total information to achieve flexible client configuration
clientFactory?: (
meta: IMeta,
) => (uri: string, init: RequestInit, opt: any) => any;
// uri 前缀,如果 client 中设置了,这里可以不设置
// URI prefix, if set in client, you can leave it unset here
uriPrefix?: string;
getParams?: (key: string) => string;
// 服务级别的配置
// Service level configuration
services?: ServiceConfig;
// 开发时,如果本地校验失败,这里可回调,通常是弹 toast
// During development, if the local verification fails, it can be called back here, usually by playing toast.
onVerifyReqError?: (message: string, ctx: any) => void;
}
export interface IOptions {
config?: IdlConfig;
// 透传 request options 的选项
// Passthrough request options
requestOptions?: Record<string, any>;
[key: string]: any;
}
@ -52,7 +52,7 @@ export interface PathPrams<T> {
}
export function getConfig(service: string, method: string): IdlConfig {
// 手动注册的配置优先级比全局变量高
// Manually registered configuration takes precedence over global variables
let config: IdlConfig | undefined = configCenter.getConfig(service);
if (!config) {
config = {};
@ -137,7 +137,7 @@ export function normalizeRequest(
);
const { uriPrefix = '', clientFactory } = config;
if (!clientFactory) {
// todo 这里考虑给个默认的 client防止某些公共 package 在一些异常情况下使用
// Todo here considers giving a default client to prevent some public packages from being used in some abnormal cases
throw new Error('Lack of clientFactory config');
}
let uri = uriPrefix + apiUri;
@ -149,11 +149,11 @@ export function normalizeRequest(
: 'application/json';
if (option?.requestOptions?.headers) {
headers = { ...headers, ...option.requestOptions.headers };
// 合并了 header可删除
// Merged headers, can be deleted
delete option.requestOptions.headers;
}
if (meta.reqMapping.query && meta.reqMapping.query.length > 0) {
// 这里默认 skipNulls网关后端需要忽略 null
// The default here is skipNulls, and the gateway backend needs to ignore null.
uri = `${uri}?${qs.stringify(getValue(req, meta.reqMapping.query), {
skipNulls: true,
arrayFormat: 'comma',
@ -168,7 +168,7 @@ export function normalizeRequest(
if (meta.reqMapping.entire_body && meta.reqMapping.entire_body.length > 0) {
if (meta.reqMapping.entire_body.length === 1) {
// 默认处理为 json ,如有其他场景需要支持,后需要再支持
// The default processing is json. If there are other scenarios that need to be supported, they need to be supported later.
requestOption.body = req[meta.reqMapping.entire_body[0]];
} else {
throw new Error('idl invalid entire_body should be only one filed');
@ -203,7 +203,7 @@ export function normalizeRequest(
};
}
// 旧版的 ferry 中,即使 idl 没有声明body也需要加一个 空的 body
// In the old version of ferry, even if idl does not declare body, you need to add an empty body.
if (
!requestOption.body &&
['POST', 'PUT', 'PATCH'].includes(

View File

@ -89,17 +89,17 @@ describe('PkgRootWebpackPlugin', () => {
new PkgRootWebpackPlugin(customOptions);
// 注意Object.assign 中后面的对象会覆盖前面的对象,所以默认配置会覆盖用户配置
// Note: Subsequent objects in Object.assign overwrite the preceding objects, so the default configuration overrides the user configuration
expect(OriginPkgRootWebpackPlugin).toHaveBeenCalledWith({
customProp: 'customValue',
root: '@', // 被默认值覆盖
root: '@', // Overwritten by default
packagesDirs: [
'packages/project1',
'packages/project2',
'apps/app1',
'apps/app2',
],
excludeFolders: [], // 被默认值覆盖
excludeFolders: [], // Overwritten by default
});
});
@ -110,9 +110,9 @@ describe('PkgRootWebpackPlugin', () => {
new PkgRootWebpackPlugin(customOptions);
// Object.assign 的行为:后面的对象会覆盖前面的对象属性
// Object.assign behavior: subsequent objects overwrite previous object properties
expect(OriginPkgRootWebpackPlugin).toHaveBeenCalledWith({
root: '@', // 被默认值覆盖
root: '@', // Overwritten by default
packagesDirs: [
'packages/project1',
'packages/project2',
@ -139,7 +139,7 @@ describe('PkgRootWebpackPlugin', () => {
});
it('验证所有导出都正确', () => {
// 验证模块导出了正确的类和默认导出
// Verify that the module exported the correct class and the default export
expect(PkgRootWebpackPlugin).toBeDefined();
expect(typeof PkgRootWebpackPlugin).toBe('function');
});
@ -147,7 +147,7 @@ describe('PkgRootWebpackPlugin', () => {
it('应该正确处理 Rush 配置中的项目文件夹', () => {
new PkgRootWebpackPlugin();
// 验证传递给父类的 packagesDirs 包含所有项目文件夹
// Verify that the packagesDirs passed to the parent class contain all project folders
const call = (OriginPkgRootWebpackPlugin as any).mock.calls[0];
const options = call[0];
@ -160,10 +160,10 @@ describe('PkgRootWebpackPlugin', () => {
});
it('测试插件基本功能正常工作', () => {
// 这个测试验证插件能正常实例化并调用父类构造函数
// This test verifies that the plugin can instantiate and call the parent class constructor normally
new PkgRootWebpackPlugin();
// 验证确实调用了父类构造函数
// Verify that the parent class constructor is indeed called
expect(OriginPkgRootWebpackPlugin).toHaveBeenCalled();
});
});

View File

@ -38,7 +38,7 @@ class PkgRootWebpackPlugin extends pkg_root_webpack_plugin_origin_1.default {
const mergedOptions = Object.assign({}, options || {}, {
root: '@',
packagesDirs: rushJsonPackagesDir,
// 排除apps/*,减少处理时间
// Exclude apps/* to reduce processing time
excludeFolders: [],
});
super(mergedOptions);

View File

@ -41,7 +41,7 @@ class PkgRootWebpackPlugin extends OriginPkgRootWebpackPlugin {
const mergedOptions = Object.assign({}, options || {}, {
root: '@',
packagesDirs: rushJsonPackagesDir,
// 排除apps/*,减少处理时间
// Exclude apps/* to reduce processing time
excludeFolders: [],
});
super(mergedOptions);

View File

@ -1,79 +1,79 @@
# @coze-arch/monorepo-kits
## 功能概述
/* Function Overview */
`@coze-arch/monorepo-kits` 是一个用于管理 monorepo 项目的工具包,提供了基于 Rush 框架的项目查找、依赖分析和配置管理功能。
/* "@Coze-arch/monorepo-kits" is a toolkit for managing monorepo projects, providing project lookup, dependency analysis, and configuration management capabilities based on the Rush framework. */
## 主要功能模块
/* Main Functional Modules */
### 1. 子包管理 (sub-packages.ts)
/* ###1. Subpackage management (sub-packages.ts) */
#### lookupSubPackages(packageName: string): string[]
- **功能**: 递归查找指定包的所有子依赖包
- **特性**: 使用缓存机制避免重复计算
- **返回**: 所有依赖包的名称数组(去重后)
/* - ** Function **: Recursively find all child dependencies of the specified package */
/* - ** Features **: Use caching mechanism to avoid double counting */
/* - ** Returns **: Array of names of all dependent packages (after deduplicate) */
#### getPackageLocation(packageName: string): string
- **功能**: 获取指定包的文件系统路径
- **返回**: 包的项目文件夹路径
/* - ** Function **: Get the file system path of the specified package */
/* - ** return **: the project folder path of the package */
#### getPackageJson(packageName: string): RushConfigurationProject['packageJson']
- **功能**: 获取指定包的 package.json 配置信息
- **返回**: 包的 package.json 对象
/* - ** Function **: Get the package.json configuration information of the specified package */
/* - ** returns **: package's package.json object */
### 2. Rush 配置管理 (rush-config.ts)
/* ###2. Rush configuration management (rush-config.ts) */
#### getRushConfiguration(): RushConfiguration
- **功能**: 获取 Rush 配置实例
- **特性**: 单例模式,首次调用时从默认位置加载配置,后续调用复用实例
- **返回**: RushConfiguration 对象
/* - ** Features **: Get Rush Configuration Instance */
/* - ** Features **: Singleton mode, first call loads configuration from default location, subsequent calls reuse instance */
/* - ** returns **: RushConfiguration object */
### 3. 项目查找 (lookup.ts)
/* ###3. Project lookup (lookup.ts) */
#### lookupTo(to: string): string[]
- **功能**: 查找指定包的直接依赖项
- **参数**: 目标包名称
- **返回**: 依赖包名称数组
/* - ** Features **: Find direct dependencies of a specified package */
/* - ** Parameter **: Target package name */
/* - ** Returns **: Array of dependency package names */
#### lookupFrom(from: string): void
- **功能**: 查找从指定包出发的相关信息(当前实现不完整)
- **参数**: 源包名称
/* - ** Features **: Find information about outgoing from a specified package (current implementation is incomplete) */
/* - ** parameter **: source package name */
#### lookupOnly(packageName: string): RushConfigurationProject
- **功能**: 查找并返回指定包的项目配置对象
- **参数**: 包名称
- **返回**: 完整的项目配置对象
/* - ** Features **: Find and return the project configuration object of the specified package */
/* - ** parameter **: package name */
/* - ** Return **: complete project configuration object */
## 依赖关系
/* ##dependencies */
- **主要依赖**: `@rushstack/rush-sdk@5.100.2`
- **开发依赖**: 包含 ESLint、TypeScript、Vitest 等工具链
/* - ** Major dependencies **: '@rushstack/rush-sdk@5.100.2' */
/* - ** Development dependencies **: Includes ESLint, TypeScript, Vitest and other toolchains */
## 使用场景
/* ##usage scenario */
1. **依赖分析**: 分析 monorepo 中包之间的依赖关系
2. **路径解析**: 获取包在文件系统中的实际位置
3. **配置查询**: 查询包的配置信息和元数据
4. **自动化工具**: 为构建脚本、部署工具等提供 monorepo 项目信息
/* 1. ** Dependency Analysis **: Analyze the dependencies between packages in Monorepo */
/* 2. ** Path parsing **: Get the actual location of the package in the file system */
/* 3. ** Configuration query **: Query the configuration information and metadata of the package */
/* 4. ** Automation Tools **: Provide monorepo project information for build scripts, deployment tools, etc */
## 架构特点
/* ##Architecture Features */
- **缓存优化**: 对递归依赖查找进行缓存,提高性能
- **错误处理**: 包含完善的包不存在异常处理
- **单例模式**: Rush 配置采用单例模式,避免重复加载
- **类型安全**: 基于 TypeScript提供完整的类型定义
/* - ** Cache optimization **: Cache recursive dependency lookups to improve performance */
/* - ** Error Handling **: Includes perfect package without exception handling */
/* - ** Singleton mode **: Rush configuration adopts singleton mode to avoid repeated loading */
/* Type safety: Based on TypeScript, complete type definition is provided */
## 代码结构
/* ##Code structure */
```
src/
├── index.ts # 主入口文件,导出所有公共 API
├── sub-packages.ts # 子包管理和依赖查找功能
├── rush-config.ts # Rush 配置管理
└── lookup.ts # 项目查找相关功能
/* < unk > ─ index.ts #Main entry file, export all public APIs */
/* < unk > ─ Sub-packages.ts #Subpackage management and dependency lookup function */
/* 🥰 ─ rush-config.ts #Rush configuration management */
/* 🥰 ─ ─ lookup.ts #Project lookup related functions */
```
## API 导出
/* ##API export */
```typescript
export {
@ -87,4 +87,4 @@ export { getRushConfiguration } from './rush-config';
export { lookupTo, lookupFrom, lookupOnly } from './lookup';
```
这个工具包为 monorepo 环境下的包管理、依赖分析和自动化工具开发提供了基础支持。
/* This toolkit provides fundamental support for package management, dependency analysis, and automated tool development in Monorepo environments. */

View File

@ -80,5 +80,5 @@ const logger = new Logger();
export { logger };
/** @deprecated 该使用方式已废弃,请使用`import { logger } from '@coze-arch/rush-logger' */
/** @Deprecated This usage is deprecated, please use'import {logger} from '@code-arch/rush-logger' */
export default logger;

View File

@ -22,7 +22,7 @@ import { I18n } from '@coze-arch/i18n';
import { UIModal } from '@coze-arch/bot-semi';
import { useResetLocationState } from '@coze-arch/bot-hooks';
// 三方授权失败callback至发布页需要显式阻塞弹窗
// Tripartite authorization failed, callback to the release page needs to explicitly block the pop-up window
export const useAuthFail = () => {
const { state } = useLocation();
const { authFailMessage = '', authStatus } = (state ??

View File

@ -41,7 +41,7 @@ const DEFAULT_BOT_INFO: PublisherBotInfo = {
prompt: '',
};
// 获取plugin收费插件信息
// Get plugin charging plugin information
const getPricingRules: (
pluginApiDetailMap?: Record<string | number, PluginAPIDetal>,
) => Promise<PluginPricingRule[] | undefined> = async pluginApiDetailMap => {
@ -58,7 +58,7 @@ const getPricingRules: (
return pricing_rules;
};
// 是否有plugin
// Is there a plugin?
const hasPluginApi: (
pluginApiDetailMap?: Record<string | number, PluginAPIDetal>,
) => boolean = pluginApiDetailMap =>
@ -113,7 +113,7 @@ export const useGetPublisherInitInfo: () => {
bot_option_data,
} = botInfoResp?.data ?? {};
// 获取plugin扣费信息
// Get plugin deduction information
let pluginPricingRules: Array<PluginPricingRule> = [];
if (
hasPluginApi(bot_option_data?.plugin_api_detail_map) &&

View File

@ -126,7 +126,7 @@ export const AgentPublishPage = () => {
const publishBtn = (
<UIButton
theme="solid"
//解决异步请求botInfo未返回时可以点击publish产生的错误
//Resolve the error caused by clicking publish when the asynchronous request botInfo is not returned
disabled={Boolean(publishDisabled) || !botInfo.name}
loading={publishLoading}
onClick={handlePublish}

View File

@ -51,7 +51,7 @@ import { PublishResultArea } from './component/publish-result-area';
import styles from '../index.module.less';
interface PublishResultProps {
// 隐藏Banner
// Hidden Banner
hiddenBanner?: boolean;
publishResult?: PublishResultInfo;
}
@ -212,7 +212,7 @@ export const PublishResult = ({
? `⚠️ ${I18n.t('publish_result_all_failed')}`
: `🎉 ${I18n.t('publish_success')}`}
</div>
{/* 开源版暂不支持该功能 */}
{/* The open-source version does not currently support this function */}
{IS_OVERSEA && !publishResult?.monetizeConfigSuccess ? (
<div className="mt-[12px] flex items-center gap-[8px] coz-fg-primary">
<IconCozInfoCircleFill className="coz-fg-hglt-yellow" />
@ -221,7 +221,7 @@ export const PublishResult = ({
</span>
</div>
) : null}
{/* 开源版暂不支持该功能 */}
{/* The open-source version does not currently support this function */}
{FLAGS['bot.studio.publish_management'] && !IS_OPEN_SOURCE ? (
<div className="coz-fg-dim text-[12px]">
{I18n.t('release_management_detail1', {

View File

@ -100,8 +100,8 @@ export const PublishConnectorAction: React.FC<ActionColumnProps> = ({
const action = (() => {
switch (record.bind_type) {
case BindType.KvBind: //仅绑定
case BindType.KvAuthBind: //绑定+授权,取消绑定后自动取消授权
case BindType.KvBind: //bind only
case BindType.KvAuthBind: //Bind + authorization, automatically cancel the authorization after unbinding
return (
<KvBindButton
record={record}
@ -181,7 +181,7 @@ export const ConfigStatusColumn: React.FC<ActionColumnProps> = props => {
tagProps={{
color,
style: { margin: 0 },
// 覆盖原来的orange-tag
// Overwrite the original orange-tag.
className: styles['common-tag'],
}}
/>

View File

@ -96,7 +96,7 @@ export const StoreBind: React.FC<StoreBindProps> = ({
setSourceConfig(true);
} else {
setSourceConfig(false);
// 兜底逻辑:如果出错,或不在白名单中,则自动更改为“私有配置”发布
// Fallback logic: if there is an error, or it is not in the whitelist, it is automatically changed to "private configuration" publishing
handleSelect('open_source', BotSubmitStatus.Private);
}
},
@ -107,7 +107,7 @@ export const StoreBind: React.FC<StoreBindProps> = ({
async () => {
const res = await ProductApi.PublicGetProductCategoryList(
{
// 代表含义:无商品也返回类型,即为全量的类型
// Representative meaning: no goods also return the type, that is, the type of the full amount
need_empty_category: true,
entity_type: ProductEntityType.Bot,
},

View File

@ -20,7 +20,7 @@ import { useEffect } from 'react';
import { AuthStatus } from '@coze-arch/idl/developer_api';
import { useResetLocationState } from '@coze-arch/bot-hooks';
// 三方授权成功,调用成功回调
// The three-party authorization is successful, and the callback is successful.
export const useAuthSuccess = (bindSuccess: (id: string) => void) => {
const { state } = useLocation();
const { oauth2, authStatus } = (state ?? history.state ?? {}) as Record<

View File

@ -103,7 +103,7 @@ const getCheckboxProps = (record: PublishConnectorInfo, disabled: boolean) => {
return {
disabled: !!disableTip || disabled,
id: record.id,
// Offline状态没有tooltip
// Offline status No tooltip
children: disableTip ? (
<Tooltip content={disableTip}>
<span className={styles['disable-tooltip']} />
@ -152,7 +152,7 @@ export const TableCollection = (props: PublishTableProps) => {
[dataSourceForChannel, connectorBrandInfoMap],
);
// 无全选按钮因此所有表格使用相同check配置
// There is no select all button, so all tables use the same check configuration
const baseConfigForChecker = {
hidden: true,
fixed: 'left' as const,
@ -212,9 +212,9 @@ export const TableCollection = (props: PublishTableProps) => {
: [record.id, ...ids],
);
}
}, // 点击行选中
onMouseEnter: () => onMouseEnter(record), // 鼠标移入行
onMouseLeave: () => onMouseLeave(record), // 鼠标移出行
}, // Click on the line to select
onMouseEnter: () => onMouseEnter(record), // mouseover
onMouseLeave: () => onMouseLeave(record), // mouse movement
});
const tableCommonProps = {
className: classNames(styles['publish-table']),
@ -285,7 +285,7 @@ function TableTittleExtra({
platforms: PublishConnectorInfo[];
botInfo: PublisherBotInfo;
}) {
// 付费墙
// paywall
const isAvailable = useBenefitAvailable({
scene: PremiumPaywallScene.API,
});

View File

@ -24,7 +24,7 @@ import { I18n } from '@coze-arch/i18n';
import { Typography } from '@coze-arch/coze-design';
import { type PluginPricingRule } from '@coze-arch/bot-api/plugin_develop';
// 发布页提示
// release page tip
export const PluginPricingInfo: FC<{
pluginPricingRules?: Array<PluginPricingRule>;
}> = ({ pluginPricingRules }) => {

View File

@ -32,7 +32,7 @@ export function SingleAgentModelView(props: SingleAgentModelViewProps) {
<SingleAgentModelViewBase
{...props}
triggerRender={m => (
// 模型临期时强制完整展示临期提示
// Forced full display of Advent prompts during model Advent
<Collapsible
itemKey={itemKey}
fullContent={

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const DOMAIN_REGEXP = /^([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})$/;
export function isValidUrl(url: string): boolean {
@ -21,7 +21,7 @@ export function isValidUrl(url: string): boolean {
// cp-disable-next-line
const urlObject = new URL(`https://${url}`);
return DOMAIN_REGEXP.test(urlObject.hostname);
// eslint-disable-next-line @coze-arch/use-error-in-catch -- 根据函数功能无需 throw error
// eslint-disable-next-line @coze-arch/use-error-in-catch -- no need to throw error according to function function
} catch {
return false;
}

View File

@ -35,8 +35,8 @@ const getDefaultState = (): DraftBotDataSetStoreState => ({
datasetsMap: {},
});
// 目前 work_info 里的 dataset 只包含了很少量的元信息,
// 为了方便判断引入的 dataset 类型(用于分组、模型能力检查等等),这里统一缓存当下使用的 dataset
// At present, the dataset in the work_info contains only a small amount of meta information.
// In order to facilitate the determination of the type of dataset introduced (for grouping, model capability checking, etc.), the dataset currently in use is cached here
export const createDraftBotDatasetsStore = () =>
create<DraftBotDataSetStoreState & DraftBotDataSetStoreAction>()(
devtools(

View File

@ -19,7 +19,7 @@ import { create } from 'zustand';
import { produce } from 'immer';
export interface FreeGrabModalHierarchyState {
// modal 的 key list
// Modal key list
modalHierarchyList: string[];
}
@ -31,7 +31,7 @@ export interface FreeGrabModalHierarchyAction {
}
/**
*
* Hierarchical relationship between pop-ups that can be dragged and dropped freely
*/
export const createFreeGrabModalHierarchyStore = () =>
create<FreeGrabModalHierarchyState & FreeGrabModalHierarchyAction>()(

View File

@ -24,15 +24,15 @@ import { type ModelPresetValues } from './type';
import { getModelPresetValues } from './helpers/get-model-preset-values';
export interface ModelState {
// 当前环境所有合法的模型列表
// List of all valid models in the current environment
onlineModelList: Model[];
/* key === modelId
* 例如: cn-inhouse GPT , cn-release, bot = + 1(GPT)
* MultiAgent , Agent = + 1()
* ,
/* Special models that do not belong to the current environment key === modelId
* For example: select the GPT model in cn-inhouse, then switch to cn-release, the current bot model list = normal model list + 1 special model (GPT)
* In MultiAgent mode, each Agent model list = normal model list + 1 special model (may exist)
* After switching from the special model to the normal model, it is not allowed to switch back to the special model
*/
offlineModelMap: Record<string, Model>;
// 纯计算属性, 由 specialModel 和 baseModel 计算而来 key === modelId
// Pure computational properties, calculated from specialModel and baseModel key === modelId
// key === modelId
modelPresetValuesMap: Record<string, ModelPresetValues>;
}

View File

@ -37,7 +37,7 @@ export interface OnboardingDirtyLogicCompatibilityAction {
}
/**
* bot onboarding
* Complex, dirty business logic for handling bot edit page onboarding
*/
export const createOnboardingDirtyLogicCompatibilityStore = () =>
create<

View File

@ -32,7 +32,7 @@ export type TGetModelCapabilityConfig = (params: {
getModelById: (id: string) => Model | undefined;
}) => ModelCapabilityConfig;
// 模型能力配置的 fallback没有配置的能力按支持处理
// Fallback of model capability configuration, capability without configuration is handled as supported
export const defaultModelCapConfig = Object.values(ModelFuncConfigType).reduce(
(res, type) => ({
...res,
@ -56,7 +56,7 @@ const mergeModelCapabilityConfig = (
target
? Object.entries(target).reduce<ModelCapabilityConfig>(
(merged, [key, status]) => {
// 未配置的能力视为完全支持
// Unconfigured capabilities are considered fully supported
const [preStatus, preName] = merged[
key as unknown as ModelFuncConfigType
] ?? [ModelFuncConfigStatus.FullSupport, []];

View File

@ -41,7 +41,7 @@ export function convertModelValueType(
return Number(value);
}
// 理论上不走这里
// Theoretically not going here
primitiveExhaustiveCheck(type);
return value;
}

View File

@ -22,13 +22,13 @@ import {
} from '../src/services/type';
import { BotInputLengthService, botInputLengthService } from '../src/services';
// 模拟 SuggestedQuestionsShowMode 枚举
// Analog SuggestedQuestionsShowMode Enumeration
enum SuggestedQuestionsShowMode {
Random = 0,
All = 1,
}
// 模拟配置
// simulation configuration
const mockConfig: BotInputLengthConfig = {
botName: 10,
botDescription: 100,
@ -39,16 +39,16 @@ const mockConfig: BotInputLengthConfig = {
projectDescription: 100,
};
// 模拟获取配置的函数
// Function to simulate acquisition configuration
const mockGetConfig = vi.fn().mockReturnValue(mockConfig);
describe('BotInputLengthService', () => {
let service: BotInputLengthService;
beforeEach(() => {
// 重置模拟
// Reset simulation
vi.clearAllMocks();
// 创建服务实例
// Create a service instance
service = new BotInputLengthService(mockGetConfig);
});
@ -62,23 +62,23 @@ describe('BotInputLengthService', () => {
expect(service.getInputLengthLimit('projectName')).toBe(10);
expect(service.getInputLengthLimit('projectDescription')).toBe(100);
// 验证配置获取函数被调用
// Verify that the configuration get function is called
expect(mockGetConfig).toHaveBeenCalledTimes(7);
});
});
describe('getValueLength', () => {
it('应该返回字符串的字形簇数量', () => {
// 普通字符串
// Normal string
expect(service.getValueLength('hello')).toBe(5);
// 包含表情符号的字符串(表情符号算作一个字形簇)
// A string containing the emoji (the emoji counts as a glyph cluster)
expect(service.getValueLength('hi😊')).toBe(3);
// 包含组合字符的字符串
// A string containing combined characters
expect(service.getValueLength('café')).toBe(4);
// 空字符串
// empty string
expect(service.getValueLength('')).toBe(0);
// undefined
@ -88,12 +88,12 @@ describe('BotInputLengthService', () => {
describe('sliceStringByMaxLength', () => {
it('应该根据字段限制截取字符串', () => {
// 字符串长度小于限制
// String length less than limit
expect(
service.sliceStringByMaxLength({ value: 'hello', field: 'botName' }),
).toBe('hello');
// 字符串长度等于限制
// String length equals limit
expect(
service.sliceStringByMaxLength({
value: '1234567890',
@ -101,7 +101,7 @@ describe('BotInputLengthService', () => {
}),
).toBe('1234567890');
// 字符串长度大于限制
// String length is greater than limit
expect(
service.sliceStringByMaxLength({
value: '12345678901234567890',
@ -109,7 +109,7 @@ describe('BotInputLengthService', () => {
}),
).toBe('1234567890');
// 包含表情符号的字符串
// A string containing emoji
expect(
service.sliceStringByMaxLength({
value: 'hello😊world',
@ -117,7 +117,7 @@ describe('BotInputLengthService', () => {
}),
).toBe('hello😊worl');
// 验证配置获取函数被调用
// Verify that the configuration get function is called
expect(mockGetConfig).toHaveBeenCalledTimes(4);
});
});
@ -147,13 +147,13 @@ describe('BotInputLengthService', () => {
const result = service.sliceWorkInfoOnboardingByMaxLength(workInfo);
// 验证开场白被截取
// Verify that the opening statement was intercepted
expect(result.prologue).toBe(
'This is a very long prologue that exceeds the limi',
);
expect(result.prologue.length).toBeLessThanOrEqual(50);
// 验证建议问题被截取
// Validation suggestion problem intercepted
expect(result.suggested_questions[0]?.content).toBe(
'This is a very long ',
);
@ -175,7 +175,7 @@ describe('BotInputLengthService', () => {
expect(result.suggested_questions[2]?.id).toBe('3');
expect(result.suggested_questions[2]?.highlight).toBe(false);
// 验证显示模式保持不变
// Verify that the display mode remains unchanged
expect(result.suggested_questions_show_mode).toBe(
SuggestedQuestionsShowMode.All,
);
@ -199,10 +199,10 @@ describe('BotInputLengthService', () => {
});
});
// 测试导出的单例
// Test Exported Singletons
describe('botInputLengthService', () => {
it('应该导出一个 BotInputLengthService 的实例', () => {
// 验证导出的单例是 BotInputLengthService 的实例
// Verify that the exported singleton is an instance of BotInputLengthService
expect(botInputLengthService).toBeInstanceOf(BotInputLengthService);
});
});

View File

@ -17,19 +17,19 @@
import { type SuggestedQuestionsShowMode } from '@coze-arch/bot-api/playground_api';
export interface BotInputLengthConfig {
/** Agent 名称的长度 */
/** Length of Agent Name */
botName: number;
/** Agent 描述的长度 */
/** Length of Agent Description */
botDescription: number;
/** Agent 开场白的长度 */
/** Length of Agent's opening statement */
onboarding: number;
/** Agent 单条开场白建议的长度 */
/** Agent, the length of a single opening line suggestion */
onboardingSuggestion: number;
/** 用户问题建议自定义 prompt 长度 */
/** User question Suggested custom prompt length */
suggestionPrompt: number;
/** Project 名称的长度 */
/** Length of Project Name */
projectName: number;
/** Project 描述的长度 */
/** Project Description Length */
projectDescription: number;
}

View File

@ -52,8 +52,8 @@ vi.mock('@coze-arch/bot-tea', () => ({
},
ParamsTypeDefine: {},
PluginMockDataGenerateMode: {
MANUAL: 0, // 手动创建
RANDOM: 1, // 随机生成
MANUAL: 0, // create manually
RANDOM: 1, // random generation
LLM: 2,
},
}));
@ -61,21 +61,21 @@ vi.mock('@coze-arch/bot-tea', () => ({
vi.mock('@coze-arch/bot-hooks', () => ({
SceneType: {
BOT__VIEW__WORKFLOW: 'botViewWorkflow',
/** bot 详情页查看 workflow或新建 workflow 但未发布,点击返回 */
/** View the workflow on the bot details page, or create a new workflow but not published, click Return */
WORKFLOW__BACK__BOT: 'workflowBackBot',
/** bot 详情页创建 workflow在 workflow 发布后返回 */
/** The bot details page creates a workflow and returns it after the workflow is published */
WORKFLOW_PUBLISHED__BACK__BOT: 'workflowPublishedBackBot',
/** bot 详情页进入 mock data 页面 */
/** Bot details page Enter the mock data page */
BOT__TO__PLUGIN_MOCK_DATA: 'botToPluginMockData',
/** workflow 详情页进入 mock data 页面 */
/** Workflow details page Enter the mock data page */
WORKFLOW__TO__PLUGIN_MOCK_DATA: 'workflowToPluginMockData',
/** mock set 页进入 mock data 页面 */
/** Mock set page Enter the mock data page */
PLUGIN_MOCK_SET__TO__PLUGIN_MOCK_DATA: 'pluginMockSetToPluginMockData',
/** bot 详情页进入 knowledge 页面 */
/** Bot details page Enter the knowledge page */
BOT__VIEW__KNOWLEDGE: 'botViewKnowledge',
/** knowledge 页面点击退出返回 bot 详情页(未点击添加) */
/** Knowledge page Click Exit to return to bot details page (not clicked Add) */
KNOWLEDGE__BACK__BOT: 'knowledgeBackBot',
/** knowledge 页面点击返回 bot 详情页,并添加到 bot */
/** Knowledge page Click to return to bot details page and add to bot */
KNOWLEDGE__ADD_TO__BOT: 'knowledgeAddToBot',
},
usePageJumpService: vi.fn().mockReturnValue({

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
// 引入我们的被测方法
// Introducing our test method
import { describe, expect, it, vi } from 'vitest';
@ -23,39 +23,39 @@ import { getEnv } from '@/util/get-env';
describe('getEnv function', () => {
it('should return "cn-boe" when not in production', () => {
vi.stubGlobal('IS_PROD', undefined);
// 不设置IS_PROD默认为非生产环境
// Do not set IS_PROD, default to non-production environment
const env = getEnv();
expect(env).toBe('cn-boe');
});
it('should return "cn-release" when in production, not overseas, and is release version', () => {
vi.stubGlobal('IS_PROD', true); // 设置为生产环境
vi.stubGlobal('IS_OVERSEA', false); // 不是海外
vi.stubGlobal('IS_RELEASE_VERSION', true); // 是发布版本
vi.stubGlobal('IS_PROD', true); // Set to production environment
vi.stubGlobal('IS_OVERSEA', false); // Not overseas.
vi.stubGlobal('IS_RELEASE_VERSION', true); // Is the release version
const env = getEnv();
expect(env).toBe('cn-release');
});
it('should return "cn-inhouse" when in production, not overseas, and is not release version', () => {
vi.stubGlobal('IS_PROD', true); // 设置为生产环境
vi.stubGlobal('IS_OVERSEA', false); // 不是海外
vi.stubGlobal('IS_RELEASE_VERSION', false); // 不是发布版本
vi.stubGlobal('IS_PROD', true); // Set to production environment
vi.stubGlobal('IS_OVERSEA', false); // Not overseas.
vi.stubGlobal('IS_RELEASE_VERSION', false); // Not the release version
const env = getEnv();
expect(env).toBe('cn-inhouse');
});
it('should return "oversea-release" when in production, overseas, and is release version', () => {
vi.stubGlobal('IS_PROD', true); // 设置为生产环境
vi.stubGlobal('IS_OVERSEA', true); // 是海外
vi.stubGlobal('IS_RELEASE_VERSION', true); // 是发布版本
vi.stubGlobal('IS_PROD', true); // Set to production environment
vi.stubGlobal('IS_OVERSEA', true); // Is overseas
vi.stubGlobal('IS_RELEASE_VERSION', true); // Is the release version
const env = getEnv();
expect(env).toBe('oversea-release');
});
it('should return "oversea-inhouse" when in production, overseas, and is not release version', () => {
vi.stubGlobal('IS_PROD', true); // 设置为生产环境
vi.stubGlobal('IS_OVERSEA', true); // 是海外
vi.stubGlobal('IS_RELEASE_VERSION', false); // 不是发布版本
vi.stubGlobal('IS_PROD', true); // Set to production environment
vi.stubGlobal('IS_OVERSEA', true); // Is overseas
vi.stubGlobal('IS_RELEASE_VERSION', false); // Not the release version
const env = getEnv();
expect(env).toBe('oversea-inhouse');
});

View File

@ -61,7 +61,7 @@ export const PluginModal: React.FC<PluginModalProps> = ({
return openMode === OpenModeType.OnlyOnceAdd ? [] : pluginApis;
};
const { sider, filter, content } = usePluginModalParts({
// 如果是仅添加一次,清空默认选中
// If it is added only once, clear the default selection.
pluginApiList: getPluginApiList(),
onPluginApiListChange: updateSkillPluginApis,
openMode,

View File

@ -36,7 +36,7 @@ export const usePluginApisModal = (props?: PluginModalModeProps) => {
const _initQuery = isNumber(params) ? undefined : params?.initQuery;
setVisible(true);
setInitQuery(_initQuery);
// 0 也有效
// 0 is also valid
if (isNumber(openType)) {
setType(openType);
}

View File

@ -54,17 +54,17 @@ export interface ToolDetailPageProps
onDebugSuccessCallback?: () => void;
}
// 页面-编辑插件API
// Page - Edit Plugin API
export const ToolDetailPage: FC<ToolDetailPageProps> = ({
toolID,
onDebugSuccessCallback,
renderDescComponent,
renderParamsComponent,
}) => {
//捕获错误信息,跳转统一落地页
//Capture error messages and jump to the unified landing page
const capture = useErrorHandler();
const [editVersion, setEditVersion] = useState<number>();
//插件-API详情
//Plugin-API Details
const [apiInfo, setApiInfo] = useState<PluginAPIInfo>();
const [debugApiInfo, setDebugApiInfo] = useState<PluginAPIInfo>();
const [loading, setLoading] = useState<boolean>(true);
@ -104,7 +104,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
});
};
// 重置 request 参数
// Reset request parameters
const resetRequestParams = (data: PluginAPIInfo) => {
const requestParams = cloneDeep(data.request_params as APIParameter[]);
if (
@ -120,7 +120,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
return requestParams;
};
// 设置接口信息(回显和置空)
// Set interface information (echo and empty)
const handleInit = async (useloading = false) => {
setApiInfo({
...apiInfo,
@ -140,12 +140,12 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
if (api_info.length > 0) {
const apiInfoTemp = api_info.length > 0 ? api_info[0] : {};
// debug 的数据 如果有 example 需要回显 入参数据额外处理
// Debug data, if there is an example, the imported parameter data needs to be echoed for additional processing
setDebugApiInfo({
...apiInfoTemp,
request_params: resetRequestParams(apiInfoTemp),
});
// 给对象增加层级标识
// Adding hierarchical identifiers to objects
addDepthAndValue(apiInfoTemp.request_params);
addDepthAndValue(apiInfoTemp.response_params);
setApiInfo(apiInfoTemp);
@ -170,7 +170,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
useloading && setLoading(false);
};
// 1.基本信息
// 1. Basic information
const {
isBaseInfoDisabled,
header: baseInfoHeader,
@ -190,7 +190,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
renderDescComponent,
});
// 2 更多设置
// 2 more settings
const {
isBaseMoreDisabled,
header: baseMoreHeader,
@ -211,7 +211,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
onSuccess: handleSuccess,
});
// 3.设置 request
// 3. Set request
const {
isRequestParamsDisabled,
itemKey: requestItemKey,
@ -233,7 +233,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
renderParamsComponent,
});
// 4.设置 response
// 4. Set up the response
const {
isResponseParamsDisabled,
itemKey: responseItemKey,
@ -298,7 +298,7 @@ export const ToolDetailPage: FC<ToolDetailPageProps> = ({
};
}, []);
// 预览状态解锁,如果有一步为编辑态,则不解锁
// The preview state is unlocked. If there is an edit state, it will not be unlocked.
useUpdateEffect(() => {
if (
!isBaseInfoDisabled ||

View File

@ -69,7 +69,7 @@ const ToolHeader: FC<ToolHeaderProps> = ({
unlockPlugin();
};
// 管理模拟集
// management simulation set
const handleManageMockset = () => {
resourceNavigate.mocksetList?.(tool_id);
};
@ -119,7 +119,7 @@ const ToolHeader: FC<ToolHeaderProps> = ({
/>
<span className={s.title}>{I18n.t('plugin_edit_tool_title')}</span>
<OauthButtonAction />
{/* 即将支持,敬请期待 */}
{/* Support soon, so stay tuned. */}
{FLAGS['bot.devops.plugin_mockset'] ? (
<Tooltip
style={{ display: mocksetDisabled ? 'block' : 'none' }}

View File

@ -54,12 +54,12 @@ export const useContentBaseMore = ({
editVersion,
onSuccess,
}: UseContentBaseInfoProps) => {
// 是否显示安全检查失败信息
// Is the security check failure message displayed?
const [showSecurityCheckFailedMsg, setShowSecurityCheckFailedMsg] =
useState(false);
const [isBaseMoreDisabled, setIsBaseMoreDisabled] = useState(true);
// 基本信息
// Basic information
const { baseInfoNode, submitBaseInfo } = useBaseMore({
pluginId: plugin_id || '',
pluginMeta: pluginInfo?.meta_info || {},
@ -101,7 +101,7 @@ export const useContentBaseMore = ({
onClick={async e => {
e.stopPropagation();
const status = await submitBaseInfo();
// 更新成功后进入下一步
// After the update is successful, proceed to the next step
if (status) {
handleInit();
}

View File

@ -48,12 +48,12 @@ export const useContentBaseInfo = ({
editVersion,
renderDescComponent,
}: UseContentBaseInfoProps) => {
// 是否显示安全检查失败信息
// Is the security check failure message displayed?
const [showSecurityCheckFailedMsg, setShowSecurityCheckFailedMsg] =
useState(false);
const [isBaseInfoDisabled, setIsBaseInfoDisabled] = useState(true);
// 基本信息
// Basic information
const { baseInfoNode, submitBaseInfo } = useBaseInfo({
pluginId: plugin_id || '',
apiId: tool_id,
@ -93,7 +93,7 @@ export const useContentBaseInfo = ({
onClick={async e => {
e.stopPropagation();
const status = await submitBaseInfo();
// 更新成功后进入下一步
// After the update is successful, proceed to the next step
if (status) {
handleInit();
}

View File

@ -77,7 +77,7 @@ export const useContentDebug = ({
debugApiInfo && tool_id ? (
<Debug
pluginType={pluginInfo?.plugin_type}
disabled={false} // 是否可调试
disabled={false} // Is it debuggable?
setDebugStatus={setDebugStatus}
pluginId={String(plugin_id)}
apiId={String(tool_id)}
@ -113,7 +113,7 @@ export const useContentDebug = ({
>
<Debug
pluginType={pluginInfo?.plugin_type}
disabled={false} // 是否可调试
disabled={false} // Is it debuggable?
setDebugStatus={setDebugStatus}
pluginId={String(plugin_id)}
apiId={String(tool_id)}

View File

@ -58,11 +58,11 @@ export const useContentRequest = ({
onSuccess,
renderParamsComponent,
}: UseContentRequestProps) => {
// 是否显示安全检查失败信息
// Is the security check failure message displayed?
const [showSecurityCheckFailedMsg, setShowSecurityCheckFailedMsg] =
useState(false);
const [isRequestParamsDisabled, setIsRequestParamsDisabled] = useState(true);
// 设置请求参数
// Set request parameters
const { requestParamsNode, submitRequestParams, nlTool } = useRequestParams({
apiInfo,
pluginId: plugin_id || '',
@ -107,7 +107,7 @@ export const useContentRequest = ({
onClick={async e => {
e.stopPropagation();
const status = await submitRequestParams();
// 更新成功后进入下一步
// After the update is successful, proceed to the next step
if (status) {
handleInit();
setIsRequestParamsDisabled(true);

View File

@ -66,12 +66,12 @@ export const useContentResponse = ({
onSuccess,
renderParamsComponent,
}: UseContentResponseProps) => {
// 是否显示安全检查失败信息
// Is the security check failure message displayed?
const [showSecurityCheckFailedMsg, setShowSecurityCheckFailedMsg] =
useState(false);
const [isResponseParamsDisabled, setIsResponseParamsDisabled] =
useState(true);
// 第三步设置相应参数的hooks组件
// The third step is to set the corresponding parameters of the hooks component
const { responseParamsNode, submitResponseParams, extra } = useResponseParams(
{
apiInfo,
@ -94,7 +94,7 @@ export const useContentResponse = ({
},
);
// 处理 debug 时 example数据先显示后隐藏的问题
// When dealing with debugging, the example data is displayed first and then hidden
useEffect(() => {
if (!isResponseParamsDisabled) {
setDebugApiInfo({
@ -133,7 +133,7 @@ export const useContentResponse = ({
onClick={async e => {
e.stopPropagation();
const status = await submitResponseParams();
// 更新成功后进入下一步
// After the update is successful, proceed to the next step
if (status) {
handleInit();
setIsResponseParamsDisabled(true);

View File

@ -78,8 +78,8 @@ const useAuthForApiTool = () => {
return {
canEdit,
needAuth, // 需要 auth 授权
isHasAuth, // 是否完成了授权
needAuth, // Requires auth authorization
isHasAuth, // Has the authorization been completed?
doCancelOauth,
isUpdateLoading,
doOauth,

View File

@ -42,7 +42,7 @@
& svg {
width: 16px;
height: 16px;
/* stylelint-disable-next-line declaration-no-important -- 覆盖icon颜色 */
/* stylelint-disable-next-line declaration-no-important -- Override icon color */
color: var(--semi-color-text-2) !important;
}
}

View File

@ -66,9 +66,9 @@ enum PageSource {
}
enum PageMode {
/** 整页 UI类似全覆盖浮层 */
/** Full page UI similar to full coverage floating layer */
FULL_PAGE = 'full_page',
/** 嵌入(左侧有菜单栏) */
/** Embed (with menu bar on the left) */
EMBED = 'embed',
}
@ -87,16 +87,16 @@ const MockSetDetail: FC<{
[],
);
const routeResponse = usePageJumpResponse(PageType.PLUGIN_MOCK_DATA);
// API 详情
// API Details
const [apiInfo, setApiInfo] = useState<PluginAPIInfo>({
name: routeResponse?.toolName,
});
// mock set 详情
// Mock set details
const [mockSetInfo, setMockSetInfo] = useState<MockSet>({
id: mocksetID,
name: routeResponse?.mockSetName,
});
// API 对应 schema
// API correspondence schema
const [toolSchema, setToolSchema] = useState<string>('');
const [perm, setPerm] = useState<{
readOnly: boolean;
@ -109,9 +109,9 @@ const MockSetDetail: FC<{
const listRef = useRef<MockDataListActions>(null);
const contentEleRef = useRef<HTMLDivElement>(null);
// 页面展示模式
// page display mode
const pageMode = params.hideMenu ? PageMode.FULL_PAGE : PageMode.EMBED;
// 页面来源
// page source
const fromSource = routeResponse?.fromSource
? (routeResponse.fromSource as PageSource)
: PageSource.FROM_MOCK_SET;
@ -142,7 +142,7 @@ const MockSetDetail: FC<{
[toolID, pluginID],
);
// 获取当前 tool 信息
// Get current tool information
const getPluginToolInfo = async () => {
try {
const { api_info = [] } = await PluginDevelopApi.GetPluginAPIs(
@ -164,7 +164,7 @@ const MockSetDetail: FC<{
}
};
// 获取当前 mock set 信息
// Get current mock set information
const getMockSetInfo = async () => {
if (!mocksetID) {
return;

View File

@ -65,7 +65,7 @@ import { getDisplayCols } from './get-col';
import styles from './index.module.less';
interface ListParams {
pageNo?: number; // 用于前端计算数量
pageNo?: number; // Quantity for front-end computing
pageSize?: number;
pageToken?: string;
order?: {
@ -80,13 +80,13 @@ const TOOL_NOT_FOUND_CODE = '600303108';
const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
const resourceNavigate = usePluginNavigate();
// user信息
// User information
const userInfo = userStoreService.useUserInfo();
// 路由信息
// routing information
const [params, setParams] = useState<ListParams>({
//请求参数
//request parameters
pageSize: PAGE_SIZE,
pageNo: 1,
});
@ -101,11 +101,11 @@ const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
})),
);
// space信息
// Space information
const space = useSpace(spaceID);
const isPersonal = space?.space_type === SpaceType.Personal;
// API 详情
// API Details
const [apiInfo, setApiInfo] = useState<PluginAPIInfo>();
const [showCreateModal, setShowCreateModal] = useState(false);
@ -118,7 +118,7 @@ const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
const [editDisabled, setEditDisabled] = useState(false);
// 后端需要的mock上下文信息
// The mock context information required by the backend
const ctxInfo = {
bizCtx: {
trafficScene: TrafficScene.Undefined,
@ -216,7 +216,7 @@ const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
}
};
// 获取当前tool信息
// Get current tool information
const getPluginToolInfo = async () => {
try {
const { api_info = [] } = await PluginDevelopApi.GetPluginAPIs({
@ -351,13 +351,13 @@ const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
if (!editDisabled) {
handleEdit(record);
}
}, // 点击行
}, // Click line
}),
onChange: e => {
if (e.sorter?.sortOrder) {
tableRef.current?.reset();
//时间排序
//chronological sorting
setParams(p => ({
...p,
pageSize: PAGE_SIZE,
@ -410,7 +410,7 @@ const MockSetList: FC<{ toolID: string }> = ({ toolID }) => {
></MockSetEditModal>
) : null}
{
// 删除弹窗
// Delete pop-up window
deleteMockSet ? (
<MockSetDeleteModal
visible={!!deleteMockSet}

View File

@ -35,8 +35,8 @@ interface UseCreateToolProps {
plugin_id: string;
onClickWrapper?: (fn: () => void) => () => Promise<void>;
/**
*
* @returns {boolean | void} false时将阻止后续动作
* The callback function before clicking the Create Tool button
* @Returns {boolean | void} returns false to block subsequent actions
*/
onBeforeClick?: () => void;
disabled: boolean;
@ -151,7 +151,7 @@ export const useCreateTool = ({
};
/**
* @description
* @description creation tool
*/
export const CreateTool: FC<CreateToolProps> = props => {
const { content } = useCreateTool({

View File

@ -155,7 +155,7 @@ const PluginDetailPage = ({
);
const [params, setParams] = useState<GetPluginAPIsRequest>({
//请求参数
//request parameters
page: 1,
size: 10,
plugin_id: pluginID,
@ -236,7 +236,7 @@ const PluginDetailPage = ({
const dataSource = data?.api_info;
/** 不再提示 */
/** no longer prompt */
const noTips = async () => {
const res = await PluginDevelopApi.NoUpdatedPrompt({
plugin_id: pluginID,
@ -248,7 +248,7 @@ const PluginDetailPage = ({
const checkPublish = async () => {
if (!pluginInfo?.published) {
//未发布过点击直接发布
//It has not been published. Click to publish directly.
setPublishPopShow(true);
return;
}
@ -264,7 +264,7 @@ const PluginDetailPage = ({
setPublishPopData(res);
setShowPublishCheckPop(true);
} else {
//没有修改api直接发布
//Publish directly without modifying the api
setPublishPopShow(true);
}
};
@ -308,14 +308,14 @@ const PluginDetailPage = ({
onStatusChange?.('error');
}
}, [initSuccessed]);
// 区分ide的跳转
// Differentiate IDE jumps
const handleIdeJump = (
initialAction = InitialAction.DEFAULT,
toolId = '',
) => {
// ide 逻辑
// IDE logic
if (isCloudIDEPlugin) {
// 改变路由地址 返回的时候会清掉
// Change the routing address and it will be cleared when returning.
preloadIDE?.handleShowIde({ initialAction, toolId });
} else if (toolId) {
resourceNavigate.tool?.(toolId);
@ -337,7 +337,7 @@ const PluginDetailPage = ({
canEdit ? { mode: 'preview' } : {},
);
}
}, // 点击行
}, // Click line
});
const { exampleNode, openExample } = useEditExample({
@ -445,7 +445,7 @@ const PluginDetailPage = ({
) : null}
<Layout.Content className={s['layout-content']}>
{/* 已发布且有更新展示 */}
{/* Published and updated */}
{pluginInfo?.status &&
pluginInfo?.published &&
canEdit &&
@ -470,7 +470,7 @@ const PluginDetailPage = ({
}
/>
) : null}
{/* plugin简介 */}
{/* Plugin Introduction */}
{pluginInfo ? (
<PluginHeader
pluginInfo={pluginInfo}
@ -502,7 +502,7 @@ const PluginDetailPage = ({
onBeforeClick={() => {
setShowDropDownItem(undefined);
if (isCloudIDEPlugin) {
// 改变路由地址 返回的时候会清掉
// Change the routing address and it will be cleared when returning.
preloadIDE?.handleShowIde({
initialAction: InitialAction.CREATE_TOOL,
toolId: '',
@ -529,7 +529,7 @@ const PluginDetailPage = ({
{I18n.t('import')}
</Button>
) : null}
{/* ! 发布按钮 */}
{/* ! Post button */}
{isRenderIDEPublishButton ? (
<Tooltip
position="left"
@ -598,7 +598,7 @@ const PluginDetailPage = ({
}
/>
) : null}
{/* 工具列表表格 */}
{/* Tool List Form */}
{!!dataSource?.length && (
<div className="mb-[24px] mt-[36px] text-[18px] weight-[600]">
{I18n.t('plugin_api_list_table_name')}
@ -615,7 +615,7 @@ const PluginDetailPage = ({
onRow,
onChange: e => {
if (e.sorter?.sortOrder) {
//时间排序
//chronological sorting
setParams(p => ({
...p,
page: 1,
@ -634,7 +634,7 @@ const PluginDetailPage = ({
btnText: canEdit ? createToolText : undefined,
btnOnClick: () => {
if (isCloudIDEPlugin) {
// 改变路由地址 返回的时候会清掉
// Change the routing address and it will be cleared when returning.
preloadIDE?.handleShowIde({
initialAction: InitialAction.CREATE_TOOL,
toolId: '',

View File

@ -51,7 +51,7 @@ export interface PluginModalContentProps extends PluginModalModeProps {
setQuery: (value: Partial<PluginQuery>, refreshPage?: boolean) => void;
}
export type PluginModalContentListItem = PluginInfoForPlayground & {
// 当前数据属于列表的第几页
// The current data belongs to the page of the list
belong_page?: number;
};
@ -99,7 +99,7 @@ export const PluginModalContent: FC<PluginModalContentProps> = ({
onCopyPluginCallback,
clickProjectPluginCallback,
}) => {
// 状态hook
// Status hook
const {
type,
mineActive,
@ -112,9 +112,9 @@ export const PluginModalContent: FC<PluginModalContentProps> = ({
pluginType,
} = query;
const id = useSpaceStore(store => store.space.id);
// scroll的container
// Scroll container
const scrollContainerRef = useRef<HTMLDivElement | null>(null);
// 当前active的key
// Currently active key
const [activeKey, setActivekey] = useState<string | string[] | undefined>([]);
const refInfiniteScroll = useRef<InfiniteListRef>(null);
const {
@ -140,10 +140,10 @@ export const PluginModalContent: FC<PluginModalContentProps> = ({
nodes: state.nodes,
})),
);
// 首次effect不执行这个是切换状态的effect
// The first effect is not executed, this is the effect of switching the state
useUpdateEffect(() => {
scroll2Top(); // 当筛选项改变时,回到顶部
// 只要是query中非page改变就执行此effect
scroll2Top(); // When the filter item changes, return to the top
// Perform this effect whenever a non-page change is made in the query
}, []);
return (
<UICompositionModalMain>

View File

@ -53,24 +53,24 @@ export interface UsePluginModalPartsProp extends PluginModalModeProps {
}
/**
*
* @param from
* @param spaceType
* @returns
* Get initialization type
* @Param from source
* @param spaceType
* @Returns initialization type
*/
const getInitType = (from?: From, spaceType?: SpaceType) => {
// 项目workflow引用插件默认选中项目插件
// Project workflow reference plug-in, the project plug-in is selected by default
if (from === From.ProjectWorkflow) {
return '';
}
if (from !== From.ProjectIde || !spaceType || !from) {
return '';
}
// projectIDE下并且是个人空间选中Mine
// Under projectIDE, and it is personal space, select Mine.
if (spaceType === SpaceType.Personal) {
return PluginFilterType.Mine;
}
// projectIDE下并且是团队空间选中Team
// Under projectIDE, and is a team space, select Team
if (spaceType === SpaceType.Team && from === From.ProjectIde) {
return PluginFilterType.Team;
}
@ -94,7 +94,7 @@ export const usePluginModalParts = ({
hideCreateBtn,
initQuery,
}: UsePluginModalPartsProp) => {
// 获取devId
// Get devId
const userInfo = userStoreService.useUserInfo();
const spaceType = useSpaceStore(store => store.space.space_type);
const [query, setQuery] = useState<PluginQuery>({
@ -103,14 +103,14 @@ export const usePluginModalParts = ({
devId: userInfo?.user_id_str || '',
search: '',
page: DEFAULT_PAGE,
// 项目IDE插件仅展示我的插件
// Project IDE plugins only show my plugins
type: initQuery?.type ?? getInitType(from, spaceType),
orderBy: OrderBy.CreateTime,
orderByPublic: SortType.Heat,
orderByFavorite: SortType.Newest,
mineActive: MineActiveEnum.All,
isOfficial: initQuery?.isOfficial ?? undefined,
// project workflow添加插件只展示云插件
// Add plugins to project workflow, only show cloud plugins
pluginType:
from === From.ProjectWorkflow ? PluginType.CLoudPlugin : undefined,
});

View File

@ -85,11 +85,11 @@ export const PluginModalSider: FC<PluginModalSiderProp> = ({
maxLength={MAX_SEARCH_LENGTH}
onSearch={search => {
if (!search) {
// 如果search清空了那么立即更新query
// If the search is empty, update the query immediately
cancel();
updateSearchQuery(search);
} else {
// 如果search有值那么防抖更新
// If search has a value, then anti-shake update
debounceChangeSearch(search);
}
}}
@ -102,7 +102,7 @@ export const PluginModalSider: FC<PluginModalSiderProp> = ({
className={s.addbtn}
theme="solid"
onClick={() => {
// TODO: 其他场景应该也统一创建方式如果创建成功回调存在则打开插件modal否则打开新tab
// TODO: Other scenes should also be created in a unified way. If the creation success callback exists, open the plugin modal, otherwise open a new tab.
if (
onCreateSuccess &&
(from === From.ProjectIde || from === From.ProjectWorkflow)

View File

@ -169,7 +169,7 @@ export function useInfiniteScrollCacheLoad<
] = true;
});
//数据去重
//Data deduplicated
const uniqList = (list || []).filter(item => {
const pluginId = (item as unknown as { pluginInfo: { id: string } })
?.pluginInfo?.id;

Some files were not shown because too many files have changed in this diff Show More