@nest-boot/eslint-plugin 7.0.4 → 7.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/dist/rules/graphql/graphql-field-config-from-types.d.ts +3 -1
  4. package/dist/rules/graphql/graphql-field-config-from-types.js +36 -36
  5. package/dist/rules/graphql/graphql-field-config-from-types.js.map +1 -1
  6. package/dist/rules/graphql/graphql-field-definite-assignment.d.ts +3 -1
  7. package/dist/rules/graphql/graphql-field-definite-assignment.js +13 -13
  8. package/dist/rules/graphql/graphql-field-definite-assignment.js.map +1 -1
  9. package/dist/rules/import/import-bullmq.d.ts +3 -1
  10. package/dist/rules/import/import-bullmq.js +4 -4
  11. package/dist/rules/import/import-bullmq.js.map +1 -1
  12. package/dist/rules/import/import-graphql.d.ts +3 -1
  13. package/dist/rules/import/import-graphql.js +4 -4
  14. package/dist/rules/import/import-graphql.js.map +1 -1
  15. package/dist/rules/import/import-mikro-orm.d.ts +3 -1
  16. package/dist/rules/import/import-mikro-orm.js +4 -4
  17. package/dist/rules/import/import-mikro-orm.js.map +1 -1
  18. package/dist/rules/index.d.ts +21 -7
  19. package/dist/rules/mikro-orm/entity-field-definite-assignment.d.ts +3 -1
  20. package/dist/rules/mikro-orm/entity-field-definite-assignment.js +10 -10
  21. package/dist/rules/mikro-orm/entity-field-definite-assignment.js.map +1 -1
  22. package/dist/rules/mikro-orm/entity-property-config-from-types.d.ts +3 -1
  23. package/dist/rules/mikro-orm/entity-property-config-from-types.js +105 -105
  24. package/dist/rules/mikro-orm/entity-property-config-from-types.js.map +1 -1
  25. package/dist/tsconfig.build.tsbuildinfo +1 -1
  26. package/dist/utils/createRule.d.ts +3 -1
  27. package/dist/utils/decorators.d.ts +16 -16
  28. package/dist/utils/decorators.js +16 -16
  29. package/package.json +12 -7
  30. package/src/rules/graphql/graphql-field-config-from-types.spec.ts +18 -18
  31. package/src/rules/graphql/graphql-field-config-from-types.ts +37 -37
  32. package/src/rules/graphql/graphql-field-definite-assignment.spec.ts +11 -11
  33. package/src/rules/graphql/graphql-field-definite-assignment.ts +13 -13
  34. package/src/rules/import/import-bullmq.spec.ts +9 -9
  35. package/src/rules/import/import-bullmq.ts +5 -4
  36. package/src/rules/import/import-graphql.spec.ts +8 -8
  37. package/src/rules/import/import-graphql.ts +4 -4
  38. package/src/rules/import/import-mikro-orm.spec.ts +8 -8
  39. package/src/rules/import/import-mikro-orm.ts +4 -4
  40. package/src/rules/mikro-orm/entity-field-definite-assignment.spec.ts +18 -18
  41. package/src/rules/mikro-orm/entity-field-definite-assignment.ts +10 -10
  42. package/src/rules/mikro-orm/entity-property-config-from-types.spec.ts +22 -22
  43. package/src/rules/mikro-orm/entity-property-config-from-types.ts +110 -109
  44. package/src/utils/decorators.ts +16 -16
@@ -9,7 +9,7 @@ import * as ts from "typescript";
9
9
  import { createRule } from "../../utils/createRule";
10
10
  import { hasClassDecorator } from "../../utils/decorators";
11
11
 
