@nest-boot/eslint-plugin 7.0.2 → 7.0.4

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.
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "@nest-boot/eslint-plugin",
3
- "version": "7.0.2",
3
+ "version": "7.0.4",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "exports": "./dist/index.js",
7
7
  "dependencies": {
8
8
  "@typescript-eslint/utils": "^8.44.1"
9
9
  },
10
+ "peerDependencies": {
11
+ "@typescript-eslint/parser": "^8.0.0",
12
+ "eslint": "^9.0.0",
13
+ "typescript": "^5.0.0"
14
+ },
10
15
  "devDependencies": {
11
16
  "@eslint/eslintrc": "^3.3.1",
12
17
  "@eslint/js": "^9.36.0",
13
18
  "@jest/globals": "^30.2.0",
14
- "@nest-boot/tsconfig": "^7.0.0",
15
19
  "@types/node": "^22.18.6",
20
+ "@typescript-eslint/parser": "^8.44.1",
16
21
  "@typescript-eslint/rule-tester": "^8.44.1",
17
22
  "eslint": "^9.36.0",
18
23
  "eslint-config-prettier": "^10.1.8",
@@ -20,7 +25,8 @@
20
25
  "jest": "^29.7.0",
21
26
  "ts-jest": "^29.4.4",
22
27
  "typescript": "^5.9.3",
23
- "typescript-eslint": "^8.46.2"
28
+ "typescript-eslint": "^8.46.2",
29
+ "@nest-boot/tsconfig": "^7.0.1"
24
30
  },
25
31
  "publishConfig": {
26
32
  "access": "public"
@@ -78,6 +78,8 @@ export default createRule({
78
78
  "OneToMany",
79
79
  "ManyToOne",
80
80
  "ManyToMany",
81
+ "EncryptedProperty",
82
+ "HashedProperty",
81
83
  ])
82
84
  )
83
85
  return;
