chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -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',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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 => {
|
||||
* }
|
||||
* }
|
||||
*```
|
||||
* 如果不采用下面这个判断,函数判断将得到3,实际应该为5. 类似的还有
|
||||
* 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' ||
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(() => ([])))',
|
||||
|
||||
@@ -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
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ enum Gender {
|
||||
}
|
||||
|
||||
// const map<Gender, string> genderMap = {
|
||||
// Gender.Male: '男性',
|
||||
// Gender.Female: '女性',
|
||||
// Gender. Male: 'Male',
|
||||
// Gender. Female: 'Female',
|
||||
// }
|
||||
|
||||
union FuncRequest {
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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[]>;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -26,7 +26,7 @@ interface IPops {
|
||||
filter: Filter;
|
||||
}
|
||||
|
||||
// 忽略 struct 中的字段
|
||||
// Ignore fields in struct
|
||||
export class IgnoreStructFiledPlugin {
|
||||
private filter: Filter;
|
||||
constructor({ filter }: IPops) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user