12
- // 自定义 Fix 对象类型,用于延迟应用修复
12
+ // Custom Fix object type for deferred fix application
13
13
  interface CustomFix {
14
14
  type: "insert" | "replace";
15
15
  range: readonly [number, number];
@@ -20,9 +20,9 @@ interface TypeInfo {
20
20
  typeName: string | null;
21
21
  isArray: boolean;
22
22
  isNullable: boolean;
23
- isEnum: boolean; // 是否是枚举类型
24
- propertyType: string | null; // MikroORM 类型如 t.text, t.bigint
25
- arrayElementTypeName?: string | null; // 数组元素的类型名称(用于特殊验证)
23
+ isEnum: boolean; // Whether the type is an enum
24
+ propertyType: string | null; // MikroORM type such as t.text, t.bigint, etc.
25
+ arrayElementTypeName?: string | null; // Type name of array elements (for special validation)
26
26
  }
27
27
 
28
28
  export default createRule<
@@ -38,20 +38,21 @@ export default createRule<
38
38
  type: "problem",
39
39
  docs: {
40
40
  description:
41
- "根据 TypeScript 类型自动生成或修正 @Property 装饰器的类型与 nullable 配置(支持数组),以及 @Enum 装饰器的 nullable 配置。检查有初始化值的属性是否使用 Opt<T> 类型。",
41
+ "Automatically generate or fix @Property decorator type and nullable configuration based on TypeScript types (with array support), as well as @Enum decorator nullable configuration. Checks whether properties with initializers use the Opt<T> type.",
42
42
  },
43
43
  fixable: "code",
44
44
  schema: [],
45
45
  messages: {
46
46
  alignPropertyDecoratorWithTsType:
47
- "@Property 装饰器应与 TypeScript 类型保持一致(类型与 nullable)。",
47
+ "@Property decorator should align with the TypeScript type (type and nullable).",
48
48
  removePropertyDecorator:
49
- "属性带有 @{{decoratorName}} 装饰器,应移除 @Property 装饰器。",
50
- useEnumDecorator: "枚举类型应使用 @Enum 装饰器而不是 @Property 装饰器。",
49
+ "Property has a @{{decoratorName}} decorator, @Property decorator should be removed.",
50
+ useEnumDecorator:
51
+ "Enum types should use @Enum decorator instead of @Property decorator.",
51
52
  useOptTypeForInitializedProperty:
52
- "有非 null 初始化值的属性应使用 Opt<T> 类型包装。",
53
+ "Properties with non-null initializers should use the Opt<T> type wrapper.",
53
54
  removeOptTypeForNonInitializedProperty:
54
- "没有初始化值或初始化为 null 的属性不应使用 Opt<T> 类型包装。",
55
+ "Properties without initializers or initialized to null should not use the Opt<T> type wrapper.",
55
56
  },
56
57
  },
57
58
  defaultOptions: [],
@@ -60,18 +61,18 @@ export default createRule<
60
61
  const parserServices = ESLintUtils.getParserServices(context);
61
62
  const checker = parserServices.program.getTypeChecker();
62
63
 