@@ -43,13 +43,13 @@ tester.run("entity-property-config-from-types", rule, {
43
43
  author!: User;
44
44
  }
45
45
  `,
46
- // PrimaryKey 不需要 @Property
46
+ // PrimaryKey 需要 type 配置
47
47
  /* typescript */ `
48
- import { Entity, PrimaryKey } from "@mikro-orm/core";
48
+ import { Entity, PrimaryKey, t } from "@mikro-orm/core";
49
49
 
50
50
  @Entity()
51
51
  class User {
52
- @PrimaryKey()
52
+ @PrimaryKey({ type: t.integer })
53
53
  id!: number;
54
54
  }
55
55
  `,
@@ -112,10 +112,11 @@ export default createRule<
112
112
  const isValidStringType = (typeConfig: string | null): boolean => {
113
113
  if (!typeConfig) return false;
114
114
 
115
- // 接受 t.string, t.text, t.decimal, t.bigint
115
+ // 接受 t.string, t.text, t.uuid, t.decimal, t.bigint
116
116
  if (
117
117
  typeConfig === "t.string" ||
118
118
  typeConfig === "t.text" ||
119
+ typeConfig === "t.uuid" ||
119
120
  typeConfig === "t.decimal" ||
120
121
  typeConfig === "t.bigint"
121
122
  ) {
@@ -572,6 +573,7 @@ export default createRule<
572
573
  const buildPropertyDecorator = (
573
574
  info: TypeInfo,
574
575
  otherProps: { key: string; value: string }[] = [],
576
+ decoratorName = "Property",
575
577
  ): string => {
576
578
  const options: string[] = [];
577
579
 
@@ -590,10 +592,10 @@ export default createRule<
590
592
  }
591
593
 
592
594
  if (options.length === 0) {
593
- return "@Property()";
595
+ return `@${decoratorName}()`;
594
596
  }
595
597
 
596
- return `@Property({ ${options.join(", ")} })`;
598
+ return `@${decoratorName}({ ${options.join(", ")} })`;
597
599
  };
598
600
 
599
601
  const addPropertyDecorator = (
@@ -622,11 +624,21 @@ export default createRule<
622
624
  nullable: boolean;
623
625
  otherProps: { key: string; value: string }[];
624
626
  },
627
+ decoratorName = "Property",
625
628
  ) => {
626
629
  const fixes: CustomFix[] = [];
627
630
 
628
631
  // 如果当前已经有有效的配置,保留它而不是替换成默认值
629
632
  const finalInfo = { ...info };
633
+
634
+ // PrimaryKey 的 number 类型默认使用 t.integer
635
+ if (
636
+ decoratorName === "PrimaryKey" &&
637
+ finalInfo.propertyType === "t.float"
638
+ ) {
639
+ finalInfo.propertyType = "t.integer";
640
+ }
641
+
630
642
  if (
631
643
  info.propertyType === "t.string" &&
632
644
  isValidStringType(currentConfig.type)
@@ -634,7 +646,8 @@ export default createRule<
634
646
  // 保留有效的 string 类型配置
635
647
  finalInfo.propertyType = currentConfig.type;
636
648
  } else if (
637
- info.propertyType === "t.float" &&
649
+ (info.propertyType === "t.float" ||
650
+ info.propertyType === "t.integer") &&
638
651
  isValidNumberType(currentConfig.type)
639
652
  ) {
640
653
  // 保留有效的 number 类型配置
@@ -658,6 +671,7 @@ export default createRule<
658
671
  const newDecoratorText = buildPropertyDecorator(
659
672
  finalInfo,
660
673
  currentConfig.otherProps,
674
+ decoratorName,
661
675
  );
662
676
 
663
677
  fixes.push({
@@ -855,7 +869,7 @@ export default createRule<
855
869
  node.body.body.forEach((member: TSESTree.ClassElement) => {
856
870
  if (member.type !== AST_NODE_TYPES.PropertyDefinition) return;
857
871
 
858
- // 检查关系装饰器(PrimaryKey, OneToOne, OneToMany, ManyToOne, ManyToMany)
872
+ // 检查关系装饰器(OneToOne, OneToMany, ManyToOne, ManyToMany)
859
873
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
860
874
  const hasRelationDecorator = member.decorators?.some(
861
875
  (decorator: TSESTree.Decorator) => {
@@ -865,7 +879,6 @@ export default createRule<
865
879
  ) {
866
880
  const decoratorName = decorator.expression.callee.name;
867
881
  return [
868
- "PrimaryKey",
869
882
  "OneToOne",
870
883
  "OneToMany",
871
884
  "ManyToOne",
@@ -879,31 +892,62 @@ export default createRule<
879
892
  // 如果有关系装饰器,跳过检查(这些属性不需要 @Property 装饰器)
880
893
  if (hasRelationDecorator) return;
881
894
 
882
- // 检查 @Enum 装饰器
895
+ // Property 装饰器列表(需要类型检查的装饰器)
896
+ const propertyLikeDecorators = [
897
+ "Property",
898
+ "PrimaryKey",
899
+ "EncryptedProperty",
900
+ "HashedProperty",
901
+ ];
902
+
903
+ // 查找类 Property 装饰器
883
904
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
884
- const enumDecorator = member.decorators?.find(
905
+ const propertyLikeDecorator = member.decorators?.find(
885
906
  (decorator: TSESTree.Decorator) => {
886
- return (
907
+ if (
887
908
  decorator.expression.type === AST_NODE_TYPES.CallExpression &&
888
- decorator.expression.callee.type ===
889
- AST_NODE_TYPES.Identifier &&
890
- decorator.expression.callee.name === "Enum"
891
- );
909
+ decorator.expression.callee.type === AST_NODE_TYPES.Identifier
910
+ ) {
911
+ return propertyLikeDecorators.includes(
912
+ decorator.expression.callee.name,
913
+ );
914
+ }
915
+ return false;
892
916
  },
893
917
  );
894
918
 
919
+ // 获取装饰器名称
920
+ const getDecoratorName = (
921
+ decorator: TSESTree.Decorator,
922
+ ): string | null => {
923
+ if (
924
+ decorator.expression.type === AST_NODE_TYPES.CallExpression &&
925
+ decorator.expression.callee.type === AST_NODE_TYPES.Identifier
926
+ ) {
927
+ return decorator.expression.callee.name;
928
+ }
929
+ return null;
930
+ };
931
+
932
+ // 检查 @Enum 装饰器
895
933
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
896
- const propertyDecorator = member.decorators?.find(
934
+ const enumDecorator = member.decorators?.find(
897
935
  (decorator: TSESTree.Decorator) => {
898
936
  return (
899
937
  decorator.expression.type === AST_NODE_TYPES.CallExpression &&
900
938
  decorator.expression.callee.type ===
901
939
  AST_NODE_TYPES.Identifier &&
902
- decorator.expression.callee.name === "Property"
940
+ decorator.expression.callee.name === "Enum"
903
941
  );
904
942
  },
905
943
  );
906
944
 
945
+ // 使用类 Property 装饰器
946
+ const propertyDecorator = propertyLikeDecorator;
947
+ const currentDecoratorName = propertyDecorator
948
+ ? getDecoratorName(propertyDecorator)
949
+ : null;
950
+
907
951
  const typeInfo = computeTypeInfo(member);
908
952
 
909
953
  if (!typeInfo?.typeName) return;
@@ -1065,9 +1109,17 @@ export default createRule<
1065
1109
  return;
1066
1110
  }
1067
1111
 
1068
- // 检查现有 @Property 装饰器是否与类型匹配
1112
+ // 检查现有装饰器是否与类型匹配
1069
1113
  const currentConfig = parsePropertyDecorator(propertyDecorator);
1070
- const expectedType = typeInfo.propertyType;
1114
+ let expectedType = typeInfo.propertyType;
1115
+
1116
+ // PrimaryKey 的 number 类型期望 t.integer
1117
+ if (
1118
+ currentDecoratorName === "PrimaryKey" &&
1119
+ expectedType === "t.float"
1120
+ ) {
1121
+ expectedType = "t.integer";
1122
+ }
1071
1123
 
1072
1124
  let needReport = false;
1073
1125
 
@@ -1080,7 +1132,7 @@ export default createRule<
1080
1132
  ) {
1081
1133
  // 当前配置是有效的 string 类型配置,不需要修改
1082
1134
  } else if (
1083
- expectedType === "t.float" &&
1135
+ (expectedType === "t.float" || expectedType === "t.integer") &&
1084
1136
  isValidNumberType(currentConfig.type)
1085
1137
  ) {
1086
1138
  // 当前配置是有效的 number 类型配置,不需要修改
@@ -1126,6 +1178,7 @@ export default createRule<
1126
1178
  propertyDecorator,
1127
1179
  typeInfo,
1128
1180
  currentConfig,
1181
+ currentDecoratorName ?? "Property",
1129
1182
  );
1130
1183
  return applyFixes(fixer, fixes);
1131
1184
  },