@nest-boot/eslint-plugin 7.0.0-beta.1 → 7.0.0-beta.2

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 (80) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/CHANGELOG.md +2 -20
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +2 -5
  5. package/dist/index.js.map +1 -1
  6. package/dist/rules/graphql/graphql-field-config-from-types.d.ts +6 -0
  7. package/dist/rules/graphql/graphql-field-config-from-types.js +417 -0
  8. package/dist/rules/graphql/graphql-field-config-from-types.js.map +1 -0
  9. package/dist/rules/graphql/graphql-field-definite-assignment.d.ts +2 -0
  10. package/dist/rules/graphql/graphql-field-definite-assignment.js +125 -0
  11. package/dist/rules/graphql/graphql-field-definite-assignment.js.map +1 -0
  12. package/dist/rules/import/import-bullmq.d.ts +2 -0
  13. package/dist/rules/import/import-bullmq.js +36 -0
  14. package/dist/rules/import/import-bullmq.js.map +1 -0
  15. package/dist/rules/import/import-graphql.d.ts +2 -0
  16. package/dist/rules/import/import-graphql.js +36 -0
  17. package/dist/rules/import/import-graphql.js.map +1 -0
  18. package/dist/rules/import/import-mikro-orm.d.ts +2 -0
  19. package/dist/rules/import/import-mikro-orm.js +36 -0
  20. package/dist/rules/import/import-mikro-orm.js.map +1 -0
  21. package/dist/rules/index.d.ts +9 -0
  22. package/dist/rules/index.js +16 -11
  23. package/dist/rules/index.js.map +1 -1
  24. package/dist/rules/mikro-orm/entity-field-definite-assignment.d.ts +2 -0
  25. package/dist/rules/mikro-orm/entity-field-definite-assignment.js +125 -0
  26. package/dist/rules/mikro-orm/entity-field-definite-assignment.js.map +1 -0
  27. package/dist/rules/mikro-orm/entity-property-config-from-types.d.ts +3 -0
  28. package/dist/rules/mikro-orm/entity-property-config-from-types.js +881 -0
  29. package/dist/rules/mikro-orm/entity-property-config-from-types.js.map +1 -0
  30. package/dist/tsconfig.build.tsbuildinfo +1 -0
  31. package/dist/utils/createRule.d.ts +2 -0
  32. package/dist/utils/createRule.js +1 -1
  33. package/dist/utils/createRule.js.map +1 -1
  34. package/dist/utils/decorators.d.ts +29 -0
  35. package/dist/utils/decorators.js +74 -0
  36. package/dist/utils/decorators.js.map +1 -0
  37. package/dist/utils/tester.d.ts +2 -0
  38. package/dist/utils/tester.js +27 -0
  39. package/dist/utils/tester.js.map +1 -0
  40. package/eslint.config.mjs +38 -2
  41. package/jest.config.ts +12 -0
  42. package/package.json +22 -14
  43. package/src/index.ts +1 -1
  44. package/src/rules/graphql/graphql-field-config-from-types.spec.ts +242 -0
  45. package/src/rules/graphql/graphql-field-config-from-types.ts +557 -0
  46. package/src/rules/graphql/graphql-field-definite-assignment.spec.ts +135 -0
  47. package/src/rules/graphql/graphql-field-definite-assignment.ts +147 -0
  48. package/src/rules/import/import-bullmq.spec.ts +69 -0
  49. package/src/rules/import/import-bullmq.ts +35 -0
  50. package/src/rules/import/import-graphql.spec.ts +65 -0
  51. package/src/rules/import/import-graphql.ts +36 -0
  52. package/src/rules/import/import-mikro-orm.spec.ts +65 -0
  53. package/src/rules/import/import-mikro-orm.ts +36 -0
  54. package/src/rules/index.ts +15 -13
  55. package/src/rules/mikro-orm/entity-field-definite-assignment.spec.ts +91 -0
  56. package/src/rules/mikro-orm/entity-field-definite-assignment.ts +141 -0
  57. package/src/rules/mikro-orm/entity-property-config-from-types.spec.ts +262 -0
  58. package/src/rules/mikro-orm/entity-property-config-from-types.ts +1111 -0
  59. package/src/utils/createRule.ts +3 -1
  60. package/src/utils/decorators.spec.ts +214 -0
  61. package/src/utils/decorators.ts +93 -0
  62. package/src/utils/tester.ts +22 -0
  63. package/tsconfig.build.json +5 -0
  64. package/tsconfig.json +6 -7
  65. package/dist/rules/entity-constructor.js +0 -78
  66. package/dist/rules/entity-constructor.js.map +0 -1
  67. package/dist/rules/entity-property-no-optional-or-non-null-assertion.js +0 -63
  68. package/dist/rules/entity-property-no-optional-or-non-null-assertion.js.map +0 -1
  69. package/dist/rules/entity-property-nullable.js +0 -81
  70. package/dist/rules/entity-property-nullable.js.map +0 -1
  71. package/dist/rules/graphql-field-arguments-match-property-type.js +0 -118
  72. package/dist/rules/graphql-field-arguments-match-property-type.js.map +0 -1
  73. package/dist/rules/graphql-resolver-method-return-type.js +0 -145
  74. package/dist/rules/graphql-resolver-method-return-type.js.map +0 -1
  75. package/dist/tsconfig.tsbuildinfo +0 -1
  76. package/src/rules/entity-constructor.ts +0 -97
  77. package/src/rules/entity-property-no-optional-or-non-null-assertion.ts +0 -81
  78. package/src/rules/entity-property-nullable.ts +0 -112
  79. package/src/rules/graphql-field-arguments-match-property-type.ts +0 -186
  80. package/src/rules/graphql-resolver-method-return-type.ts +0 -207
