@darraghor/eslint-plugin-nestjs-typed 6.0.0-rc.9 → 6.0.0
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/README.md +58 -16
- package/dist/configs/base.d.ts +1 -1
- package/dist/configs/base.js +3 -4
- package/dist/configs/noSwagger.d.ts +2 -1
- package/dist/configs/noSwagger.js +3 -4
- package/dist/configs/recommended.d.ts +2 -1
- package/dist/configs/recommended.js +3 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +25 -57
- package/dist/rules/allPropertiesAreWhitelisted/allPropertiesAreWhitelisted.js +11 -13
- package/dist/rules/allPropertiesHaveExplicitDefined/allPropertiesHaveExplicitDefined.js +15 -17
- package/dist/rules/apiEnumPropertyBestPractices/apiEnumPropertyBestPractices.d.ts +1 -1
- package/dist/rules/apiEnumPropertyBestPractices/apiEnumPropertyBestPractices.js +17 -22
- package/dist/rules/apiEnumPropertyBestPractices/enumTestResultModel.js +2 -6
- package/dist/rules/apiMethodsShouldBeGuarded/apiMethodsShouldBeGuarded.js +12 -16
- package/dist/rules/apiMethodsShouldSpecifyApiOperation/apiMethodsShouldSpecifyApiOperation.js +9 -13
- package/dist/rules/apiMethodsShouldSpecifyApiResponse/apiMethodsShouldSpecifyApiResponse.js +9 -13
- package/dist/rules/apiPropertyMatchesPropertyOptionality/apiPropertyMatchesPropertyOptionality.js +13 -18
- package/dist/rules/apiPropertyReturningArrayShouldSetArray/apiPropertyReturningArrayShouldSetArray.d.ts +1 -1
- package/dist/rules/apiPropertyReturningArrayShouldSetArray/apiPropertyReturningArrayShouldSetArray.js +17 -24
- package/dist/rules/apiPropertyReturningArrayShouldSetArray/arraySetResultModel.js +2 -5
- package/dist/rules/controllerDecoratedHasApiTags/controllerDecoratedHasApiTags.js +9 -13
- package/dist/rules/index.d.ts +3 -3
- package/dist/rules/index.js +36 -41
- package/dist/rules/injectablesShouldBeProvided/injectableShouldBeProvided.js +13 -18
- package/dist/rules/noDuplicateDecorators/noDuplicateDecorators.js +10 -14
- package/dist/rules/paramDecoratorNameMatchesRouteParam/paramDecoratorNameMatchesRouteParam.js +19 -26
- package/dist/rules/paramDecoratorNameMatchesRouteParam/rule.testData.js +3 -6
- package/dist/rules/providerInjectedShouldMatchFactory/ProviderInjectedShouldMatchFactory.js +12 -18
- package/dist/rules/shouldSpecifyForbidUnknownValues/shouldSpecifyForbidUnknownValuesRule.js +20 -27
- package/dist/rules/sortModuleMetadataArrays/sortModuleMetadataArrays.js +18 -23
- package/dist/rules/validateNestedOfArrayShouldSetEach/arraySetResultModel.js +2 -5
- package/dist/rules/validateNestedOfArrayShouldSetEach/validateNestedOfArrayShouldSetEach.d.ts +1 -1
- package/dist/rules/validateNestedOfArrayShouldSetEach/validateNestedOfArrayShouldSetEach.js +14 -21
- package/dist/rules/validateNonPrimitiveNeedsTypeDecorator/validateNonPrimitiveNeedsDecorators.js +29 -33
- package/dist/testing/fixtureSetup.js +4 -10
- package/dist/testing/preRun.js +2 -4
- package/dist/utils/ast.js +4 -7
- package/dist/utils/createRule.js +3 -6
- package/dist/utils/files/customFileEnumeratorWrapper.js +9 -16
- package/dist/utils/files/isFilteredPath.js +2 -4
- package/dist/utils/nestModules/models/NestProvidedInjectablesMap.js +2 -6
- package/dist/utils/nestModules/nestModuleAstParser.d.ts +1 -1
- package/dist/utils/nestModules/nestModuleAstParser.js +9 -12
- package/dist/utils/nestModules/nestProvidedInjectableMapper.d.ts +1 -1
- package/dist/utils/nestModules/nestProvidedInjectableMapper.js +14 -52
- package/dist/utils/nestModules/nestProvidedInjectableMapper.testData.d.ts +1 -1
- package/dist/utils/nestModules/nestProvidedInjectableMapper.testData.js +9 -12
- package/dist/utils/nestModules/nestProviderAstParser.d.ts +1 -1
- package/dist/utils/nestModules/nestProviderAstParser.js +13 -16
- package/dist/utils/typedTokenHelpers.js +25 -64
- package/dist/utils/wellKnownSelectors.js +2 -5
- package/package.json +4 -3
- package/dist/configs/index.d.ts +0 -11
- package/dist/configs/index.js +0 -13
package/README.md
CHANGED
|
@@ -12,6 +12,18 @@
|
|
|
12
12
|
- Version `3.x` supports Eslint version `>=8.x` and typescript eslint parser `^5`
|
|
13
13
|
- Version `2.x` supports Eslint version `<=7.x` and typescript eslint parser `^4`
|
|
14
14
|
|
|
15
|
+
## Eslint 9.x support
|
|
16
|
+
|
|
17
|
+
I have updated the configs to work with eslint 9.x. This is a breaking change.
|
|
18
|
+
|
|
19
|
+
If you are using eslint 8.x you should use version 5.x of this plugin.
|
|
20
|
+
|
|
21
|
+
I did try to leave the old style configs in place but I haven't tested them properly. If you have any issues please submit a PR.
|
|
22
|
+
|
|
23
|
+
See [How to configure](#to-configure) for more info.
|
|
24
|
+
|
|
25
|
+
## TS Eslint version support
|
|
26
|
+
|
|
15
27
|
There are breaking changes between versions of ts-eslint.
|
|
16
28
|
|
|
17
29
|
typescript eslint parser supports a range of typescript versions but there can be a delay in supporting the latest versions.
|
|
@@ -118,29 +130,59 @@ pnpm add class-validator
|
|
|
118
130
|
|
|
119
131
|
## To configure
|
|
120
132
|
|
|
121
|
-
Update your eslint with the plugin import and add the
|
|
133
|
+
Update your flat eslint config with the plugin import and add the flatRecommended rule set.
|
|
134
|
+
|
|
135
|
+
My config looks something like this. I'm 99% sure that you have to setup typescript parser also.
|
|
122
136
|
|
|
123
137
|
```ts
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
138
|
+
import eslintNestJs from "@darraghor/eslint-plugin-nestjs-typed";
|
|
139
|
+
// ... and all your other imports
|
|
140
|
+
export default tseslint.config(
|
|
141
|
+
eslint.configs.recommended,
|
|
142
|
+
tseslint.configs.strictTypeChecked,
|
|
143
|
+
tseslint.configs.stylisticTypeChecked,
|
|
144
|
+
{
|
|
145
|
+
languageOptions: {
|
|
146
|
+
globals: {
|
|
147
|
+
...globals.node,
|
|
148
|
+
...globals.jest,
|
|
149
|
+
},
|
|
150
|
+
parser,
|
|
151
|
+
ecmaVersion: 2022,
|
|
152
|
+
sourceType: "module",
|
|
153
|
+
parserOptions: {
|
|
154
|
+
project: "tsconfig.json",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
134
157
|
},
|
|
135
|
-
|
|
158
|
+
eslintNestJs.configs.flatRecommended // This is the recommended ruleset for this plugin
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For ESlint 8 I export the old style config in the "classicConfig" export.
|
|
163
|
+
|
|
164
|
+
I believe it would work something like this...
|
|
165
|
+
|
|
166
|
+
````ts
|
|
167
|
+
import {
|
|
168
|
+
classicPlugin,
|
|
169
|
+
} from "@darraghor/eslint-plugin-nestjs-typed";
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
plugins: [
|
|
174
|
+
classicPlugin,
|
|
175
|
+
],
|
|
136
176
|
};
|
|
177
|
+
|
|
137
178
|
```
|
|
138
179
|
|
|
180
|
+
|
|
139
181
|
Note: the injectables test scans your whole project. It's best to filter out ts things that don't matter - use `filterFromPaths` configuration setting for this. See the rule documentation for more info.
|
|
140
182
|
|
|
141
|
-
There are some defaults already applied.
|
|
183
|
+
There are some sensible defaults already applied.
|
|
142
184
|
|
|
143
|
-
Note: You can easily turn off all the swagger rules if you don't use swagger by adding the `
|
|
185
|
+
Note: You can easily turn off all the swagger rules if you don't use swagger by adding the `flatNoSwagger` rule set AFTER the recommended rule set.
|
|
144
186
|
|
|
145
187
|
```ts
|
|
146
188
|
// all the other config
|
|
@@ -148,11 +190,11 @@ Note: You can easily turn off all the swagger rules if you don't use swagger by
|
|
|
148
190
|
"plugin:@darraghor/nestjs-typed/no-swagger"
|
|
149
191
|
],
|
|
150
192
|
// more config
|
|
151
|
-
|
|
193
|
+
````
|
|
152
194
|
|
|
153
195
|
Disable a single rule with the full name e.g. in your eslint configuration...
|
|
154
196
|
|
|
155
|
-
```
|
|
197
|
+
```ts
|
|
156
198
|
rules: {
|
|
157
199
|
"@darraghor/nestjs-typed/api-property-returning-array-should-set-array":
|
|
158
200
|
"off",
|
package/dist/configs/base.d.ts
CHANGED
package/dist/configs/base.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
module.exports = {
|
|
1
|
+
export default {
|
|
3
2
|
parser: "@typescript-eslint/parser",
|
|
4
3
|
parserOptions: { sourceType: "module" },
|
|
5
|
-
plugins: ["@
|
|
4
|
+
plugins: ["@darraghor/nestjs-typed"],
|
|
6
5
|
};
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWdzL2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsZUFBZTtJQUNYLE1BQU0sRUFBRSwyQkFBMkI7SUFDbkMsYUFBYSxFQUFFLEVBQUMsVUFBVSxFQUFFLFFBQVEsRUFBQztJQUNyQyxPQUFPLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQztDQUNSLENBQUMifQ==
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// Should turn off swagger rules for folks not using swagger typings
|
|
3
|
-
const rules = {
|
|
2
|
+
export const rules = {
|
|
4
3
|
"@darraghor/nestjs-typed/api-property-matches-property-optionality": "off",
|
|
5
4
|
"@darraghor/nestjs-typed/api-method-should-specify-api-response": "off",
|
|
6
5
|
"@darraghor/nestjs-typed/api-method-should-specify-api-operation": "off",
|
|
@@ -8,8 +7,8 @@ const rules = {
|
|
|
8
7
|
"@darraghor/nestjs-typed/api-enum-property-best-practices": "off",
|
|
9
8
|
"@darraghor/nestjs-typed/api-property-returning-array-should-set-array": "off",
|
|
10
9
|
};
|
|
11
|
-
|
|
10
|
+
export default {
|
|
12
11
|
extends: ["./configs/base"],
|
|
13
12
|
rules,
|
|
14
13
|
};
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9Td2FnZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZ3Mvbm9Td2FnZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQWdDO0lBQzlDLG1FQUFtRSxFQUFFLEtBQUs7SUFDMUUsZ0VBQWdFLEVBQUUsS0FBSztJQUN2RSxpRUFBaUUsRUFBRSxLQUFLO0lBQ3hFLDREQUE0RCxFQUFFLEtBQUs7SUFDbkUsMERBQTBELEVBQUUsS0FBSztJQUNqRSx1RUFBdUUsRUFDbkUsS0FBSztDQUNaLENBQUM7QUFFRixlQUFlO0lBQ1gsT0FBTyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7SUFDM0IsS0FBSztDQUNSLENBQUMifQ==
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const rules = {
|
|
1
|
+
export const rules = {
|
|
3
2
|
"@darraghor/nestjs-typed/provided-injected-should-match-factory-parameters": "error",
|
|
4
3
|
"@darraghor/nestjs-typed/injectable-should-be-provided": [
|
|
5
4
|
"error",
|
|
@@ -24,8 +23,8 @@ const rules = {
|
|
|
24
23
|
"@darraghor/nestjs-typed/sort-module-metadata-arrays": "off",
|
|
25
24
|
"@darraghor/nestjs-typed/no-duplicate-decorators": "error",
|
|
26
25
|
};
|
|
27
|
-
|
|
26
|
+
export default {
|
|
28
27
|
extends: ["./configs/base"],
|
|
29
28
|
rules,
|
|
30
29
|
};
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb21tZW5kZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uZmlncy9yZWNvbW1lbmRlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQWdDO0lBQzlDLDJFQUEyRSxFQUN2RSxPQUFPO0lBQ1gsdURBQXVELEVBQUU7UUFDckQsT0FBTztRQUNQO1lBQ0ksR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQ3BCLGVBQWUsRUFBRSxDQUFDLGNBQWMsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDO1NBQ3hEO0tBQ0o7SUFDRCxtRUFBbUUsRUFDL0QsT0FBTztJQUNYLGdFQUFnRSxFQUFFLE9BQU87SUFDekUsNERBQTRELEVBQUUsT0FBTztJQUNyRSwwREFBMEQsRUFBRSxPQUFPO0lBQ25FLHVFQUF1RSxFQUNuRSxPQUFPO0lBQ1gsOERBQThELEVBQUUsT0FBTztJQUN2RSxrRUFBa0UsRUFBRSxPQUFPO0lBQzNFLCtFQUErRSxFQUMzRSxPQUFPO0lBQ1gsa0VBQWtFLEVBQUUsT0FBTztJQUMzRSx3REFBd0QsRUFBRSxPQUFPO0lBQ2pFLDhEQUE4RCxFQUFFLE9BQU87SUFDdkUsdURBQXVELEVBQUUsS0FBSztJQUM5RCxpRUFBaUUsRUFBRSxLQUFLO0lBQ3hFLHFEQUFxRCxFQUFFLEtBQUs7SUFDNUQsaURBQWlELEVBQUUsT0FBTztDQUM3RCxDQUFDO0FBQ0YsZUFBZTtJQUNYLE9BQU8sRUFBRSxDQUFDLGdCQUFnQixDQUFDO0lBQzNCLEtBQUs7Q0FDUixDQUFDIn0=
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { FlatConfig } from "@typescript-eslint/utils/ts-eslint";
|
|
2
2
|
import { TSESLint } from "@typescript-eslint/utils";
|
|
3
3
|
export declare const parser: TSESLint.FlatConfig.Parser;
|
|
4
|
-
export declare const plugin: TSESLint.FlatConfig.Plugin;
|
|
5
4
|
declare const classicPlugin: {
|
|
6
5
|
configs: {
|
|
7
6
|
recommended: {
|
|
@@ -20,7 +19,7 @@ declare const classicPlugin: {
|
|
|
20
19
|
src: string[];
|
|
21
20
|
filterFromPaths: string[];
|
|
22
21
|
}], unknown, TSESLint.RuleListener>;
|
|
23
|
-
"no-duplicate-decorators": TSESLint.RuleModule<"noDuplicateDecorators", import("./rules/noDuplicateDecorators/noDuplicateDecorators").NoDuplicateDecoratorsOptions, unknown, TSESLint.RuleListener>;
|
|
22
|
+
"no-duplicate-decorators": TSESLint.RuleModule<"noDuplicateDecorators", import("./rules/noDuplicateDecorators/noDuplicateDecorators.js").NoDuplicateDecoratorsOptions, unknown, TSESLint.RuleListener>;
|
|
24
23
|
"provided-injected-should-match-factory-parameters": TSESLint.RuleModule<"mainMessage", [], unknown, TSESLint.RuleListener>;
|
|
25
24
|
"controllers-should-supply-api-tags": TSESLint.RuleModule<"shouldUseApiTagDecorator", [], unknown, TSESLint.RuleListener>;
|
|
26
25
|
"api-method-should-specify-api-response": TSESLint.RuleModule<"shouldSpecifyApiResponse", [], unknown, TSESLint.RuleListener>;
|
|
@@ -29,17 +28,18 @@ declare const classicPlugin: {
|
|
|
29
28
|
"api-property-returning-array-should-set-array": TSESLint.RuleModule<"shouldSetArrayPropertyTrue" | "shouldSetArrayPropertyFalse", [], unknown, TSESLint.RuleListener>;
|
|
30
29
|
"should-specify-forbid-unknown-values": TSESLint.RuleModule<"shouldSpecifyForbidUnknownValues", [], unknown, TSESLint.RuleListener>;
|
|
31
30
|
"param-decorator-name-matches-route-param": TSESLint.RuleModule<"paramIdentifierDoesntNeedColon" | "paramIdentifierShouldMatch", [], unknown, TSESLint.RuleListener>;
|
|
32
|
-
"validated-non-primitive-property-needs-type-decorator": TSESLint.RuleModule<"shouldUseTypeDecorator" | "autofixWithTypeDecorator", import("./rules/validateNonPrimitiveNeedsTypeDecorator/validateNonPrimitiveNeedsDecorators").ValidateNonPrimitivePropertyTypeDecoratorOptions, unknown, TSESLint.RuleListener>;
|
|
31
|
+
"validated-non-primitive-property-needs-type-decorator": TSESLint.RuleModule<"shouldUseTypeDecorator" | "autofixWithTypeDecorator", import("./rules/validateNonPrimitiveNeedsTypeDecorator/validateNonPrimitiveNeedsDecorators.js").ValidateNonPrimitivePropertyTypeDecoratorOptions, unknown, TSESLint.RuleListener>;
|
|
33
32
|
"validate-nested-of-array-should-set-each": TSESLint.RuleModule<"shouldSetEachPropertyTrue" | "shouldSetEachPropertyFalse", [], unknown, TSESLint.RuleListener>;
|
|
34
33
|
"all-properties-are-whitelisted": TSESLint.RuleModule<"missing-property-decorator", [], unknown, TSESLint.RuleListener>;
|
|
35
34
|
"api-methods-should-be-guarded": TSESLint.RuleModule<"apiMethodsShouldBeGuarded", [], unknown, TSESLint.RuleListener>;
|
|
36
|
-
"sort-module-metadata-arrays": TSESLint.RuleModule<"moduleMetadataArraysAreSorted", import("./rules/sortModuleMetadataArrays/sortModuleMetadataArrays").RuleOptions, unknown, TSESLint.RuleListener>;
|
|
35
|
+
"sort-module-metadata-arrays": TSESLint.RuleModule<"moduleMetadataArraysAreSorted", import("./rules/sortModuleMetadataArrays/sortModuleMetadataArrays.js").RuleOptions, unknown, TSESLint.RuleListener>;
|
|
37
36
|
};
|
|
38
37
|
meta: {
|
|
39
38
|
name: string;
|
|
40
39
|
version: string;
|
|
41
40
|
};
|
|
42
41
|
};
|
|
42
|
+
export declare const plugin: TSESLint.FlatConfig.Plugin;
|
|
43
43
|
export { classicPlugin };
|
|
44
44
|
export type ConfigArray = TSESLint.FlatConfig.ConfigArray;
|
|
45
45
|
declare const _default: {
|
package/dist/index.js
CHANGED
|
@@ -1,68 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.classicPlugin = exports.plugin = exports.parser = void 0;
|
|
40
|
-
const configs_1 = __importDefault(require("./configs"));
|
|
41
|
-
const rules_1 = __importDefault(require("./rules"));
|
|
42
|
-
const parserBase = __importStar(require("@typescript-eslint/parser"));
|
|
43
|
-
const eslint_plugin_1 = __importDefault(require("@typescript-eslint/eslint-plugin"));
|
|
1
|
+
import noSwagger from "./configs/noSwagger.js";
|
|
2
|
+
import recommended from "./configs/recommended.js";
|
|
3
|
+
import rules from "./rules/index.js";
|
|
4
|
+
import * as parserBase from "@typescript-eslint/parser";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
import { dirname, resolve } from "path";
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const { name, version } = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
|
|
44
13
|
// Most of this is copied and simplified from https://github.com/typescript-eslint/typescript-eslint/blob/v8.22.0/packages/typescript-eslint/src/configs/recommended.ts
|
|
45
14
|
// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
47
|
-
const { name, version } = require("../package.json");
|
|
48
15
|
const meta = {
|
|
49
16
|
name,
|
|
50
17
|
version,
|
|
51
18
|
};
|
|
52
|
-
|
|
19
|
+
export const parser = {
|
|
53
20
|
meta: parserBase.meta,
|
|
54
21
|
parseForESLint: parserBase.parseForESLint,
|
|
55
22
|
};
|
|
56
|
-
exports.plugin = eslint_plugin_1.default;
|
|
57
23
|
const classicPlugin = {
|
|
58
24
|
configs: {
|
|
59
|
-
recommended:
|
|
60
|
-
"no-swagger":
|
|
25
|
+
recommended: recommended,
|
|
26
|
+
"no-swagger": noSwagger,
|
|
61
27
|
},
|
|
62
|
-
rules
|
|
28
|
+
rules,
|
|
63
29
|
meta,
|
|
64
30
|
};
|
|
65
|
-
|
|
31
|
+
export const plugin = classicPlugin;
|
|
66
32
|
const flatBaseConfig = (plugin, parser) => {
|
|
67
33
|
const baseConfig = {
|
|
68
34
|
name: "@darraghor/nestjs-typed/base",
|
|
@@ -76,23 +42,25 @@ const flatBaseConfig = (plugin, parser) => {
|
|
|
76
42
|
};
|
|
77
43
|
return baseConfig;
|
|
78
44
|
};
|
|
45
|
+
// export the classic plugin configs
|
|
46
|
+
export { classicPlugin };
|
|
79
47
|
// export the flat configs
|
|
80
|
-
|
|
81
|
-
plugin
|
|
48
|
+
export default {
|
|
49
|
+
plugin,
|
|
82
50
|
configs: {
|
|
83
51
|
flatRecommended: [
|
|
84
|
-
flatBaseConfig(
|
|
52
|
+
flatBaseConfig(plugin, parser),
|
|
85
53
|
{
|
|
86
54
|
name: "@darraghor/nestjs-typed/recommended",
|
|
87
|
-
rules:
|
|
55
|
+
rules: recommended.rules,
|
|
88
56
|
},
|
|
89
57
|
],
|
|
90
58
|
flatNoSwagger: [
|
|
91
59
|
{
|
|
92
60
|
name: "@darraghor/nestjs-typed/no-swagger",
|
|
93
|
-
rules:
|
|
61
|
+
rules: noSwagger.rules,
|
|
94
62
|
},
|
|
95
63
|
],
|
|
96
64
|
},
|
|
97
65
|
};
|
|
98
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxTQUFTLE1BQU0sd0JBQXdCLENBQUM7QUFDL0MsT0FBTyxXQUFXLE1BQU0sMEJBQTBCLENBQUM7QUFDbkQsT0FBTyxLQUFLLE1BQU0sa0JBQWtCLENBQUM7QUFFckMsT0FBTyxLQUFLLFVBQVUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sS0FBSyxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxJQUFJLENBQUM7QUFDaEMsT0FBTyxFQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFFdEMsZ0VBQWdFO0FBQ2hFLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2xELGdFQUFnRTtBQUNoRSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDdEMsTUFBTSxFQUFDLElBQUksRUFBRSxPQUFPLEVBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUM5QixZQUFZLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUk5RCxDQUFDO0FBQ0YsdUtBQXVLO0FBRXZLLHNIQUFzSDtBQUV0SCxNQUFNLElBQUksR0FBRztJQUNULElBQUk7SUFDSixPQUFPO0NBQ1YsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBK0I7SUFDOUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO0lBQ3JCLGNBQWMsRUFBRSxVQUFVLENBQUMsY0FBYztDQUM1QyxDQUFDO0FBRUYsTUFBTSxhQUFhLEdBQUc7SUFDbEIsT0FBTyxFQUFFO1FBQ0wsV0FBVyxFQUFFLFdBQVc7UUFDeEIsWUFBWSxFQUFFLFNBQVM7S0FDMUI7SUFDRCxLQUFLO0lBQ0wsSUFBSTtDQUNpQixDQUFDO0FBRTFCLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBK0IsYUFHakQsQ0FBQztBQUNGLE1BQU0sY0FBYyxHQUFHLENBQ25CLE1BQXlCLEVBQ3pCLE1BQXlCLEVBQ1IsRUFBRTtJQUNuQixNQUFNLFVBQVUsR0FBc0I7UUFDbEMsSUFBSSxFQUFFLDhCQUE4QjtRQUNwQyxlQUFlLEVBQUU7WUFDYixNQUFNO1lBQ04sVUFBVSxFQUFFLFFBQVE7U0FDdkI7UUFDRCxPQUFPLEVBQUU7WUFDTCx5QkFBeUIsRUFBRSxNQUFNO1NBQ3BDO0tBQ0osQ0FBQztJQUNGLE9BQU8sVUFBVSxDQUFDO0FBQ3RCLENBQUMsQ0FBQztBQUVGLG9DQUFvQztBQUNwQyxPQUFPLEVBQUMsYUFBYSxFQUFDLENBQUM7QUFFdkIsMEJBQTBCO0FBQzFCLGVBQWU7SUFDWCxNQUFNO0lBQ04sT0FBTyxFQUFFO1FBQ0wsZUFBZSxFQUFFO1lBQ2IsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUM7WUFDOUI7Z0JBQ0ksSUFBSSxFQUFFLHFDQUFxQztnQkFDM0MsS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLO2FBQzNCO1NBQ0o7UUFDRCxhQUFhLEVBQUU7WUFDWDtnQkFDSSxJQUFJLEVBQUUsb0NBQW9DO2dCQUMxQyxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7YUFDekI7U0FDSjtLQUlKO0NBQ0osQ0FBQyJ9
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const typedTokenHelpers_1 = require("../../utils/typedTokenHelpers");
|
|
6
|
-
const rule = (0, createRule_1.createRule)({
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../../utils/createRule.js";
|
|
3
|
+
import { typedTokenHelpers } from "../../utils/typedTokenHelpers.js";
|
|
4
|
+
const rule = createRule({
|
|
7
5
|
name: "all-properties-are-whitelisted",
|
|
8
6
|
meta: {
|
|
9
7
|
docs: {
|
|
@@ -19,18 +17,18 @@ const rule = (0, createRule_1.createRule)({
|
|
|
19
17
|
create: function (context) {
|
|
20
18
|
return {
|
|
21
19
|
ClassDeclaration(node) {
|
|
22
|
-
const program =
|
|
20
|
+
const program = typedTokenHelpers.getRootProgram(node);
|
|
23
21
|
const withDecorator = [];
|
|
24
22
|
const withoutDecorator = [];
|
|
25
23
|
for (const element of node.body.body) {
|
|
26
|
-
if (element.type !==
|
|
24
|
+
if (element.type !== AST_NODE_TYPES.PropertyDefinition) {
|
|
27
25
|
continue;
|
|
28
26
|
}
|
|
29
27
|
const hasDecorator = element.decorators.some((decorator) => decorator.expression.type ===
|
|
30
|
-
|
|
28
|
+
AST_NODE_TYPES.CallExpression &&
|
|
31
29
|
decorator.expression.callee.type ===
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
AST_NODE_TYPES.Identifier &&
|
|
31
|
+
typedTokenHelpers.decoratorIsClassValidatorDecorator(program, decorator));
|
|
34
32
|
if (hasDecorator) {
|
|
35
33
|
withDecorator.push(element);
|
|
36
34
|
}
|
|
@@ -50,5 +48,5 @@ const rule = (0, createRule_1.createRule)({
|
|
|
50
48
|
};
|
|
51
49
|
},
|
|
52
50
|
});
|
|
53
|
-
|
|
54
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
51
|
+
export default rule;
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsUHJvcGVydGllc0FyZVdoaXRlbGlzdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bGVzL2FsbFByb3BlcnRpZXNBcmVXaGl0ZWxpc3RlZC9hbGxQcm9wZXJ0aWVzQXJlV2hpdGVsaXN0ZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGNBQWMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRSxNQUFNLElBQUksR0FBRyxVQUFVLENBQW1DO0lBQ3RELElBQUksRUFBRSxnQ0FBZ0M7SUFDdEMsSUFBSSxFQUFFO1FBQ0YsSUFBSSxFQUFFO1lBQ0YsV0FBVyxFQUFFLHdDQUF3QztTQUN4RDtRQUNELFFBQVEsRUFBRTtZQUNOLDRCQUE0QixFQUN4Qix5RkFBeUY7U0FDaEc7UUFDRCxJQUFJLEVBQUUsU0FBUztRQUNmLE1BQU0sRUFBRSxFQUFFO0tBQ2I7SUFDRCxjQUFjLEVBQUUsRUFBRTtJQUNsQixNQUFNLEVBQUUsVUFBVSxPQUFPO1FBQ3JCLE9BQU87WUFDSCxnQkFBZ0IsQ0FBQyxJQUErQjtnQkFDNUMsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2RCxNQUFNLGFBQWEsR0FBa0MsRUFBRSxDQUFDO2dCQUN4RCxNQUFNLGdCQUFnQixHQUFrQyxFQUFFLENBQUM7Z0JBQzNELEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDbkMsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO3dCQUNyRCxTQUFTO29CQUNiLENBQUM7b0JBQ0QsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQ3hDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FDVixTQUFTLENBQUMsVUFBVSxDQUFDLElBQUk7d0JBQ3JCLGNBQWMsQ0FBQyxjQUFjO3dCQUNqQyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJOzRCQUM1QixjQUFjLENBQUMsVUFBVTt3QkFDN0IsaUJBQWlCLENBQUMsa0NBQWtDLENBQ2hELE9BQU8sRUFDUCxTQUFTLENBQ1osQ0FDUixDQUFDO29CQUNGLElBQUksWUFBWSxFQUFFLENBQUM7d0JBQ2YsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDaEMsQ0FBQzt5QkFBTSxDQUFDO3dCQUNKLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDbkMsQ0FBQztnQkFDTCxDQUFDO2dCQUNELElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksZ0JBQWdCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUMxRCxLQUFLLE1BQU0sT0FBTyxJQUFJLGdCQUFnQixFQUFFLENBQUM7d0JBQ3JDLE9BQU8sQ0FBQyxNQUFNLENBQUM7NEJBQ1gsSUFBSSxFQUFFLE9BQU87NEJBQ2IsU0FBUyxFQUFFLDRCQUE0Qjt5QkFDMUMsQ0FBQyxDQUFDO29CQUNQLENBQUM7Z0JBQ0wsQ0FBQztZQUNMLENBQUM7U0FDSixDQUFDO0lBQ04sQ0FBQztDQUNKLENBQUMsQ0FBQztBQUVILGVBQWUsSUFBSSxDQUFDIn0=
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const typedTokenHelpers_1 = require("../../utils/typedTokenHelpers");
|
|
8
|
-
const rule = (0, createRule_1.createRule)({
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
|
|
2
|
+
import { isNullableType } from "@typescript-eslint/type-utils";
|
|
3
|
+
import { getPropertiesDefinitions } from "../../utils/ast.js";
|
|
4
|
+
import { createRule } from "../../utils/createRule.js";
|
|
5
|
+
import { typedTokenHelpers } from "../../utils/typedTokenHelpers.js";
|
|
6
|
+
const rule = createRule({
|
|
9
7
|
name: "all-properties-have-explicit-defined",
|
|
10
8
|
meta: {
|
|
11
9
|
docs: {
|
|
@@ -24,13 +22,13 @@ const rule = (0, createRule_1.createRule)({
|
|
|
24
22
|
},
|
|
25
23
|
defaultOptions: [],
|
|
26
24
|
create: function (context) {
|
|
27
|
-
const service =
|
|
25
|
+
const service = ESLintUtils.getParserServices(context);
|
|
28
26
|
const checker = service.program.getTypeChecker();
|
|
29
27
|
return {
|
|
30
28
|
ClassDeclaration(node) {
|
|
31
29
|
const propertyDefinitionsWithDecoratorsStatus = [];
|
|
32
30
|
let withDecoratorCount = 0;
|
|
33
|
-
const propertyDefinitions =
|
|
31
|
+
const propertyDefinitions = getPropertiesDefinitions(node);
|
|
34
32
|
// for each property in the class
|
|
35
33
|
for (const propertyDefinition of propertyDefinitions) {
|
|
36
34
|
// check for the optional or defined decorators, or any class-validator decorator
|
|
@@ -86,7 +84,7 @@ const rule = (0, createRule_1.createRule)({
|
|
|
86
84
|
const type = getType(propertyDefinition.typeAnnotation.typeAnnotation, service, checker);
|
|
87
85
|
// if the type is nullable, it should be optional
|
|
88
86
|
if (propertyDefinition.optional ||
|
|
89
|
-
|
|
87
|
+
isNullableType(type)) {
|
|
90
88
|
if (!decoratorsStatus.hasIsOptionalDecorator &&
|
|
91
89
|
!decoratorsStatus.hasValidateIfDecorator) {
|
|
92
90
|
context.report({
|
|
@@ -110,7 +108,7 @@ const rule = (0, createRule_1.createRule)({
|
|
|
110
108
|
};
|
|
111
109
|
},
|
|
112
110
|
});
|
|
113
|
-
|
|
111
|
+
export default rule;
|
|
114
112
|
function getType(typeNode, service, checker) {
|
|
115
113
|
const tsNode = service.esTreeNodeToTSNodeMap.get(typeNode);
|
|
116
114
|
const type = checker.getTypeAtLocation(tsNode);
|
|
@@ -121,13 +119,13 @@ function getDecoratorsStatus(propertyDefinition) {
|
|
|
121
119
|
let hasTypeCheckingDecorator = false;
|
|
122
120
|
let hasIsOptionalDecorator = false;
|
|
123
121
|
let hasValidateIfDecorator = false;
|
|
124
|
-
const program =
|
|
122
|
+
const program = typedTokenHelpers.getRootProgram(propertyDefinition);
|
|
125
123
|
if (propertyDefinition.decorators) {
|
|
126
124
|
for (const decorator of propertyDefinition.decorators) {
|
|
127
|
-
if (decorator.expression.type ===
|
|
128
|
-
decorator.expression.callee.type ===
|
|
125
|
+
if (decorator.expression.type === AST_NODE_TYPES.CallExpression &&
|
|
126
|
+
decorator.expression.callee.type === AST_NODE_TYPES.Identifier) {
|
|
129
127
|
// if this is not a class-validator decorator, skip it (this avoids name conflicts with decorators from other libraries)
|
|
130
|
-
if (!
|
|
128
|
+
if (!typedTokenHelpers.decoratorIsClassValidatorDecorator(program, decorator)) {
|
|
131
129
|
continue;
|
|
132
130
|
}
|
|
133
131
|
// We care if the decorator is a validation decorator like IsString etc for checks later
|
|
@@ -156,4 +154,4 @@ function getDecoratorsStatus(propertyDefinition) {
|
|
|
156
154
|
hasValidateIfDecorator,
|
|
157
155
|
};
|
|
158
156
|
}
|
|
159
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
157
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsUHJvcGVydGllc0hhdmVFeHBsaWNpdERlZmluZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVsZXMvYWxsUHJvcGVydGllc0hhdmVFeHBsaWNpdERlZmluZWQvYWxsUHJvcGVydGllc0hhdmVFeHBsaWNpdERlZmluZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNILGNBQWMsRUFFZCxXQUFXLEdBRWQsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFDN0QsT0FBTyxFQUFDLHdCQUF3QixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDNUQsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBRXJELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGtDQUFrQyxDQUFDO0FBRW5FLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FRckI7SUFDRSxJQUFJLEVBQUUsc0NBQXNDO0lBQzVDLElBQUksRUFBRTtRQUNGLElBQUksRUFBRTtZQUNGLFdBQVcsRUFDUCxrRUFBa0U7U0FDekU7UUFDRCxRQUFRLEVBQUU7WUFDTiw4QkFBOEIsRUFDMUIsNEdBQTRHO1lBQ2hILCtCQUErQixFQUMzQix3RUFBd0U7WUFDNUUsaURBQWlELEVBQzdDLGdFQUFnRTtZQUNwRSxvREFBb0QsRUFDaEQsZ0VBQWdFO1lBQ3BFLHFEQUFxRCxFQUNqRCxpRUFBaUU7WUFDckUsb0NBQW9DLEVBQ2hDLDJFQUEyRTtTQUNsRjtRQUNELElBQUksRUFBRSxTQUFTO1FBQ2YsTUFBTSxFQUFFLEVBQUU7S0FDYjtJQUNELGNBQWMsRUFBRSxFQUFFO0lBQ2xCLE1BQU0sRUFBRSxVQUFVLE9BQU87UUFDckIsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXZELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFP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
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
|
|
2
|
-
import { EnumTestResultModel } from "./enumTestResultModel";
|
|
2
|
+
import { EnumTestResultModel } from "./enumTestResultModel.js";
|
|
3
3
|
export declare const hasEnumSpecifiedCorrectly: (node: TSESTree.Node, isEnumType: boolean) => EnumTestResultModel;
|
|
4
4
|
export declare const needsEnumNameMatchingEnumType: (enumNameProperty: TSESTree.Property, enumProperty: TSESTree.Property) => boolean;
|
|
5
5
|
declare const rule: ESLintUtils.RuleModule<"needsEnumNameAdded" | "needsTypeRemoved" | "enumNameShouldMatchType", [], unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const typedTokenHelpers_1 = require("../../utils/typedTokenHelpers");
|
|
7
|
-
const enumTestResultModel_1 = require("./enumTestResultModel");
|
|
8
|
-
const noChangesRequiredResult = new enumTestResultModel_1.EnumTestResultModel({
|
|
1
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../../utils/createRule.js";
|
|
3
|
+
import { typedTokenHelpers } from "../../utils/typedTokenHelpers.js";
|
|
4
|
+
import { EnumTestResultModel } from "./enumTestResultModel.js";
|
|
5
|
+
const noChangesRequiredResult = new EnumTestResultModel({
|
|
9
6
|
needsEnumAdded: false,
|
|
10
7
|
needsEnumNameAdded: false,
|
|
11
8
|
needsEnumNameToMatchEnumType: false,
|
|
12
9
|
needsTypeRemoved: false,
|
|
13
10
|
});
|
|
14
|
-
const hasEnumSpecifiedCorrectly = (node, isEnumType) => {
|
|
11
|
+
export const hasEnumSpecifiedCorrectly = (node, isEnumType) => {
|
|
15
12
|
// is this an enum
|
|
16
13
|
if (!isEnumType) {
|
|
17
14
|
return noChangesRequiredResult;
|
|
18
15
|
}
|
|
19
16
|
// is this decorated with api documentation
|
|
20
|
-
const decorators =
|
|
17
|
+
const decorators = typedTokenHelpers.getDecoratorsNamed(node, ["ApiPropertyOptional", "ApiProperty"]);
|
|
21
18
|
if (decorators.length === 0) {
|
|
22
19
|
return noChangesRequiredResult;
|
|
23
20
|
}
|
|
@@ -25,7 +22,7 @@ const hasEnumSpecifiedCorrectly = (node, isEnumType) => {
|
|
|
25
22
|
const firstArgument = decorators[0].expression
|
|
26
23
|
.arguments[0];
|
|
27
24
|
if (!firstArgument) {
|
|
28
|
-
return new
|
|
25
|
+
return new EnumTestResultModel({
|
|
29
26
|
needsEnumAdded: true,
|
|
30
27
|
needsEnumNameAdded: true,
|
|
31
28
|
needsEnumNameToMatchEnumType: false,
|
|
@@ -40,15 +37,14 @@ const hasEnumSpecifiedCorrectly = (node, isEnumType) => {
|
|
|
40
37
|
// check if there is an enumName: property in the provided options (enums should specify a name)
|
|
41
38
|
const enumNameProperty = firstArgument.properties.find((p) => p.key.name ===
|
|
42
39
|
"enumName");
|
|
43
|
-
return new
|
|
40
|
+
return new EnumTestResultModel({
|
|
44
41
|
needsEnumAdded: enumProperty === undefined,
|
|
45
42
|
needsEnumNameAdded: enumNameProperty === undefined,
|
|
46
|
-
needsEnumNameToMatchEnumType:
|
|
43
|
+
needsEnumNameToMatchEnumType: needsEnumNameMatchingEnumType(enumNameProperty, enumProperty),
|
|
47
44
|
needsTypeRemoved: hasTypeProperty,
|
|
48
45
|
});
|
|
49
46
|
};
|
|
50
|
-
|
|
51
|
-
const needsEnumNameMatchingEnumType = (enumNameProperty, enumProperty) => {
|
|
47
|
+
export const needsEnumNameMatchingEnumType = (enumNameProperty, enumProperty) => {
|
|
52
48
|
// if enum props aren't specified we don't care about this scenario
|
|
53
49
|
if (enumNameProperty === undefined || enumProperty === undefined) {
|
|
54
50
|
return false;
|
|
@@ -57,8 +53,7 @@ const needsEnumNameMatchingEnumType = (enumNameProperty, enumProperty) => {
|
|
|
57
53
|
enumProperty.value?.name;
|
|
58
54
|
return !isEnumNameMatchingEnumType;
|
|
59
55
|
};
|
|
60
|
-
|
|
61
|
-
const rule = (0, createRule_1.createRule)({
|
|
56
|
+
const rule = createRule({
|
|
62
57
|
name: "api-enum-property-best-practices",
|
|
63
58
|
meta: {
|
|
64
59
|
docs: {
|
|
@@ -76,14 +71,14 @@ const rule = (0, createRule_1.createRule)({
|
|
|
76
71
|
defaultOptions: [],
|
|
77
72
|
create(context) {
|
|
78
73
|
//const globalScope = context.getScope();
|
|
79
|
-
const parserServices =
|
|
74
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
80
75
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
81
76
|
return {
|
|
82
77
|
PropertyDefinition(node) {
|
|
83
78
|
const mappedNode = parserServices.esTreeNodeToTSNodeMap.get(node);
|
|
84
79
|
const objectType = typeChecker.getTypeAtLocation(mappedNode);
|
|
85
|
-
const isEnumType =
|
|
86
|
-
const result =
|
|
80
|
+
const isEnumType = typedTokenHelpers.isEnumType(objectType);
|
|
81
|
+
const result = hasEnumSpecifiedCorrectly(node, isEnumType);
|
|
87
82
|
if (result.needsEnumNameAdded) {
|
|
88
83
|
context.report({
|
|
89
84
|
node: node,
|
|
@@ -106,5 +101,5 @@ const rule = (0, createRule_1.createRule)({
|
|
|
106
101
|
};
|
|
107
102
|
},
|
|
108
103
|
});
|
|
109
|
-
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
104
|
+
export default rule;
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpRW51bVByb3BlcnR5QmVzdFByYWN0aWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydWxlcy9hcGlFbnVtUHJvcGVydHlCZXN0UHJhY3RpY2VzL2FwaUVudW1Qcm9wZXJ0eUJlc3RQcmFjdGljZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxrQ0FBa0MsQ0FBQztBQUNuRSxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUU3RCxNQUFNLHVCQUF1QixHQUFHLElBQUksbUJBQW1CLENBQUM7SUFDcEQsY0FBYyxFQUFFLEtBQUs7SUFDckIsa0JBQWtCLEVBQUUsS0FBSztJQUN6Qiw0QkFBNEIsRUFBRSxLQUFLO0lBQ25DLGdCQUFnQixFQUFFLEtBQUs7Q0FDMUIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FDckMsSUFBbUIsRUFDbkIsVUFBbUIsRUFDQSxFQUFFO0lBQ3JCLGtCQUFrQjtJQUNsQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDZCxPQUFPLHVCQUF1QixDQUFDO0lBQ25DLENBQUM7SUFFRCwyQ0FBMkM7SUFDM0MsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsa0JBQWtCLENBQ25ELElBQW1DLEVBQ25DLENBQUMscUJBQXFCLEVBQUUsYUFBYSxDQUFDLENBQ3pDLENBQUM7SUFFRixJQUFJLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTyx1QkFBdUIsQ0FBQztJQUNuQyxDQUFDO0lBRUQsc0dBQXNHO0lBQ3RHLE1BQU0sYUFBYSxHQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFz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
|