@nest-boot/eslint-plugin 7.0.0 → 7.0.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/rules/mikro-orm/entity-field-definite-assignment.js +8 -1
- package/dist/rules/mikro-orm/entity-field-definite-assignment.js.map +1 -1
- package/dist/rules/mikro-orm/entity-property-config-from-types.js +21 -1
- package/dist/rules/mikro-orm/entity-property-config-from-types.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/rules/mikro-orm/entity-field-definite-assignment.spec.ts +130 -0
- package/src/rules/mikro-orm/entity-field-definite-assignment.ts +11 -1
- package/src/rules/mikro-orm/entity-property-config-from-types.spec.ts +96 -0
- package/src/rules/mikro-orm/entity-property-config-from-types.ts +27 -1
package/package.json
CHANGED
|
@@ -49,6 +49,46 @@ tester.run("entity-field-definite-assignment", rule, {
|
|
|
49
49
|
field: string;
|
|
50
50
|
}
|
|
51
51
|
`,
|
|
52
|
+
// @Enum 装饰器 - 有 !
|
|
53
|
+
/* typescript */ `
|
|
54
|
+
@Entity()
|
|
55
|
+
class User {
|
|
56
|
+
@Enum()
|
|
57
|
+
role!: UserRole;
|
|
58
|
+
}
|
|
59
|
+
`,
|
|
60
|
+
// @OneToOne 装饰器 - 使用 Ref
|
|
61
|
+
/* typescript */ `
|
|
62
|
+
@Entity()
|
|
63
|
+
class User {
|
|
64
|
+
@OneToOne()
|
|
65
|
+
profile!: Ref<Profile>;
|
|
66
|
+
}
|
|
67
|
+
`,
|
|
68
|
+
// @OneToMany 装饰器 - 使用 Collection 初始化
|
|
69
|
+
/* typescript */ `
|
|
70
|
+
@Entity()
|
|
71
|
+
class User {
|
|
72
|
+
@OneToMany()
|
|
73
|
+
posts = new Collection<Post>(this);
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
// @ManyToOne 装饰器 - 使用 Ref
|
|
77
|
+
/* typescript */ `
|
|
78
|
+
@Entity()
|
|
79
|
+
class Post {
|
|
80
|
+
@ManyToOne()
|
|
81
|
+
author!: Ref<User>;
|
|
82
|
+
}
|
|
83
|
+
`,
|
|
84
|
+
// @ManyToMany 装饰器 - 使用 Collection 初始化
|
|
85
|
+
/* typescript */ `
|
|
86
|
+
@Entity()
|
|
87
|
+
class User {
|
|
88
|
+
@ManyToMany()
|
|
89
|
+
tags = new Collection<Tag>(this);
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
52
92
|
],
|
|
53
93
|
invalid: [
|
|
54
94
|
// 没有初始化值,也没有 !
|
|
@@ -87,5 +127,95 @@ tester.run("entity-field-definite-assignment", rule, {
|
|
|
87
127
|
`,
|
|
88
128
|
errors: [{ messageId: "removeDefiniteAssignment" }],
|
|
89
129
|
},
|
|
130
|
+
// @Enum 装饰器 - 没有初始化值,也没有 !
|
|
131
|
+
{
|
|
132
|
+
code: /* typescript */ `
|
|
133
|
+
@Entity()
|
|
134
|
+
class User {
|
|
135
|
+
@Enum()
|
|
136
|
+
role: UserRole;
|
|
137
|
+
}
|
|
138
|
+
`,
|
|
139
|
+
output: /* typescript */ `
|
|
140
|
+
@Entity()
|
|
141
|
+
class User {
|
|
142
|
+
@Enum()
|
|
143
|
+
role!: UserRole;
|
|
144
|
+
}
|
|
145
|
+
`,
|
|
146
|
+
errors: [{ messageId: "addDefiniteAssignment" }],
|
|
147
|
+
},
|
|
148
|
+
// @OneToOne 装饰器 - 没有初始化值,也没有 ! (使用 Ref)
|
|
149
|
+
{
|
|
150
|
+
code: /* typescript */ `
|
|
151
|
+
@Entity()
|
|
152
|
+
class User {
|
|
153
|
+
@OneToOne()
|
|
154
|
+
profile: Ref<Profile>;
|
|
155
|
+
}
|
|
156
|
+
`,
|
|
157
|
+
output: /* typescript */ `
|
|
158
|
+
@Entity()
|
|
159
|
+
class User {
|
|
160
|
+
@OneToOne()
|
|
161
|
+
profile!: Ref<Profile>;
|
|
162
|
+
}
|
|
163
|
+
`,
|
|
164
|
+
errors: [{ messageId: "addDefiniteAssignment" }],
|
|
165
|
+
},
|
|
166
|
+
// @OneToMany 装饰器 - 有初始化值,但也有 ! (使用 Collection)
|
|
167
|
+
{
|
|
168
|
+
code: /* typescript */ `
|
|
169
|
+
@Entity()
|
|
170
|
+
class User {
|
|
171
|
+
@OneToMany()
|
|
172
|
+
posts!: Collection<Post> = new Collection<Post>(this);
|
|
173
|
+
}
|
|
174
|
+
`,
|
|
175
|
+
output: /* typescript */ `
|
|
176
|
+
@Entity()
|
|
177
|
+
class User {
|
|
178
|
+
@OneToMany()
|
|
179
|
+
posts: Collection<Post> = new Collection<Post>(this);
|
|
180
|
+
}
|
|
181
|
+
`,
|
|
182
|
+
errors: [{ messageId: "removeDefiniteAssignment" }],
|
|
183
|
+
},
|
|
184
|
+
// @ManyToOne 装饰器 - 没有初始化值,也没有 ! (使用 Ref)
|
|
185
|
+
{
|
|
186
|
+
code: /* typescript */ `
|
|
187
|
+
@Entity()
|
|
188
|
+
class Post {
|
|
189
|
+
@ManyToOne()
|
|
190
|
+
author: Ref<User>;
|
|
191
|
+
}
|
|
192
|
+
`,
|
|
193
|
+
output: /* typescript */ `
|
|
194
|
+
@Entity()
|
|
195
|
+
class Post {
|
|
196
|
+
@ManyToOne()
|
|
197
|
+
author!: Ref<User>;
|
|
198
|
+
}
|
|
199
|
+
`,
|
|
200
|
+
errors: [{ messageId: "addDefiniteAssignment" }],
|
|
201
|
+
},
|
|
202
|
+
// @ManyToMany 装饰器 - 有初始化值,但也有 ! (使用 Collection)
|
|
203
|
+
{
|
|
204
|
+
code: /* typescript */ `
|
|
205
|
+
@Entity()
|
|
206
|
+
class User {
|
|
207
|
+
@ManyToMany()
|
|
208
|
+
tags!: Collection<Tag> = new Collection<Tag>(this);
|
|
209
|
+
}
|
|
210
|
+
`,
|
|
211
|
+
output: /* typescript */ `
|
|
212
|
+
@Entity()
|
|
213
|
+
class User {
|
|
214
|
+
@ManyToMany()
|
|
215
|
+
tags: Collection<Tag> = new Collection<Tag>(this);
|
|
216
|
+
}
|
|
217
|
+
`,
|
|
218
|
+
errors: [{ messageId: "removeDefiniteAssignment" }],
|
|
219
|
+
},
|
|
90
220
|
],
|
|
91
221
|
});
|
|
@@ -70,7 +70,17 @@ export default createRule({
|
|
|
70
70
|
|
|
71
71
|
node.body.body.forEach((member: TSESTree.ClassElement) => {
|
|
72
72
|
if (member.type !== AST_NODE_TYPES.PropertyDefinition) return;
|
|
73
|
-
if (
|
|
73
|
+
if (
|
|
74
|
+
!hasPropertyDecorator(member, [
|
|
75
|
+
"Property",
|
|
76
|
+
"Enum",
|
|
77
|
+
"OneToOne",
|
|
78
|
+
"OneToMany",
|
|
79
|
+
"ManyToOne",
|
|
80
|
+
"ManyToMany",
|
|
81
|
+
])
|
|
82
|
+
)
|
|
83
|
+
return;
|
|
74
84
|
|
|
75
85
|
const propertyName = getPropertyName(member);
|
|
76
86
|
if (!propertyName) return;
|
|
@@ -88,6 +88,36 @@ tester.run("entity-property-config-from-types", rule, {
|
|
|
88
88
|
isActive!: boolean;
|
|
89
89
|
}
|
|
90
90
|
`,
|
|
91
|
+
// Date 类型使用 t.datetime
|
|
92
|
+
/* typescript */ `
|
|
93
|
+
import { Entity, Property, Opt } from "@mikro-orm/core";
|
|
94
|
+
|
|
95
|
+
@Entity()
|
|
96
|
+
class User {
|
|
97
|
+
@Property({ type: t.datetime, defaultRaw: 'now()' })
|
|
98
|
+
createdAt: Opt<Date> = new Date();
|
|
99
|
+
}
|
|
100
|
+
`,
|
|
101
|
+
// Date 类型使用 t.date(有效的 Date 类型配置)
|
|
102
|
+
/* typescript */ `
|
|
103
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
104
|
+
|
|
105
|
+
@Entity()
|
|
106
|
+
class User {
|
|
107
|
+
@Property({ type: t.date })
|
|
108
|
+
birthDate!: Date;
|
|
109
|
+
}
|
|
110
|
+
`,
|
|
111
|
+
// Date 类型使用 t.time(有效的 Date 类型配置)
|
|
112
|
+
/* typescript */ `
|
|
113
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
114
|
+
|
|
115
|
+
@Entity()
|
|
116
|
+
class User {
|
|
117
|
+
@Property({ type: t.time })
|
|
118
|
+
workTime!: Date;
|
|
119
|
+
}
|
|
120
|
+
`,
|
|
91
121
|
// 使用 t.text 代替 t.string(有效的 string 类型配置)
|
|
92
122
|
/* typescript */ `
|
|
93
123
|
import { Entity, Property } from "@mikro-orm/core";
|
|
@@ -258,5 +288,71 @@ tester.run("entity-property-config-from-types", rule, {
|
|
|
258
288
|
`,
|
|
259
289
|
errors: [{ messageId: "alignPropertyDecoratorWithTsType" }],
|
|
260
290
|
},
|
|
291
|
+
// 空的 @Property() 应该添加 type: t.boolean
|
|
292
|
+
{
|
|
293
|
+
code: /* typescript */ `
|
|
294
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
295
|
+
|
|
296
|
+
@Entity()
|
|
297
|
+
class User {
|
|
298
|
+
@Property()
|
|
299
|
+
published!: boolean;
|
|
300
|
+
}
|
|
301
|
+
`,
|
|
302
|
+
output: /* typescript */ `
|
|
303
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
304
|
+
|
|
305
|
+
@Entity()
|
|
306
|
+
class User {
|
|
307
|
+
@Property({ type: t.boolean })
|
|
308
|
+
published!: boolean;
|
|
309
|
+
}
|
|
310
|
+
`,
|
|
311
|
+
errors: [{ messageId: "alignPropertyDecoratorWithTsType" }],
|
|
312
|
+
},
|
|
313
|
+
// 空的 @Property() 应该添加 type: t.datetime(Date 类型)
|
|
314
|
+
{
|
|
315
|
+
code: /* typescript */ `
|
|
316
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
317
|
+
|
|
318
|
+
@Entity()
|
|
319
|
+
class User {
|
|
320
|
+
@Property()
|
|
321
|
+
createdAt!: Date;
|
|
322
|
+
}
|
|
323
|
+
`,
|
|
324
|
+
output: /* typescript */ `
|
|
325
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
326
|
+
|
|
327
|
+
@Entity()
|
|
328
|
+
class User {
|
|
329
|
+
@Property({ type: t.datetime })
|
|
330
|
+
createdAt!: Date;
|
|
331
|
+
}
|
|
332
|
+
`,
|
|
333
|
+
errors: [{ messageId: "alignPropertyDecoratorWithTsType" }],
|
|
334
|
+
},
|
|
335
|
+
// Date 类型配置错误应该修正为 t.datetime
|
|
336
|
+
{
|
|
337
|
+
code: /* typescript */ `
|
|
338
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
339
|
+
|
|
340
|
+
@Entity()
|
|
341
|
+
class User {
|
|
342
|
+
@Property({ type: t.string })
|
|
343
|
+
createdAt!: Date;
|
|
344
|
+
}
|
|
345
|
+
`,
|
|
346
|
+
output: /* typescript */ `
|
|
347
|
+
import { Entity, Property } from "@mikro-orm/core";
|
|
348
|
+
|
|
349
|
+
@Entity()
|
|
350
|
+
class User {
|
|
351
|
+
@Property({ type: t.datetime })
|
|
352
|
+
createdAt!: Date;
|
|
353
|
+
}
|
|
354
|
+
`,
|
|
355
|
+
errors: [{ messageId: "alignPropertyDecoratorWithTsType" }],
|
|
356
|
+
},
|
|
261
357
|
],
|
|
262
358
|
});
|
|
@@ -100,7 +100,7 @@ export default createRule<
|
|
|
100
100
|
case "boolean":
|
|
101
101
|
return "t.boolean"; // 默认使用 t.boolean
|
|
102
102
|
case "Date":
|
|
103
|
-
return
|
|
103
|
+
return "t.datetime"; // 默认使用 t.datetime
|
|
104
104
|
case "GraphQLJSONObject":
|
|
105
105
|
case "Record":
|
|
106
106
|
return "t.json";
|
|
@@ -206,6 +206,21 @@ export default createRule<
|
|
|
206
206
|
return false;
|
|
207
207
|
};
|
|
208
208
|
|
|
209
|
+
const isValidDateType = (typeConfig: string | null): boolean => {
|
|
210
|
+
if (!typeConfig) return false;
|
|
211
|
+
|
|
212
|
+
// 接受 t.datetime, t.date, t.time
|
|
213
|
+
if (
|
|
214
|
+
typeConfig === "t.datetime" ||
|
|
215
|
+
typeConfig === "t.date" ||
|
|
216
|
+
typeConfig === "t.time"
|
|
217
|
+
) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return false;
|
|
222
|
+
};
|
|
223
|
+
|
|
209
224
|
const getIdentifierName = (node: TSESTree.TypeNode): string | null => {
|
|
210
225
|
if (
|
|
211
226
|
node.type === AST_NODE_TYPES.TSTypeReference &&
|
|
@@ -624,6 +639,12 @@ export default createRule<
|
|
|
624
639
|
) {
|
|
625
640
|
// 保留有效的 number 类型配置
|
|
626
641
|
finalInfo.propertyType = currentConfig.type;
|
|
642
|
+
} else if (
|
|
643
|
+
info.propertyType === "t.datetime" &&
|
|
644
|
+
isValidDateType(currentConfig.type)
|
|
645
|
+
) {
|
|
646
|
+
// 保留有效的 Date 类型配置
|
|
647
|
+
finalInfo.propertyType = currentConfig.type;
|
|
627
648
|
} else if (
|
|
628
649
|
info.isArray &&
|
|
629
650
|
info.arrayElementTypeName === "number" &&
|
|
@@ -1063,6 +1084,11 @@ export default createRule<
|
|
|
1063
1084
|
isValidNumberType(currentConfig.type)
|
|
1064
1085
|
) {
|
|
1065
1086
|
// 当前配置是有效的 number 类型配置,不需要修改
|
|
1087
|
+
} else if (
|
|
1088
|
+
expectedType === "t.datetime" &&
|
|
1089
|
+
isValidDateType(currentConfig.type)
|
|
1090
|
+
) {
|
|
1091
|
+
// 当前配置是有效的 Date 类型配置,不需要修改
|
|
1066
1092
|
} else if (
|
|
1067
1093
|
expectedType === "t.array" &&
|
|
1068
1094
|
typeInfo.arrayElementTypeName === "number" &&
|