@@ -0,0 +1,147 @@
1
+ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils";
2
+
3
+ import { createRule } from "../../utils/createRule";
4
+ import {
5
+ hasClassDecorator,
6
+ hasPropertyDecorator,
7
+ } from "../../utils/decorators";
8
+
9
+ export default createRule<
10
+ [],
11
+ "addDefiniteAssignment" | "removeDefiniteAssignment"
12
+ >({
13
+ name: "graphql-field-definite-assignment",
14
+ meta: {
15
+ type: "problem",
16
+ docs: {
17
+ description:
18
+ "确保 GraphQL @Field 装饰器的属性正确使用 definite assignment assertion (!)。没有初始化值的属性应添加 !,有初始化值的属性应移除 !。",
19
+ },
20
+ fixable: "code",
21
+ schema: [],
22
+ messages: {
23
+ addDefiniteAssignment:
24
+ "属性 '{{propertyName}}' 使用了 @Field 装饰器但没有初始化值,应添加 definite assignment assertion (!)。",
25
+ removeDefiniteAssignment:
26
+ "属性 '{{propertyName}}' 使用了 @Field 装饰器且有初始化值,应移除 definite assignment assertion (!)。",
27
+ },
28
+ },
29
+ defaultOptions: [],
30
+ create(context) {
31
+ const source = context.sourceCode;
32
+
33
+ const isGraphqlModelClass = (node: TSESTree.ClassDeclaration): boolean => {
34
+ return hasClassDecorator(node, ["ObjectType", "InputType", "ArgsType"]);
35
+ };
36
+
37
+ const getPropertyName = (
38
+ member: TSESTree.PropertyDefinition,
39
+ ): string | null => {
40
+ if (member.key.type === AST_NODE_TYPES.Identifier) {
41
+ return member.key.name;
42
+ }
43
+ return null;
44
+ };
45
+
46
+ const hasInitializer = (member: TSESTree.PropertyDefinition): boolean => {
47
+ return !!member.value;
48
+ };
49
+
50
+ const hasDefiniteAssignment = (
51
+ member: TSESTree.PropertyDefinition,
52
+ ): boolean => {
53
+ return member.definite;
54
+ };
55
+
56
+ const isOptionalProperty = (
57
+ member: TSESTree.PropertyDefinition,
58
+ ): boolean => {
59
+ // 检查 AST 节点的 optional 标记
60
+ if (member.optional) return true;
61
+
62
+ // 检查源代码中是否有 ? 符号(在属性名和冒号之间)
63
+ const keyEnd = member.key.range[1];
64
+ const text = source.text;
65
+ for (let i = keyEnd; i < member.range[1]; i++) {
66
+ if (text[i] === "?") return true;
67
+ if (text[i] === ":" || text[i] === "!") break;
68
+ }
69
+
70
+ return false;
71
+ };
72
+
73
+ return {
74
+ ClassDeclaration(node) {
75
+ if (!isGraphqlModelClass(node)) return;
76
+
77
+ node.body.body.forEach((member: TSESTree.ClassElement) => {
78
+ if (member.type !== AST_NODE_TYPES.PropertyDefinition) return;
79
+ if (!hasPropertyDecorator(member, "Field")) return;
80
+
81
+ const propertyName = getPropertyName(member);
82
+ if (!propertyName) return;
83
+
84
+ // 可选属性(?:)不需要 definite assignment assertion
85
+ if (isOptionalProperty(member)) return;
86
+
87
+ const hasInit = hasInitializer(member);
88
+ const hasDefinite = hasDefiniteAssignment(member);
89
+
90
+ // 情况1: 没有初始化值,但也没有 definite assignment assertion
91
+ if (!hasInit && !hasDefinite) {
92
+ context.report({
93
+ node: member,
94
+ messageId: "addDefiniteAssignment",
95
+ data: {
96
+ propertyName,
97
+ },
98
+ fix: (fixer) => {
99
+ // 找到属性名称的结束位置
100
+ const keyEnd = member.key.range[1];
101
+ // 在属性名称后添加 !
102
+ return fixer.insertTextAfterRange([keyEnd, keyEnd], "!");
103
+ },
104
+ });
105
+ }
106
+
107
+ // 情况2: 有初始化值,但也有 definite assignment assertion
108
+ if (hasInit && hasDefinite) {
109
+ context.report({
110
+ node: member,
111
+ messageId: "removeDefiniteAssignment",
112
+ data: {
113
+ propertyName,
114
+ },
115
+ fix: (fixer) => {
116
+ // 找到 ! 的位置并移除
117
+ const keyEnd = member.key.range[1];
118
+ const text = source.text;
119
+
120
+ // 查找 ! 的位置(在属性名称和冒号之间)
121
+ let exclamationPos = -1;
122
+ for (let i = keyEnd; i < member.range[1]; i++) {
123
+ if (text[i] === "!") {
124
+ exclamationPos = i;
125
+ break;
126
+ }
127
+ // 如果遇到冒号,说明没有 !
128
+ if (text[i] === ":") {
129
+ break;
130
+ }
131
+ }
132
+
133
+ if (exclamationPos !== -1) {
134
+ return fixer.removeRange([
135
+ exclamationPos,
136
+ exclamationPos + 1,
137
+ ]);
138
+ }
139
+ return null;
140
+ },
141
+ });
142
+ }
143
+ });
144
+ },
145
+ };
146
+ },
147
+ });
@@ -0,0 +1,69 @@
1
+ import { tester } from "../../utils/tester";
2
+ import rule from "./import-bullmq";
3
+
4
+ tester.run("import-bullmq", rule, {
5
+ valid: [
6
+ // 正确的导入来源
7
+ /* typescript */ `
8
+ import { BullModule } from "@nest-boot/bullmq";
9
+ `,
10
+ // 从其他包导入
11
+ /* typescript */ `
12
+ import { Module } from "@nestjs/common";
13
+ `,
14
+ // 命名导入
15
+ /* typescript */ `
16
+ import { InjectQueue, Processor } from "@nest-boot/bullmq";
17
+ `,
18
+ // 默认导入
19
+ /* typescript */ `
20
+ import BullMQ from "@nest-boot/bullmq";
21
+ `,
22
+ // 从 bullmq 核心包导入(不应该被替换)
23
+ /* typescript */ `
24
+ import { Queue, Worker } from "bullmq";
25
+ `,
26
+ ],
27
+ invalid: [
28
+ // 从 @nestjs/bullmq 导入,应该替换为 @nest-boot/bullmq
29
+ {
30
+ code: /* typescript */ `
31
+ import { BullModule } from "@nestjs/bullmq";
32
+ `,
33
+ output: /* typescript */ `
34
+ import { BullModule } from "@nest-boot/bullmq";
35
+ `,
36
+ errors: [{ messageId: "replaceBullmqImport" }],
37
+ },
38
+ // Processor 相关导入
39
+ {
40
+ code: /* typescript */ `
41
+ import { Processor, InjectQueue } from "@nestjs/bullmq";
42
+ `,
43
+ output: /* typescript */ `
44
+ import { Processor, InjectQueue } from "@nest-boot/bullmq";
45
+ `,
46
+ errors: [{ messageId: "replaceBullmqImport" }],
47
+ },
48
+ // 类型导入
49
+ {
50
+ code: /* typescript */ `
51
+ import type { BullModuleOptions } from "@nestjs/bullmq";
52
+ `,
53
+ output: /* typescript */ `
54
+ import type { BullModuleOptions } from "@nest-boot/bullmq";
55
+ `,
56
+ errors: [{ messageId: "replaceBullmqImport" }],
57
+ },
58
+ // 装饰器导入
59
+ {
60
+ code: /* typescript */ `
61
+ import { OnQueueActive, OnQueueCompleted } from "@nestjs/bullmq";
62
+ `,
63
+ output: /* typescript */ `
64
+ import { OnQueueActive, OnQueueCompleted } from "@nest-boot/bullmq";
65
+ `,
66
+ errors: [{ messageId: "replaceBullmqImport" }],
67
+ },
68
+ ],
69
+ });
@@ -0,0 +1,35 @@
1
+ import { createRule } from "../../utils/createRule";
2
+
3
+ export default createRule({
4
+ name: "import-bullmq",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description:
9
+ "将从 @nestjs/bullmq 导入的包修复为从 @nest-boot/bullmq 导入",
10
+ },
11
+ fixable: "code",
12
+ schema: [],
13
+ messages: {
14
+ replaceBullmqImport: "应从 @nest-boot/bullmq 导入,而不是 @nestjs/bullmq",
15
+ },
16
+ },
17
+ defaultOptions: [],
18
+ create(context) {
19
+ return {
20
+ ImportDeclaration(node) {
21
+ // 检查是否从 @nestjs/bullmq 导入
22
+ if (node.source.value === "@nestjs/bullmq") {
23
+ context.report({
24
+ node,
25
+ messageId: "replaceBullmqImport",
26
+ fix(fixer) {
27
+ // 将导入源替换为 @nest-boot/bullmq
28
+ return fixer.replaceText(node.source, '"@nest-boot/bullmq"');
29
+ },
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ });
@@ -0,0 +1,65 @@
1
+ import { tester } from "../../utils/tester";
2
+ import rule from "./import-graphql";
3
+
4
+ tester.run("import-graphql", rule, {
5
+ valid: [
6
+ // 正确的导入来源
7
+ /* typescript */ `
8
+ import { Field, ObjectType } from "@nest-boot/graphql";
9
+ `,
10
+ // 从其他包导入
11
+ /* typescript */ `
12
+ import { Module } from "@nestjs/common";
13
+ `,
14
+ // 命名导入
15
+ /* typescript */ `
16
+ import { Resolver, Query } from "@nest-boot/graphql";
17
+ `,
18
+ // 默认导入
19
+ /* typescript */ `
20
+ import GraphQL from "@nest-boot/graphql";
21
+ `,
22
+ ],
23
+ invalid: [
24
+ // 从 @nestjs/graphql 导入,应该替换为 @nest-boot/graphql
25
+ {
26
+ code: /* typescript */ `
27
+ import { Field, ObjectType } from "@nestjs/graphql";
28
+ `,
29
+ output: /* typescript */ `
30
+ import { Field, ObjectType } from "@nest-boot/graphql";
31
+ `,
32
+ errors: [{ messageId: "replaceGraphqlImport" }],
33
+ },
34
+ // Resolver 相关导入
35
+ {
36
+ code: /* typescript */ `
37
+ import { Resolver, Query, Mutation } from "@nestjs/graphql";
38
+ `,
39
+ output: /* typescript */ `
40
+ import { Resolver, Query, Mutation } from "@nest-boot/graphql";
41
+ `,
42
+ errors: [{ messageId: "replaceGraphqlImport" }],
43
+ },
44
+ // 类型导入
45
+ {
46
+ code: /* typescript */ `
47
+ import type { GraphQLModule } from "@nestjs/graphql";
48
+ `,
49
+ output: /* typescript */ `
50
+ import type { GraphQLModule } from "@nest-boot/graphql";
51
+ `,
52
+ errors: [{ messageId: "replaceGraphqlImport" }],
53
+ },
54
+ // 混合导入
55
+ {
56
+ code: /* typescript */ `
57
+ import { Args, Int } from "@nestjs/graphql";
58
+ `,
59
+ output: /* typescript */ `
60
+ import { Args, Int } from "@nest-boot/graphql";
61
+ `,
62
+ errors: [{ messageId: "replaceGraphqlImport" }],
63
+ },
64
+ ],
65
+ });
@@ -0,0 +1,36 @@
1
+ import { createRule } from "../../utils/createRule";
2
+
3
+ export default createRule({
4
+ name: "import-graphql",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description:
9
+ "将从 @nestjs/graphql 导入的包修复为从 @nest-boot/graphql 导入",
10
+ },
11
+ fixable: "code",
12
+ schema: [],
13
+ messages: {
14
+ replaceGraphqlImport:
15
+ "应从 @nest-boot/graphql 导入,而不是 @nestjs/graphql",
16
+ },
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ return {
21
+ ImportDeclaration(node) {
22
+ // 检查是否从 @nestjs/graphql 导入
23
+ if (node.source.value === "@nestjs/graphql") {
24
+ context.report({
25
+ node,
26
+ messageId: "replaceGraphqlImport",
27
+ fix(fixer) {
28
+ // 将导入源替换为 @nest-boot/graphql
29
+ return fixer.replaceText(node.source, '"@nest-boot/graphql"');
30
+ },
31
+ });
32
+ }
33
+ },
34
+ };
35
+ },
36
+ });
@@ -0,0 +1,65 @@
1
+ import { tester } from "../../utils/tester";
2
+ import rule from "./import-mikro-orm";
3
+
4
+ tester.run("import-mikro-orm", rule, {
5
+ valid: [
6
+ // 正确的导入来源
7
+ /* typescript */ `
8
+ import { MikroOrmModule } from "@nest-boot/mikro-orm";
9
+ `,
10
+ // 从其他包导入
11
+ /* typescript */ `
12
+ import { Module } from "@nestjs/common";
13
+ `,
14
+ // 从 @mikro-orm/core 导入(不应该被替换)
15
+ /* typescript */ `
16
+ import { Entity, Property } from "@mikro-orm/core";
17
+ `,
18
+ // 命名导入
19
+ /* typescript */ `
20
+ import { InjectRepository } from "@nest-boot/mikro-orm";
21
+ `,
22
+ ],
23
+ invalid: [
24
+ // 从 @mikro-orm/nestjs 导入,应该替换为 @nest-boot/mikro-orm
25
+ {
26
+ code: /* typescript */ `
27
+ import { MikroOrmModule } from "@mikro-orm/nestjs";
28
+ `,
29
+ output: /* typescript */ `
30
+ import { MikroOrmModule } from "@nest-boot/mikro-orm";
31
+ `,
32
+ errors: [{ messageId: "replaceMikroOrmImport" }],
33
+ },
34
+ // InjectRepository 导入
35
+ {
36
+ code: /* typescript */ `
37
+ import { InjectRepository } from "@mikro-orm/nestjs";
38
+ `,
39
+ output: /* typescript */ `
40
+ import { InjectRepository } from "@nest-boot/mikro-orm";
41
+ `,
42
+ errors: [{ messageId: "replaceMikroOrmImport" }],
43
+ },
44
+ // 类型导入
45
+ {
46
+ code: /* typescript */ `
47
+ import type { MikroOrmModuleOptions } from "@mikro-orm/nestjs";
48
+ `,
49
+ output: /* typescript */ `
50
+ import type { MikroOrmModuleOptions } from "@nest-boot/mikro-orm";
51
+ `,
52
+ errors: [{ messageId: "replaceMikroOrmImport" }],
53
+ },
54
+ // 混合导入
55
+ {
56
+ code: /* typescript */ `
57
+ import { MikroOrmModule, InjectRepository } from "@mikro-orm/nestjs";
58
+ `,
59
+ output: /* typescript */ `
60
+ import { MikroOrmModule, InjectRepository } from "@nest-boot/mikro-orm";
61
+ `,
62
+ errors: [{ messageId: "replaceMikroOrmImport" }],
63
+ },
64
+ ],
65
+ });
@@ -0,0 +1,36 @@
1
+ import { createRule } from "../../utils/createRule";
2
+
3
+ export default createRule({
4
+ name: "import-mikro-orm",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description:
9
+ "将从 @mikro-orm/nestjs 导入的包修复为从 @nest-boot/mikro-orm 导入",
10
+ },
11
+ fixable: "code",
12
+ schema: [],
13
+ messages: {
14
+ replaceMikroOrmImport:
15
+ "应从 @nest-boot/mikro-orm 导入,而不是 @mikro-orm/nestjs",
16
+ },
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ return {
21
+ ImportDeclaration(node) {
22
+ // 检查是否从 @mikro-orm/nestjs 导入
23
+ if (node.source.value === "@mikro-orm/nestjs") {
24
+ context.report({
25
+ node,
26
+ messageId: "replaceMikroOrmImport",
27
+ fix(fixer) {
28
+ // 将导入源替换为 @nest-boot/mikro-orm
29
+ return fixer.replaceText(node.source, '"@nest-boot/mikro-orm"');
30
+ },
31
+ });
32
+ }
33
+ },
34
+ };
35
+ },
36
+ });
@@ -1,15 +1,17 @@
1
- import entityConstructor from "./entity-constructor";
2
- import entityPropertyNoOptionalOrNonNullAssertion from "./entity-property-no-optional-or-non-null-assertion";
3
- import entityPropertyNullable from "./entity-property-nullable";
4
- import graphqlFieldArgumentsMatchPropertyType from "./graphql-field-arguments-match-property-type";
5
- import graphqlResolverMethodReturnType from "./graphql-resolver-method-return-type";
1
+ import graphqlFieldConfigFromTypes from "./graphql/graphql-field-config-from-types";
2
+ import graphqlFieldDefiniteAssignment from "./graphql/graphql-field-definite-assignment";
3
+ import importBullmq from "./import/import-bullmq";
4
+ import importGraphql from "./import/import-graphql";
5
+ import importMikroOrm from "./import/import-mikro-orm";
6
+ import entityFieldDefiniteAssignment from "./mikro-orm/entity-field-definite-assignment";
7
+ import entityPropertyConfigFromTypes from "./mikro-orm/entity-property-config-from-types";
6
8
 