63
- // 检查是否为枚举类型
64
+ // Check if the type is an enum
64
65
  const isEnumType = (node: TSESTree.Node): boolean => {
65
66
  try {
66
67
  const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
67
68
  const type = checker.getTypeAtLocation(tsNode);
68
69
 
69
- // 检查是否是枚举类型
70
+ // Check if it is an enum type
70
71
  if (type.symbol.flags & ts.SymbolFlags.Enum) {
71
72
  return true;
72
73
  }
73
74
 
74
- // 检查联合类型中的每个成员
75
+ // Check each member in a union type
75
76
  if (type.isUnion()) {
76
77
  return type.types.some(
77
78
  (t) =>
@@ -92,15 +93,15 @@ export default createRule<
92
93
  switch (typeName) {
93
94
  case "String":
94
95
  case "string":
95
- return "t.string"; // 默认使用 t.string
96
+ return "t.string"; // Default to t.string
96
97
  case "Number":
97
98
  case "number":
98
- return "t.float"; // 默认使用 t.float
99
+ return "t.float"; // Default to t.float
99
100
  case "Boolean":
100
101
  case "boolean":
101
- return "t.boolean"; // 默认使用 t.boolean
102
+ return "t.boolean"; // Default to t.boolean
102
103
  case "Date":
103
- return "t.datetime"; // 默认使用 t.datetime
104
+ return "t.datetime"; // Default to t.datetime
104
105
  case "GraphQLJSONObject":
105
106
  case "Record":
106
107
  return "t.json";
@@ -112,7 +113,7 @@ export default createRule<
112
113
  const isValidStringType = (typeConfig: string | null): boolean => {
113
114
  if (!typeConfig) return false;
114
115
 
115
- // 接受 t.string, t.text, t.uuid, t.decimal, t.bigint
116
+ // Accept t.string, t.text, t.uuid, t.decimal, t.bigint
116
117
  if (
117
118
  typeConfig === "t.string" ||
118
119
  typeConfig === "t.text" ||
@@ -123,25 +124,25 @@ export default createRule<
123
124
  return true;
124
125
  }
125
126
 
126
- // 接受 DecimalType(类引用,不带参数)
127
+ // Accept DecimalType (class reference, without arguments)
127
128
  if (typeConfig === "DecimalType") {
128
129
  return true;
129
130
  }
130
131
 
131
- // 接受 new DecimalType('string') new BigIntType('string')
132
- // 但排除 new BigIntType('number')
132
+ // Accept new DecimalType('string') and new BigIntType('string')
133
+ // but exclude new BigIntType('number')
133
134
  if (
134
135
  typeConfig.includes("DecimalType") ||
135
136
  typeConfig.includes("BigIntType")
136
137
  ) {
137
- // 如果是 new BigIntType('number'),则无效
138
+ // If it's new BigIntType('number'), it's invalid
138
139
  if (
139
140
  typeConfig.includes("BigIntType") &&
140
141
  (typeConfig.includes("'number'") || typeConfig.includes('"number"'))
141
142
  ) {
142
143
  return false;
143
144
  }
144
- // 其他情况(包括 new XXXType('string') DecimalType)都有效
145
+ // Other cases (including new XXXType('string') and DecimalType) are valid
145
146
  return true;
146
147
  }
147
148
 
@@ -151,7 +152,7 @@ export default createRule<
151
152
  const isValidNumberType = (typeConfig: string | null): boolean => {
152
153
  if (!typeConfig) return false;
153
154
 
154
- // 接受 t.integer, t.float, t.double, t.decimal
155
+ // Accept t.integer, t.float, t.double, t.decimal
155
156
  if (
156
157
  typeConfig === "t.integer" ||
157
158
  typeConfig === "t.float" ||
@@ -161,25 +162,25 @@ export default createRule<
161
162
  return true;
162
163
  }
163
164
 
164
- // 接受 BigIntType DecimalType(类引用,不带参数)
165
+ // Accept BigIntType and DecimalType (class reference, without arguments)
165
166
  if (typeConfig === "BigIntType" || typeConfig === "DecimalType") {
166
167
  return true;
167
168
  }
168
169
 
169
- // 接受 new DecimalType('number') new BigIntType('number')
170
- // 但排除 new XXXType('string')
170
+ // Accept new DecimalType('number') and new BigIntType('number')
171
+ // but exclude new XXXType('string')
171
172
  if (
172
173
  typeConfig.includes("DecimalType") ||
173
174
  typeConfig.includes("BigIntType")
174
175
  ) {
175
- // 如果包含 'string',则对 number 类型无效
176
+ // If it contains 'string', it's invalid for number type
176
177
  if (
177
178
  typeConfig.includes("'string'") ||
178
179
  typeConfig.includes('"string"')
179
180
  ) {
180
181
  return false;
181
182
  }
182
- // 其他情况(包括 new XXXType('number'))都有效
183
+ // Other cases (including new XXXType('number')) are valid
183
184
  return true;
184
185
  }
185
186
 
@@ -189,17 +190,17 @@ export default createRule<
189
190
  const isValidNumberArrayType = (typeConfig: string | null): boolean => {
190
191
  if (!typeConfig) return false;
191
192
 
192
- // 接受 t.array(默认)
193
+ // Accept t.array (default)
193
194
  if (typeConfig === "t.array") {
194
195
  return true;
195
196
  }
196
197
 
197
- // 接受 VectorType(类引用)
198
+ // Accept VectorType (class reference)
198
199
  if (typeConfig === "VectorType") {
199
200
  return true;
200
201
  }
201
202
 
202
- // 接受 new VectorType(...)
203
+ // Accept new VectorType(...)
203
204
  if (typeConfig.includes("VectorType")) {
204
205
  return true;
205
206
  }
@@ -210,7 +211,7 @@ export default createRule<
210
211
  const isValidDateType = (typeConfig: string | null): boolean => {
211
212
  if (!typeConfig) return false;
212
213
 
213
- // 接受 t.datetime, t.date, t.time
214
+ // Accept t.datetime, t.date, t.time
214
215
  if (
215
216
  typeConfig === "t.datetime" ||
216
217
  typeConfig === "t.date" ||
@@ -256,7 +257,7 @@ export default createRule<
256
257
  );
257
258
  };
258
259
 
259
- // 检查类型是否被 Opt<T> 包装
260
+ // Check if the type is wrapped with Opt<T>
260
261
  const isWrappedWithOpt = (
261
262
  property: TSESTree.PropertyDefinition,
262
263
  ): boolean => {
@@ -273,13 +274,13 @@ export default createRule<
273
274
  );
274
275
  };
275
276
 
276
- // 检查是否已导入 Opt
277
+ // Check if Opt is imported
277
278
  const hasOptImport = (): boolean => {
278
279
  const program = context.sourceCode.ast;
279
280
  for (const statement of program.body) {
280
281
  if (statement.type === AST_NODE_TYPES.ImportDeclaration) {
281
282
  const importSource = statement.source.value;
282
- // 检查从 @mikro-orm/* 导入的语句
283
+ // Check imports from @mikro-orm/*
283
284
  if (
284
285
  typeof importSource === "string" &&
285
286
  importSource.startsWith("@mikro-orm/")
@@ -300,11 +301,11 @@ export default createRule<
300
301
  return false;
301
302
  };
302
303
 
303
- // 添加 Opt @mikro-orm/core 的导入
304
+ // Add Opt to the @mikro-orm/core import
304
305
  const addOptImport = (fixer: RuleFixer): RuleFix | null => {
305
306
  const program = context.sourceCode.ast;
306
307
 
307
- // 查找 @mikro-orm/core 的导入语句
308
+ // Find the @mikro-orm/core import statement
308
309
  let coreImport: TSESTree.ImportDeclaration | null = null;
309
310
 
310
311
  for (const statement of program.body) {
@@ -318,24 +319,24 @@ export default createRule<
318
319
  }
319
320
 
320
321
  if (coreImport) {
321
- // 已有 @mikro-orm/core 导入,添加 Opt 到导入列表
322
+ // Already has @mikro-orm/core import, add Opt to the import list
322
323
  const lastSpecifier =
323
324
  coreImport.specifiers[coreImport.specifiers.length - 1];
324
325
 
325
- // 检查是否是多行导入
326
+ // Check if it's a multiline import
326
327
  const importText = source.getText(coreImport);
327
328
  const isMultiline = importText.includes("\n");
328
329
 
329
330
  if (isMultiline) {
330
- // 多行导入:在最后一个导入项后添加,保持缩进
331
- const indent = " "; // 假设使用 2 个空格缩进
331
+ // Multiline import: add after the last import item, keeping indentation
332
+ const indent = " "; // Assuming 2-space indentation
332
333
  return fixer.insertTextAfter(lastSpecifier, `,\n${indent}Opt`);
333
334
  } else {
334
- // 单行导入:直接添加
335
+ // Single-line import: add directly
335
336
  return fixer.insertTextAfter(lastSpecifier, ", Opt");
336
337
  }
337
338
  } else {
338
- // 没有 @mikro-orm/core 导入,在文件开头添加新的导入语句
339
+ // No @mikro-orm/core import, add a new import statement at the top
339
340
  const firstImport = program.body.find(
340
341
  (node: TSESTree.ProgramStatement) =>
341
342
  node.type === AST_NODE_TYPES.ImportDeclaration,
@@ -363,12 +364,12 @@ export default createRule<
363
364
  ? property.typeAnnotation.typeAnnotation
364
365
  : null;
365
366
 
366
- // 可选属性(?)视为可空
367
+ // Optional property (?) is treated as nullable
367
368
  if (property.optional) {
368
369
  isNullable = true;
369
370
  }
370
371
 
371
- // 处理联合类型中的 null/undefined
372
+ // Handle null/undefined in union types
372
373
  if (baseTypeNode?.type === AST_NODE_TYPES.TSUnionType) {
373
374
  const hasNullish = baseTypeNode.types.some((t: TSESTree.TypeNode) => {
374
375
  return (
@@ -387,7 +388,7 @@ export default createRule<
387
388
  }) ?? null;
388
389
  }
389
390
 
390
- // 先解包 Ref<T> Opt<T> → T,并在内部再次处理 null/undefined
391
+ // First unwrap Ref<T> and Opt<T> → T, and handle null/undefined within
391
392
  if (
392
393
  baseTypeNode?.type === AST_NODE_TYPES.TSTypeReference &&
393
394
  baseTypeNode.typeName.type === AST_NODE_TYPES.Identifier &&
@@ -414,12 +415,12 @@ export default createRule<
414
415
  baseTypeNode = inner ?? baseTypeNode;
415
416
  }
416
417
 
417
- // 跳过 Collection<T> 类型(这些应该由 OneToMany 等装饰器处理)
418
+ // Skip Collection<T> types (these should be handled by OneToMany etc. decorators)
418
419
  if (baseTypeNode && isCollectionType(baseTypeNode)) {
419
420
  return null;
420
421
  }
421
422
 
422
- // 数组类型(T[] Array<T>)- 在解包 Opt/Ref 之后检查
423
+ // Array type (T[] or Array<T>) - checked after unwrapping Opt/Ref
423
424
  const elementTypeNode = baseTypeNode
424
425
  ? extractArrayElementType(baseTypeNode)
425
426
  : null;
@@ -430,12 +431,12 @@ export default createRule<
430
431
  const targetTypeNode: TSESTree.TypeNode | null =
431
432
  elementTypeNode ?? baseTypeNode;
432
433
 
433
- // 检查目标类型是否为枚举
434
+ // Check if target type is an enum
434
435
  if (targetTypeNode) {
435
436
  isEnum = isEnumType(targetTypeNode);
436
437
  }
437
438
 
438
- // 无显式类型时,尝试从字面量初始值推断
439
+ // When no explicit type, try to infer from literal initializer
439
440
  if (!targetTypeNode) {
440
441
  if (property.value?.type === AST_NODE_TYPES.Literal) {
441
442
  const value = property.value.value;
@@ -487,7 +488,7 @@ export default createRule<
487
488
  };
488
489
  }
489
490
 
490
- // 关键字类型
491
+ // Keyword types
491
492
  if (targetTypeNode.type === AST_NODE_TYPES.TSStringKeyword) {
492
493
  return {
493
494
  typeName: "string",
@@ -519,10 +520,10 @@ export default createRule<
519
520
  };
520
521
  }
521
522
 
522
- // 标识符(类/自定义类型)
523
+ // Identifier (class/custom type)
523
524
  const ident = getIdentifierName(targetTypeNode);
524
525
  if (ident) {
525
- // 如果是数组,自定义类型数组使用 t.json
526
+ // For arrays, custom type arrays use t.json
526
527
  if (isArray) {
527
528
  return {
528
529
  typeName: ident,
@@ -547,7 +548,7 @@ export default createRule<
547
548
  return null;
548
549
  };
549
550
 
550
- // 将类型包装为 Opt<T>
551
+ // Wrap type with Opt<T>
551
552
  const wrapWithOpt = (typeString: string): string => {
552
553
  return `Opt<${typeString}>`;
553
554
  };
@@ -577,12 +578,12 @@ export default createRule<
577
578
  ): string => {
578
579
  const options: string[] = [];
579
580
 
580
- // 如果有 propertyType 配置,添加 type
581
+ // If there is a propertyType configuration, add type
581
582
  if (info.propertyType) {
582
583
  options.push(`type: ${info.propertyType}`);
583
584
  }
584
585
 
585
- // 添加其他属性(保持原有顺序)
586
+ // Add other properties (keeping original order)
586
587
  for (const prop of otherProps) {
587
588
  options.push(`${prop.key}: ${prop.value}`);
588
589
  }
@@ -628,10 +629,10 @@ export default createRule<
628
629
  ) => {
629
630
  const fixes: CustomFix[] = [];
630
631
 
631
- // 如果当前已经有有效的配置,保留它而不是替换成默认值
632
+ // If current config already has a valid value, keep it instead of replacing with default
632
633
  const finalInfo = { ...info };
633
634
 
634
- // PrimaryKey number 类型默认使用 t.integer
635
+ // PrimaryKey number type defaults to t.integer
635
636
  if (
636
637
  decoratorName === "PrimaryKey" &&
637
638
  finalInfo.propertyType === "t.float"
@@ -643,31 +644,31 @@ export default createRule<
643
644
  info.propertyType === "t.string" &&
644
645
  isValidStringType(currentConfig.type)
645
646
  ) {
646
- // 保留有效的 string 类型配置
647
+ // Keep valid string type config
647
648
  finalInfo.propertyType = currentConfig.type;
648
649
  } else if (
649
650
  (info.propertyType === "t.float" ||
650
651
  info.propertyType === "t.integer") &&
651
652
  isValidNumberType(currentConfig.type)
652
653
  ) {
653
- // 保留有效的 number 类型配置
654
+ // Keep valid number type config
654
655
  finalInfo.propertyType = currentConfig.type;
655
656
  } else if (
656
657
  info.propertyType === "t.datetime" &&
657
658
  isValidDateType(currentConfig.type)
658
659
  ) {
659
- // 保留有效的 Date 类型配置
660
+ // Keep valid Date type config
660
661
  finalInfo.propertyType = currentConfig.type;
661
662
  } else if (
662
663
  info.isArray &&
663
664
  info.arrayElementTypeName === "number" &&
664
665
  isValidNumberArrayType(currentConfig.type)
665
666
  ) {
666
- // 保留有效的 number[] 类型配置(VectorType
667
+ // Keep valid number[] type config (VectorType)
667
668
  finalInfo.propertyType = currentConfig.type;
668
669
  }
669
670
 
670
- // 保留其他属性配置
671
+ // Keep other property configs
671
672
  const newDecoratorText = buildPropertyDecorator(
672
673
  finalInfo,
673
674
  currentConfig.otherProps,
@@ -736,7 +737,7 @@ export default createRule<
736
737
  nullable = true;
737
738
  }
738
739
  } else {
739
- // 保留其他所有属性
740
+ // Keep all other properties
740
741
  otherProps.push({
741
742
  key: prop.key.name,
742
743
  value: source.getText(prop.value),
@@ -789,23 +790,23 @@ export default createRule<
789
790
  return { items, nullable };
790
791
  };
791
792
 
792
- // 检查文件中是否使用了 Opt 类型但没有导入
793
+ // Check if the file uses the Opt type but hasn't imported it
793
794
  const checkOptUsageWithoutImport = (node: TSESTree.ClassDeclaration) => {
794
795
  let usesOpt = false;
795
796
 
796
- // 遍历所有成员,检查是否有使用 Opt<T> 的类型注解
797
+ // Iterate through all members to check for Opt<T> type annotations
797
798
  node.body.body.forEach((member: TSESTree.ClassElement) => {
798
799
  if (member.type !== AST_NODE_TYPES.PropertyDefinition) return;
799
800
 
800
801
  const typeAnnotation = member.typeAnnotation?.typeAnnotation;
801
802
  if (!typeAnnotation) return;
802
803
 
803
- // 递归检查类型节点中是否包含 Opt
804
+ // Recursively check if the type node contains Opt
804
805
  const containsOpt = (typeNode: TSESTree.TypeNode): boolean => {
805
806
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
806
807
  if (!typeNode) return false;
807
808
 
808
- // 检查是否是 Opt<T>
809
+ // Check if it's Opt<T>
809
810
  if (
810
811
  typeNode.type === AST_NODE_TYPES.TSTypeReference &&
811
812
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
@@ -815,14 +816,14 @@ export default createRule<
815
816
  return true;
816
817
  }
817
818
 
818
- // 递归检查联合类型
819
+ // Recursively check union types
819
820
  if (typeNode.type === AST_NODE_TYPES.TSUnionType) {
820
821
  return typeNode.types.some((t: TSESTree.TypeNode) =>
821
822
  containsOpt(t),
822
823
  );
823
824
  }
824
825
 
825
- // 递归检查类型参数
826
+ // Recursively check type parameters
826
827
  if (
827
828
  typeNode.type === AST_NODE_TYPES.TSTypeReference &&
828
829
  typeNode.typeArguments?.params
@@ -832,7 +833,7 @@ export default createRule<
832
833
  );
833
834
  }
834
835
 
835
- // 递归检查数组元素类型
836
+ // Recursively check array element type
836
837
  if (typeNode.type === AST_NODE_TYPES.TSArrayType) {
837
838
  return containsOpt(typeNode.elementType);
838
839
  }
@@ -845,7 +846,7 @@ export default createRule<
845
846
  }
846
847
  });
847
848
 
848
- // 如果使用了 Opt 但没有导入,报告错误
849
+ // If Opt is used but not imported, report an error
849
850
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
850
851
  if (usesOpt && !hasOptImport()) {
851
852
  context.report({
@@ -863,13 +864,13 @@ export default createRule<
863
864
  ClassDeclaration(node) {
864
865
  if (!isEntityClass(node)) return;
865
866
 
866
- // 首先检查是否使用了 Opt 但没有导入
867
+ // First check if Opt is used but not imported
867
868
  checkOptUsageWithoutImport(node);
868
869
 
869
870
  node.body.body.forEach((member: TSESTree.ClassElement) => {
870
871
  if (member.type !== AST_NODE_TYPES.PropertyDefinition) return;
871
872
 
872
- // 检查关系装饰器(OneToOne, OneToMany, ManyToOne, ManyToMany
873
+ // Check relation decorators (OneToOne, OneToMany, ManyToOne, ManyToMany)
873
874
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
874
875
  const hasRelationDecorator = member.decorators?.some(
875
876
  (decorator: TSESTree.Decorator) => {
@@ -889,10 +890,10 @@ export default createRule<
889
890
  },
890
891
  );
891
892
 
892
- // 如果有关系装饰器,跳过检查(这些属性不需要 @Property 装饰器)
893
+ // If there are relation decorators, skip checking (these properties don't need @Property)
893
894
  if (hasRelationDecorator) return;
894
895
 
895
- // Property 装饰器列表(需要类型检查的装饰器)
896
+ // Property-like decorators (decorators that need type checking)
896
897
  const propertyLikeDecorators = [
897
898
  "Property",
898
899
  "PrimaryKey",
@@ -900,7 +901,7 @@ export default createRule<
900
901
  "HashedProperty",
901
902
  ];
902
903
 
903
- // 查找类 Property 装饰器
904
+ // Find property-like decorator
904
905
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
905
906
  const propertyLikeDecorator = member.decorators?.find(
906
907
  (decorator: TSESTree.Decorator) => {
@@ -916,7 +917,7 @@ export default createRule<
916
917
  },
917
918
  );
918
919
 
919
- // 获取装饰器名称
920
+ // Get decorator name
920
921
  const getDecoratorName = (
921
922
  decorator: TSESTree.Decorator,
922
923
  ): string | null => {
@@ -929,7 +930,7 @@ export default createRule<
929
930
  return null;
930
931
  };
931
932
 
932
- // 检查 @Enum 装饰器
933
+ // Check @Enum decorator
933
934
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
934
935
  const enumDecorator = member.decorators?.find(
935
936
  (decorator: TSESTree.Decorator) => {
@@ -942,7 +943,7 @@ export default createRule<
942
943
  },
943
944
  );
944
945
 
945
- // 使用类 Property 装饰器
946
+ // Use property-like decorator
946
947
  const propertyDecorator = propertyLikeDecorator;
947
948
  const currentDecoratorName = propertyDecorator
948
949
  ? getDecoratorName(propertyDecorator)
@@ -952,11 +953,11 @@ export default createRule<
952
953
 
953
954
  if (!typeInfo?.typeName) return;
954
955
 
955
- // 检查初始化值和 Opt<T> 类型的匹配
956
+ // Check initializer and Opt<T> type match
956
957
  const hasInitializer = member.value !== null;
957
958
  const isOptWrapped = isWrappedWithOpt(member);
958
959
 
959
- // 检查初始化值是否为 null
960
+ // Check if the initializer is null
960
961
 
961
962
  const isInitializedToNull =
962
963
  hasInitializer &&
@@ -964,14 +965,14 @@ export default createRule<
964
965
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
965
966
  member.value?.value === null;
966
967
 
967
- // 情况 1:有非 null 初始化值但没有使用 Opt<T>
968
+ // Case 1: Has non-null initializer but not wrapped with Opt<T>
968
969
  if (
969
970
  hasInitializer &&
970
971
  !isInitializedToNull &&
971
972
  !isOptWrapped &&
972
973
  !member.optional
973
974
  ) {
974
- // 有初始化值但没有使用 Opt<T> 包装,需要报错
975
+ // Has initializer but not wrapped with Opt<T>, needs to report error
975
976
  const typeAnnotation = member.typeAnnotation?.typeAnnotation;
976
977
  const needsImport = !hasOptImport();
977
978
 
@@ -987,7 +988,7 @@ export default createRule<
987
988
  fixer.replaceText(typeAnnotation, wrappedType),
988
989
  ];
989
990
 
990
- // 如果需要,添加 Opt 导入
991
+ // If needed, add Opt import
991
992
  if (needsImport) {
992
993
  const importFix = addOptImport(fixer);
993
994
  if (importFix) fixes.push(importFix);
@@ -997,7 +998,7 @@ export default createRule<
997
998
  },
998
999
  });
999
1000
  } else if (member.value) {
1000
- // 没有类型注解,从初始化值推断类型
1001
+ // No type annotation, infer type from initializer
1001
1002
  let inferredType: string | null = null;
1002
1003
 
1003
1004
  if (member.value.type === AST_NODE_TYPES.Literal) {
@@ -1006,10 +1007,10 @@ export default createRule<
1006
1007
  else if (valueType === "number") inferredType = "number";
1007
1008
  else if (valueType === "string") inferredType = "string";
1008
1009
  } else if (member.value.type === AST_NODE_TYPES.ArrayExpression) {
1009
- // 空数组 [] 的情况,需要从 @Property 装饰器推断类型
1010
+ // Empty array [] case, need to infer type from @Property decorator
1010
1011
  inferredType = "unknown[]";
1011
1012
  } else if (member.value.type === AST_NODE_TYPES.NewExpression) {
1012
- // new Date() 的情况
1013
+ // new Date() case
1013
1014
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1014
1015
  if (member.value.callee?.type === AST_NODE_TYPES.Identifier) {
1015
1016
  inferredType = member.value.callee.name;
@@ -1028,7 +1029,7 @@ export default createRule<
1028
1029
  fixer.insertTextAfter(propertyName, `: ${wrappedType}`),
1029
1030
  ];
1030
1031
 
1031
- // 如果需要,添加 Opt 导入
1032
+ // If needed, add Opt import
1032
1033
  if (needsImport) {
1033
1034
  const importFix = addOptImport(fixer);
1034
1035
  if (importFix) fixes.push(importFix);
@@ -1041,11 +1042,11 @@ export default createRule<
1041
1042
  }
1042
1043
  }
1043
1044
 
1044
- // 如果有 @Enum 装饰器,无论是否识别为枚举类型,都检查其配置
1045
+ // If there is an @Enum decorator, check its configuration regardless of whether the type is recognized as enum
1045
1046
  if (enumDecorator) {
1046
1047
  const enumConfig = parseEnumDecorator(enumDecorator);
1047
1048
 
1048
- // 检查 nullable 配置是否与 TypeScript 类型匹配
1049
+ // Check if nullable configuration matches the TypeScript type
1049
1050
  if (enumConfig.nullable !== typeInfo.isNullable) {
1050
1051
  const expectedEnumText = buildEnumDecorator(typeInfo);
1051
1052
  context.report({
@@ -1059,13 +1060,13 @@ export default createRule<
1059
1060
  },
1060
1061
  });
1061
1062
  }
1062
- // @Enum 装饰器的属性,不需要 @Property 装饰器
1063
+ // Properties with @Enum decorator do not need @Property decorator
1063
1064
  return;
1064
1065
  }
1065
1066
 
1066
- // 如果是枚举类型但没有 @Enum 装饰器
1067
+ // If it's an enum type but doesn't have @Enum decorator
1067
1068
  if (typeInfo.isEnum) {
1068
- // 如果有 @Property 装饰器,建议替换为 @Enum
1069
+ // If it has @Property decorator, suggest replacing with @Enum
1069
1070
  if (propertyDecorator) {
1070
1071
  context.report({
1071
1072
  node: propertyDecorator,
@@ -1081,7 +1082,7 @@ export default createRule<
1081
1082
  return;
1082
1083
  }
1083
1084
 
1084
- // 如果没有 @Enum 装饰器,添加它
1085
+ // If it doesn't have @Enum decorator, add one
1085
1086
  context.report({
1086
1087
  node: member,
1087
1088
  messageId: "useEnumDecorator",
@@ -1096,7 +1097,7 @@ export default createRule<
1096
1097
  return;
1097
1098
  }
1098
1099
 
1099
- // 非枚举类型:如果没有 @Property 装饰器,添加它
1100
+ // Non-enum type: if no @Property decorator, add one
1100
1101
  if (!propertyDecorator) {
1101
1102
  context.report({
1102
1103
  node: member,
@@ -1109,11 +1110,11 @@ export default createRule<
1109
1110
  return;
1110
1111
  }
1111
1112
 
1112
- // 检查现有装饰器是否与类型匹配
1113
+ // Check if existing decorator matches the type
1113
1114
  const currentConfig = parsePropertyDecorator(propertyDecorator);
1114
1115
  let expectedType = typeInfo.propertyType;
1115
1116
 
1116
- // PrimaryKey number 类型期望 t.integer
1117
+ // PrimaryKey number type expects t.integer
1117
1118
  if (
1118
1119
  currentDecoratorName === "PrimaryKey" &&
1119
1120
  expectedType === "t.float"
@@ -1123,34 +1124,34 @@ export default createRule<
1123
1124
 
1124
1125
  let needReport = false;
1125
1126
 
1126
- // 检查 type 配置
1127
+ // Check type configuration
1127
1128
  if (expectedType && currentConfig.type !== expectedType) {
1128
- // 对于 string 类型,接受多种有效配置
1129
+ // For string type, accept multiple valid configurations
1129
1130
  if (
1130
1131
  expectedType === "t.string" &&
1131
1132
  isValidStringType(currentConfig.type)
1132
1133
  ) {
1133
- // 当前配置是有效的 string 类型配置,不需要修改
1134
+ // Current config is a valid string type configuration, no modification needed
1134
1135
  } else if (
1135
1136
  (expectedType === "t.float" || expectedType === "t.integer") &&
1136
1137
  isValidNumberType(currentConfig.type)
1137
1138
  ) {
1138
- // 当前配置是有效的 number 类型配置,不需要修改
1139
+ // Current config is a valid number type configuration, no modification needed
1139
1140
  } else if (
1140
1141
  expectedType === "t.datetime" &&
1141
1142
  isValidDateType(currentConfig.type)
1142
1143
  ) {
1143
- // 当前配置是有效的 Date 类型配置,不需要修改
1144
+ // Current config is a valid Date type configuration, no modification needed
1144
1145
  } else if (
1145
1146
  expectedType === "t.array" &&
1146
1147
  typeInfo.arrayElementTypeName === "number" &&
1147
1148
  isValidNumberArrayType(currentConfig.type)
1148
1149
  ) {
1149
- // 当前配置是有效的 number[] 类型配置(t.array VectorType),不需要修改
1150
+ // Current config is a valid number[] type configuration (t.array or VectorType), no modification needed
1150
1151
  } else if (expectedType === "t.json") {
1151
- // 对于 t.json 类型(Record 或自定义类型数组)
1152
+ // For t.json type (Record or custom type arrays)
1152
1153
  if (currentConfig.type === "t.json") {
1153
- // t.json 配置正确,不需要修改
1154
+ // t.json config is correct, no modification needed
1154
1155
  } else {
1155
1156
  needReport = true;
1156
1157
  }
@@ -1158,11 +1159,11 @@ export default createRule<
1158
1159
  needReport = true;
1159
1160
  }
1160
1161
  } else if (!expectedType && currentConfig.type) {
1161
- // 如果不需要 type 但当前有 type,也需要修正
1162
+ // If type is not needed but currently has one, needs correction
1162
1163
  needReport = true;
1163
1164
  }
1164
1165
 
1165
- // 检查 nullable 配置
1166
+ // Check nullable configuration
1166
1167
  if (currentConfig.nullable !== typeInfo.isNullable) {
1167
1168
  needReport = true;
1168
1169
  }