7
- export default {
8
- "entity-constructor": entityConstructor,
9
- "entity-property-no-optional-or-non-null-assertion":
10
- entityPropertyNoOptionalOrNonNullAssertion,
11
- "entity-property-nullable": entityPropertyNullable,
12
- "graphql-field-arguments-match-property-type":
13
- graphqlFieldArgumentsMatchPropertyType,
14
- "graphql-resolver-method-return-type": graphqlResolverMethodReturnType,
9
+ export const rules = {
10
+ "graphql-field-config-from-types": graphqlFieldConfigFromTypes,
11
+ "entity-property-config-from-types": entityPropertyConfigFromTypes,
12
+ "graphql-field-definite-assignment": graphqlFieldDefiniteAssignment,
13
+ "entity-field-definite-assignment": entityFieldDefiniteAssignment,
14
+ "import-bullmq": importBullmq,
15
+ "import-graphql": importGraphql,
16
+ "import-mikro-orm": importMikroOrm,
15
17
  };
@@ -0,0 +1,91 @@
1
+ import { tester } from "../../utils/tester";
2
+ import rule from "./entity-field-definite-assignment";
3
+
4
+ tester.run("entity-field-definite-assignment", rule, {
5
+ valid: [
6
+ // 有初始化值的属性,不需要 !
7
+ /* typescript */ `
8
+ @Entity()
9
+ class User {
10
+ @Property()
11
+ createdAt: Date = new Date();
12
+ }
13
+ `,
14
+ // 有 ! 的属性,没有初始化值
15
+ /* typescript */ `
16
+ @Entity()
17
+ class User {
18
+ @Property()
19
+ name!: string;
20
+ }
21
+ `,
22
+ // 可选属性,不需要 !
23
+ /* typescript */ `
24
+ @Entity()
25
+ class User {
26
+ @Property()
27
+ age?: number;
28
+ }
29
+ `,
30
+ // 可空属性且有初始化值
31
+ /* typescript */ `
32
+ @Entity()
33
+ class User {
34
+ @Property({ nullable: true })
35
+ name: string | null = null;
36
+ }
37
+ `,
38
+ // 非 Entity 类不检查
39
+ /* typescript */ `
40
+ class NotAnEntity {
41
+ @Property()
42
+ field: string;
43
+ }
44
+ `,
45
+ // 没有 @Property 装饰器不检查
46
+ /* typescript */ `
47
+ @Entity()
48
+ class User {
49
+ field: string;
50
+ }
51
+ `,
52
+ ],
53
+ invalid: [
54
+ // 没有初始化值,也没有 !
55
+ {
56
+ code: /* typescript */ `
57
+ @Entity()
58
+ class User {
59
+ @Property()
60
+ name: string;
61
+ }
62
+ `,
63
+ output: /* typescript */ `
64
+ @Entity()
65
+ class User {
66
+ @Property()
67
+ name!: string;
68
+ }
69
+ `,
70
+ errors: [{ messageId: "addDefiniteAssignment" }],
71
+ },
72
+ // 有初始化值,但也有 !
73
+ {
74
+ code: /* typescript */ `
75
+ @Entity()
76
+ class User {
77
+ @Property()
78
+ createdAt!: Date = new Date();
79
+ }
80
+ `,
81
+ output: /* typescript */ `
82
+ @Entity()
83
+ class User {
84
+ @Property()
85
+ createdAt: Date = new Date();
86
+ }
87
+ `,
88
+ errors: [{ messageId: "removeDefiniteAssignment" }],
89
+ },
90
+ ],
91
+ });