@darraghor/eslint-plugin-nestjs-typed 7.3.4 → 7.4.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 +4 -1
- package/dist/configs/noSwagger.js +2 -1
- package/dist/configs/recommended.js +4 -1
- package/dist/index.d.ts +9 -0
- package/dist/rules/forwardRefInjectionShouldUseWrapperType/forwardRefInjectionShouldUseWrapperType.d.ts +4 -0
- package/dist/rules/forwardRefInjectionShouldUseWrapperType/forwardRefInjectionShouldUseWrapperType.js +88 -0
- package/dist/rules/index.d.ts +9 -0
- package/dist/rules/index.js +7 -1
- package/dist/rules/swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.d.ts +9 -0
- package/dist/rules/swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.js +91 -0
- package/dist/rules/uploadedFileShouldBeValidated/uploadedFileShouldBeValidated.d.ts +10 -0
- package/dist/rules/uploadedFileShouldBeValidated/uploadedFileShouldBeValidated.js +79 -0
- package/dist/utils/decorators.d.ts +2 -0
- package/dist/utils/decorators.js +8 -0
- package/dist/utils/nestFileUpload.d.ts +5 -0
- package/dist/utils/nestFileUpload.js +116 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -73,14 +73,17 @@ Awesome! [Click here](https://github.com/darraghoriordan/eslint-plugin-nestjs-ty
|
|
|
73
73
|
| | [`api-property-returning-array-should-set-array`](./src/docs/rules/api-property-returning-array-should-set-array.md) | ✅ |
|
|
74
74
|
| | [`api-property-should-have-api-extra-models`](./src/docs/rules/api-property-should-have-api-extra-models.md) | ✅ |
|
|
75
75
|
| | [`api-operation-summary-description-capitalized`](./src/docs/rules/api-operation-summary-description-capitalized.md) | ✅ |
|
|
76
|
+
| | [`swagger-file-upload-should-be-documented`](./src/docs/rules/swagger-file-upload-should-be-documented.md) | ✅ |
|
|
76
77
|
| | | |
|
|
77
78
|
| Preventing bugs | [`param-decorator-name-matches-route-param`](./src/docs/rules/param-decorator-name-matches-route-param.md) | ✅ |
|
|
79
|
+
| | [`forward-ref-injection-should-use-wrapper-type`](./src/docs/rules/forward-ref-injection-should-use-wrapper-type.md) | ✅ |
|
|
80
|
+
| | [`uploaded-file-should-be-validated`](./src/docs/rules/uploaded-file-should-be-validated.md) | ✅ |
|
|
78
81
|
| | [`validate-nested-of-array-should-set-each`](./src/docs/rules/validate-nested-of-array-should-set-each.md) | ✅ |
|
|
79
82
|
| | [`validated-non-primitive-property-needs-type-decorator`](./src/docs/rules/validated-non-primitive-property-needs-type-decorator.md) | ✅ |
|
|
80
83
|
| | [`all-properties-are-whitelisted`](./src/docs/rules/all-properties-are-whitelisted.md) | ✅ |
|
|
81
84
|
| | [`all-properties-have-explicit-defined`](./src/docs/rules/all-properties-have-explicit-defined.md) | ✅ |
|
|
82
85
|
| | [`no-duplicate-decorators`](./src/docs/rules/no-duplicate-decorators.md) | ✅ |
|
|
83
|
-
| | [`validation-pipe-should-use-forbid-unknown`](./src/docs/rules/validation-pipe-should-use-forbid-unknown.md)
|
|
86
|
+
| | [`validation-pipe-should-use-forbid-unknown`](./src/docs/rules/validation-pipe-should-use-forbid-unknown.md) | ✅ |
|
|
84
87
|
| | | |
|
|
85
88
|
| Security | [`api-methods-should-be-guarded`](./src/docs/rules/api-methods-should-be-guarded.md) | ❌ |
|
|
86
89
|
| | | |
|
|
@@ -6,10 +6,11 @@ export const rules = {
|
|
|
6
6
|
"@darraghor/nestjs-typed/controllers-should-supply-api-tags": "off",
|
|
7
7
|
"@darraghor/nestjs-typed/api-enum-property-best-practices": "off",
|
|
8
8
|
"@darraghor/nestjs-typed/api-property-returning-array-should-set-array": "off",
|
|
9
|
+
"@darraghor/nestjs-typed/swagger-file-upload-should-be-documented": "off",
|
|
9
10
|
};
|
|
10
11
|
const config = {
|
|
11
12
|
extends: ["./configs/base"],
|
|
12
13
|
rules,
|
|
13
14
|
};
|
|
14
15
|
export default config;
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9Td2FnZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZ3Mvbm9Td2FnZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQWdEO0lBQzlELG1FQUFtRSxFQUFFLEtBQUs7SUFDMUUsZ0VBQWdFLEVBQUUsS0FBSztJQUN2RSxpRUFBaUUsRUFBRSxLQUFLO0lBQ3hFLDREQUE0RCxFQUFFLEtBQUs7SUFDbkUsMERBQTBELEVBQUUsS0FBSztJQUNqRSx1RUFBdUUsRUFDbkUsS0FBSztJQUNULGtFQUFrRSxFQUFFLEtBQUs7Q0FDNUUsQ0FBQztBQUVGLE1BQU0sTUFBTSxHQUFHO0lBQ1gsT0FBTyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7SUFDM0IsS0FBSztDQUNSLENBQUM7QUFFRixlQUFlLE1BQXVDLENBQUMifQ==
|
|
@@ -27,9 +27,12 @@ export const rules = {
|
|
|
27
27
|
"@darraghor/nestjs-typed/api-operation-summary-description-capitalized": "error",
|
|
28
28
|
"@darraghor/nestjs-typed/use-dependency-injection": "off",
|
|
29
29
|
"@darraghor/nestjs-typed/use-correct-endpoint-naming-convention": "off",
|
|
30
|
+
"@darraghor/nestjs-typed/forward-ref-injection-should-use-wrapper-type": "error",
|
|
31
|
+
"@darraghor/nestjs-typed/swagger-file-upload-should-be-documented": "error",
|
|
32
|
+
"@darraghor/nestjs-typed/uploaded-file-should-be-validated": "error",
|
|
30
33
|
};
|
|
31
34
|
export default {
|
|
32
35
|
extends: ["./configs/base"],
|
|
33
36
|
rules,
|
|
34
37
|
};
|
|
35
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb21tZW5kZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uZmlncy9yZWNvbW1lbmRlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQWdDO0lBQzlDLDJFQUEyRSxFQUN2RSxPQUFPO0lBQ1gsdURBQXVELEVBQUU7UUFDckQsT0FBTztRQUNQO1lBQ0ksR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQ3BCLGVBQWUsRUFBRSxDQUFDLGNBQWMsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDO1NBQ3hEO0tBQ0o7SUFDRCxtRUFBbUUsRUFDL0QsT0FBTztJQUNYLGdFQUFnRSxFQUFFLE9BQU87SUFDekUsNERBQTRELEVBQUUsT0FBTztJQUNyRSwwREFBMEQsRUFBRSxPQUFPO0lBQ25FLHVFQUF1RSxFQUNuRSxPQUFPO0lBQ1gsbUVBQW1FLEVBQy9ELE9BQU87SUFDWCxrRUFBa0UsRUFBRSxPQUFPO0lBQzNFLCtFQUErRSxFQUMzRSxPQUFPO0lBQ1gsa0VBQWtFLEVBQUUsT0FBTztJQUMzRSx3REFBd0QsRUFBRSxPQUFPO0lBQ2pFLDhEQUE4RCxFQUFFLE9BQU87SUFDdkUsdURBQXVELEVBQUUsS0FBSztJQUM5RCxpRUFBaUUsRUFBRSxLQUFLO0lBQ3hFLHFEQUFxRCxFQUFFLEtBQUs7SUFDNUQsaURBQWlELEVBQUUsT0FBTztJQUMxRCx1REFBdUQsRUFBRSxPQUFPO0lBQ2hFLG1FQUFtRSxFQUMvRCxPQUFPO0lBQ1gsdUVBQXVFLEVBQ25FLE9BQU87SUFDWCxrREFBa0QsRUFBRSxLQUFLO0lBQ3pELGdFQUFnRSxFQUFFLEtBQUs7SUFDdkUsdUVBQXVFLEVBQ25FLE9BQU87SUFDWCxrRUFBa0UsRUFBRSxPQUFPO0lBQzNFLDJEQUEyRCxFQUFFLE9BQU87Q0FDdkUsQ0FBQztBQUNGLGVBQWU7SUFDWCxPQUFPLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztJQUMzQixLQUFLO0NBQ1IsQ0FBQyJ9
|
package/dist/index.d.ts
CHANGED
|
@@ -92,6 +92,15 @@ declare const _default: {
|
|
|
92
92
|
"use-dependency-injection": TSESLint.RuleModule<"useDependencyInjection", [], unknown, TSESLint.RuleListener> & {
|
|
93
93
|
name: string;
|
|
94
94
|
};
|
|
95
|
+
"forward-ref-injection-should-use-wrapper-type": TSESLint.RuleModule<"useWrapperType", [], unknown, TSESLint.RuleListener> & {
|
|
96
|
+
name: string;
|
|
97
|
+
};
|
|
98
|
+
"swagger-file-upload-should-be-documented": TSESLint.RuleModule<"missingApiBody" | "missingApiConsumes", import("./rules/swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.js").SwaggerFileUploadShouldBeDocumentedOptions, unknown, TSESLint.RuleListener> & {
|
|
99
|
+
name: string;
|
|
100
|
+
};
|
|
101
|
+
"uploaded-file-should-be-validated": TSESLint.RuleModule<"missingFileValidation", import("./rules/uploadedFileShouldBeValidated/uploadedFileShouldBeValidated.js").UploadedFileShouldBeValidatedOptions, unknown, TSESLint.RuleListener> & {
|
|
102
|
+
name: string;
|
|
103
|
+
};
|
|
95
104
|
};
|
|
96
105
|
plugin: FlatConfig.Plugin;
|
|
97
106
|
configs: {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import { createRule } from "../../utils/createRule.js";
|
|
4
|
+
import { getParameterDecorators } from "../../utils/decorators.js";
|
|
5
|
+
const getForwardRefTargetName = (decorator) => {
|
|
6
|
+
if (decorator.expression.type !== AST_NODE_TYPES.CallExpression ||
|
|
7
|
+
decorator.expression.callee.type !== AST_NODE_TYPES.Identifier ||
|
|
8
|
+
decorator.expression.callee.name !== "Inject") {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const forwardRefCall = decorator.expression.arguments[0];
|
|
12
|
+
if (forwardRefCall?.type !== AST_NODE_TYPES.CallExpression ||
|
|
13
|
+
forwardRefCall.callee.type !== AST_NODE_TYPES.Identifier ||
|
|
14
|
+
forwardRefCall.callee.name !== "forwardRef") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const callback = forwardRefCall.arguments[0];
|
|
18
|
+
if (callback?.type !== AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
19
|
+
callback.body.type !== AST_NODE_TYPES.Identifier) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return callback.body.name;
|
|
23
|
+
};
|
|
24
|
+
const getDirectTypeReference = (parameter) => {
|
|
25
|
+
const innerParameter = parameter.type === AST_NODE_TYPES.TSParameterProperty
|
|
26
|
+
? parameter.parameter
|
|
27
|
+
: parameter;
|
|
28
|
+
if (innerParameter.type !== AST_NODE_TYPES.Identifier) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const typeNode = innerParameter.typeAnnotation?.typeAnnotation;
|
|
32
|
+
if (typeNode?.type !== AST_NODE_TYPES.TSTypeReference ||
|
|
33
|
+
typeNode.typeName.type !== AST_NODE_TYPES.Identifier) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return { name: typeNode.typeName.name, node: typeNode };
|
|
37
|
+
};
|
|
38
|
+
const rule = createRule({
|
|
39
|
+
name: "forward-ref-injection-should-use-wrapper-type",
|
|
40
|
+
meta: {
|
|
41
|
+
docs: {
|
|
42
|
+
description: "Requires forwardRef constructor injections to avoid a direct runtime type reference that can fail with ESM decorator metadata.",
|
|
43
|
+
},
|
|
44
|
+
messages: {
|
|
45
|
+
useWrapperType: "The type '{{typeName}}' is also referenced by forwardRef(). Wrap the parameter type (for example WrapperType<{{typeName}}>) or refactor the circular dependency to prevent an ESM initialization error.",
|
|
46
|
+
},
|
|
47
|
+
schema: [],
|
|
48
|
+
hasSuggestions: false,
|
|
49
|
+
type: "problem",
|
|
50
|
+
},
|
|
51
|
+
defaultOptions: [],
|
|
52
|
+
create(context) {
|
|
53
|
+
const program = context.sourceCode.parserServices?.program;
|
|
54
|
+
const compilerOptions = program?.getCompilerOptions();
|
|
55
|
+
const sourceFile = program?.getSourceFile(context.filename);
|
|
56
|
+
const isEsmDecoratorMetadataProject = compilerOptions?.emitDecoratorMetadata === true &&
|
|
57
|
+
compilerOptions.module !== undefined &&
|
|
58
|
+
compilerOptions.module !== ts.ModuleKind.CommonJS &&
|
|
59
|
+
sourceFile?.impliedNodeFormat !== ts.ModuleKind.CommonJS;
|
|
60
|
+
if (!isEsmDecoratorMetadataProject) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
MethodDefinition(node) {
|
|
65
|
+
if (node.kind !== "constructor") {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
for (const parameter of node.value.params) {
|
|
69
|
+
const directType = getDirectTypeReference(parameter);
|
|
70
|
+
if (!directType) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const matchingDecorator = getParameterDecorators(parameter).find((decorator) => getForwardRefTargetName(decorator) ===
|
|
74
|
+
directType.name);
|
|
75
|
+
if (matchingDecorator) {
|
|
76
|
+
context.report({
|
|
77
|
+
node: directType.node,
|
|
78
|
+
messageId: "useWrapperType",
|
|
79
|
+
data: { typeName: directType.name },
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
export default rule;
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yd2FyZFJlZkluamVjdGlvblNob3VsZFVzZVdyYXBwZXJUeXBlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bGVzL2ZvcndhcmRSZWZJbmplY3Rpb25TaG91bGRVc2VXcmFwcGVyVHlwZS9mb3J3YXJkUmVmSW5qZWN0aW9uU2hvdWxkVXNlV3JhcHBlclR5cGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGNBQWMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUM1QixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFFakUsTUFBTSx1QkFBdUIsR0FBRyxDQUM1QixTQUE2QixFQUNoQixFQUFFO0lBQ2YsSUFDSSxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsY0FBYztRQUMzRCxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDLFVBQVU7UUFDOUQsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFDL0MsQ0FBQztRQUNDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLGNBQWMsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RCxJQUNJLGNBQWMsRUFBRSxJQUFJLEtBQUssY0FBYyxDQUFDLGNBQWM7UUFDdEQsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDLFVBQVU7UUFDeEQsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUM3QyxDQUFDO1FBQ0MsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFH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
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -79,5 +79,14 @@ declare const allRules: {
|
|
|
79
79
|
"use-dependency-injection": import("@typescript-eslint/utils/ts-eslint").RuleModule<"useDependencyInjection", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
80
80
|
name: string;
|
|
81
81
|
};
|
|
82
|
+
"forward-ref-injection-should-use-wrapper-type": import("@typescript-eslint/utils/ts-eslint").RuleModule<"useWrapperType", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
83
|
+
name: string;
|
|
84
|
+
};
|
|
85
|
+
"swagger-file-upload-should-be-documented": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingApiBody" | "missingApiConsumes", import("./swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.js").SwaggerFileUploadShouldBeDocumentedOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
86
|
+
name: string;
|
|
87
|
+
};
|
|
88
|
+
"uploaded-file-should-be-validated": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingFileValidation", import("./uploadedFileShouldBeValidated/uploadedFileShouldBeValidated.js").UploadedFileShouldBeValidatedOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
89
|
+
name: string;
|
|
90
|
+
};
|
|
82
91
|
};
|
|
83
92
|
export default allRules;
|
package/dist/rules/index.js
CHANGED
|
@@ -20,6 +20,9 @@ import useInjectableProvidedToken from "./useInjectableProvidedToken/useInjectab
|
|
|
20
20
|
import apiPropertyShouldHaveApiExtraModels from "./apiPropertyShouldHaveApiExtraModels/apiPropertyShouldHaveApiExtraModels.js";
|
|
21
21
|
import apiOperationSummaryDescriptionCapitalized from "./apiOperationSummaryDescriptionCapitalized/apiOperationSummaryDescriptionCapitalized.js";
|
|
22
22
|
import useDependencyInjection from "./useDependencyInjection/useDependencyInjection.js";
|
|
23
|
+
import forwardRefInjectionShouldUseWrapperType from "./forwardRefInjectionShouldUseWrapperType/forwardRefInjectionShouldUseWrapperType.js";
|
|
24
|
+
import swaggerFileUploadShouldBeDocumented from "./swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.js";
|
|
25
|
+
import uploadedFileShouldBeValidated from "./uploadedFileShouldBeValidated/uploadedFileShouldBeValidated.js";
|
|
23
26
|
const allRules = {
|
|
24
27
|
"all-properties-have-explicit-defined": allPropertiesHaveExplicitDefined,
|
|
25
28
|
"api-property-matches-property-optionality": apiPropertyMatchesPropertyOptionality,
|
|
@@ -43,6 +46,9 @@ const allRules = {
|
|
|
43
46
|
"api-property-should-have-api-extra-models": apiPropertyShouldHaveApiExtraModels,
|
|
44
47
|
"api-operation-summary-description-capitalized": apiOperationSummaryDescriptionCapitalized,
|
|
45
48
|
"use-dependency-injection": useDependencyInjection,
|
|
49
|
+
"forward-ref-injection-should-use-wrapper-type": forwardRefInjectionShouldUseWrapperType,
|
|
50
|
+
"swagger-file-upload-should-be-documented": swaggerFileUploadShouldBeDocumented,
|
|
51
|
+
"uploaded-file-should-be-validated": uploadedFileShouldBeValidated,
|
|
46
52
|
};
|
|
47
53
|
export default allRules;
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVsZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTywwQkFBMEIsTUFBTSw2REFBNkQsQ0FBQztBQUNyRyxPQUFPLDRDQUE0QyxNQUFNLDRFQUE0RSxDQUFDO0FBQ3RJLE9BQU8scUNBQXFDLE1BQU0sa0ZBQWtGLENBQUM7QUFDckksT0FBTyw2QkFBNkIsTUFBTSxrRUFBa0UsQ0FBQztBQUM3RyxPQUFPLGtDQUFrQyxNQUFNLDRFQUE0RSxDQUFDO0FBQzVILE9BQU8sNEJBQTRCLE1BQU0sZ0VBQWdFLENBQUM7QUFDMUcsT0FBTyx1Q0FBdUMsTUFBTSxzRkFBc0YsQ0FBQztBQUMzSSxPQUFPLGdDQUFnQyxNQUFNLDRFQUE0RSxDQUFDO0FBQzFILE9BQU8sdUNBQXVDLE1BQU0sOEVBQThFLENBQUM7QUFDbkksT0FBTyxtQ0FBbUMsTUFBTSxpRkFBaUYsQ0FBQztBQUNsSSxPQUFPLGtDQUFrQyxNQUFNLDRFQUE0RSxDQUFDO0FBQzVILE9BQU8sMkJBQTJCLE1BQU0sOERBQThELENBQUM7QUFDdkcsT0FBTyxnQ0FBZ0MsTUFBTSx3RUFBd0UsQ0FBQztBQUN0SCxPQUFPLHlCQUF5QixNQUFNLDBEQUEwRCxDQUFDO0FBQ2pHLE9BQU8sbUNBQW1DLE1BQU0sOEVBQThFLENBQUM7QUFDL0gsT0FBTyx3QkFBd0IsTUFBTSx3REFBd0QsQ0FBQztBQUM5RixPQUFPLHFCQUFxQixNQUFNLGtEQUFrRCxDQUFDO0FBQ3JGLE9BQU8sa0NBQWtDLE1BQU0sNEVBQTRFLENBQUM7QUFDNUgsT0FBTywwQkFBMEIsTUFBTSw0REFBNEQsQ0FBQztBQUNwRyxPQUFPLG1DQUFtQyxNQUFNLDhFQUE4RSxDQUFDO0FBQy9ILE9BQU8seUNBQXlDLE1BQU0sMEZBQTBGLENBQUM7QUFDakosT0FBTyxzQkFBc0IsTUFBTSxvREFBb0QsQ0FBQztBQUN4RixPQUFPLHVDQUF1QyxNQUFNLHNGQUFzRixDQUFDO0FBQzNJLE9BQU8sbUNBQW1DLE1BQU0sOEVBQThFLENBQUM7QUFDL0gsT0FBTyw2QkFBNkIsTUFBTSxrRUFBa0UsQ0FBQztBQUM3RyxNQUFNLFFBQVEsR0FBRztJQUNiLHNDQUFzQyxFQUFFLGdDQUFnQztJQUN4RSwyQ0FBMkMsRUFDdkMscUNBQXFDO0lBQ3pDLCtCQUErQixFQUFFLDBCQUEwQjtJQUMzRCx5QkFBeUIsRUFBRSxxQkFBcUI7SUFDaEQsbURBQW1ELEVBQy9DLDRDQUE0QztJQUNoRCxvQ0FBb0MsRUFBRSw2QkFBNkI7SUFDbkUsd0NBQXdDLEVBQ3BDLGtDQUFrQztJQUN0Qyx5Q0FBeUMsRUFDckMsbUNBQW1DO0lBQ3ZDLGtDQUFrQyxFQUFFLDRCQUE0QjtJQUNoRSwrQ0FBK0MsRUFDM0MsdUNBQXVDO0lBQzNDLDJDQUEyQyxFQUN2QyxnQ0FBZ0M7SUFDcEMsMENBQTBDLEVBQ3RDLHVDQUF1QztJQUMzQyx1REFBdUQsRUFDbkQsbUNBQW1DO0lBQ3ZDLDBDQUEwQyxFQUN0QyxrQ0FBa0M7SUFDdEMsZ0NBQWdDLEVBQUUsMkJBQTJCO0lBQzdELCtCQUErQixFQUFFLHlCQUF5QjtJQUMxRCw2QkFBNkIsRUFBRSx3QkFBd0I7SUFDdkQsd0NBQXdDLEVBQ3BDLGtDQUFrQztJQUN0QywrQkFBK0IsRUFBRSwwQkFBMEI7SUFDM0QsMkNBQTJDLEVBQ3ZDLG1DQUFtQztJQUN2QywrQ0FBK0MsRUFDM0MseUNBQXlDO0lBQzdDLDBCQUEwQixFQUFFLHNCQUFzQjtJQUNsRCwrQ0FBK0MsRUFDM0MsdUNBQXVDO0lBQzNDLDBDQUEwQyxFQUN0QyxtQ0FBbUM7SUFDdkMsbUNBQW1DLEVBQUUsNkJBQTZCO0NBQ3JFLENBQUM7QUFFRixlQUFlLFFBQVEsQ0FBQyJ9
|
package/dist/rules/swaggerFileUploadShouldBeDocumented/swaggerFileUploadShouldBeDocumented.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type SwaggerFileUploadShouldBeDocumentedOptions = [
|
|
2
|
+
{
|
|
3
|
+
additionalSwaggerDecorators: string[];
|
|
4
|
+
}
|
|
5
|
+
];
|
|
6
|
+
declare const rule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingApiBody" | "missingApiConsumes", SwaggerFileUploadShouldBeDocumentedOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
7
|
+
name: string;
|
|
8
|
+
};
|
|
9
|
+
export default rule;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../../utils/createRule.js";
|
|
3
|
+
import { getUploadedFileDecorators, nodeHasAnyDecoratorNamed, } from "../../utils/nestFileUpload.js";
|
|
4
|
+
import { typedTokenHelpers } from "../../utils/typedTokenHelpers.js";
|
|
5
|
+
const httpMethodDecoratorNames = [
|
|
6
|
+
"Get",
|
|
7
|
+
"Post",
|
|
8
|
+
"Put",
|
|
9
|
+
"Delete",
|
|
10
|
+
"Patch",
|
|
11
|
+
"Options",
|
|
12
|
+
"Head",
|
|
13
|
+
"All",
|
|
14
|
+
];
|
|
15
|
+
const hasMultipartConsumesDecorator = (node) => typedTokenHelpers
|
|
16
|
+
.getDecoratorsNamed(node, ["ApiConsumes"])
|
|
17
|
+
.some((decorator) => {
|
|
18
|
+
if (decorator.expression.type !== AST_NODE_TYPES.CallExpression) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return decorator.expression.arguments.some((argument) => argument.type === AST_NODE_TYPES.Literal &&
|
|
22
|
+
argument.value === "multipart/form-data");
|
|
23
|
+
});
|
|
24
|
+
const rule = createRule({
|
|
25
|
+
name: "swagger-file-upload-should-be-documented",
|
|
26
|
+
meta: {
|
|
27
|
+
docs: {
|
|
28
|
+
description: "Requires Swagger file-upload endpoints to declare multipart consumption and an API body schema.",
|
|
29
|
+
},
|
|
30
|
+
messages: {
|
|
31
|
+
missingApiConsumes: "File-upload endpoints should use @ApiConsumes('multipart/form-data') so the generated OpenAPI operation declares the correct content type.",
|
|
32
|
+
missingApiBody: "File-upload endpoints should use @ApiBody() with a binary file schema so the uploaded file is represented in OpenAPI.",
|
|
33
|
+
},
|
|
34
|
+
schema: [
|
|
35
|
+
{
|
|
36
|
+
type: "object",
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
properties: {
|
|
39
|
+
additionalSwaggerDecorators: {
|
|
40
|
+
description: "Custom method or controller decorators that provide both multipart consumption and the upload body schema.",
|
|
41
|
+
type: "array",
|
|
42
|
+
items: { type: "string", minLength: 1 },
|
|
43
|
+
minItems: 0,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
hasSuggestions: false,
|
|
49
|
+
type: "suggestion",
|
|
50
|
+
},
|
|
51
|
+
defaultOptions: [{ additionalSwaggerDecorators: [] }],
|
|
52
|
+
create(context) {
|
|
53
|
+
const { additionalSwaggerDecorators } = context.options[0] ?? {
|
|
54
|
+
additionalSwaggerDecorators: [],
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
MethodDefinition(node) {
|
|
58
|
+
if (getUploadedFileDecorators(node).length === 0 ||
|
|
59
|
+
!typedTokenHelpers.nodeHasDecoratorsNamed(node, httpMethodDecoratorNames)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const containingClass = node.parent.parent;
|
|
63
|
+
if (containingClass.type !== AST_NODE_TYPES.ClassDeclaration) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (typedTokenHelpers.nodeHasDecoratorsNamed(containingClass, [
|
|
67
|
+
"ApiExcludeController",
|
|
68
|
+
]) ||
|
|
69
|
+
typedTokenHelpers.nodeHasDecoratorsNamed(node, [
|
|
70
|
+
"ApiExcludeEndpoint",
|
|
71
|
+
]) ||
|
|
72
|
+
nodeHasAnyDecoratorNamed(node, additionalSwaggerDecorators) ||
|
|
73
|
+
nodeHasAnyDecoratorNamed(containingClass, additionalSwaggerDecorators)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!hasMultipartConsumesDecorator(node) &&
|
|
77
|
+
!hasMultipartConsumesDecorator(containingClass)) {
|
|
78
|
+
context.report({
|
|
79
|
+
node,
|
|
80
|
+
messageId: "missingApiConsumes",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (!typedTokenHelpers.nodeHasDecoratorsNamed(node, ["ApiBody"])) {
|
|
84
|
+
context.report({ node, messageId: "missingApiBody" });
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
export default rule;
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3dhZ2dlckZpbGVVcGxvYWRTaG91bGRCZURvY3VtZW50ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVsZXMvc3dhZ2dlckZpbGVVcGxvYWRTaG91bGRCZURvY3VtZW50ZWQvc3dhZ2dlckZpbGVVcGxvYWRTaG91bGRCZURvY3VtZW50ZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGNBQWMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRCxPQUFPLEVBQ0gseUJBQXlCLEVBQ3pCLHdCQUF3QixHQUMzQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGtDQUFrQyxDQUFDO0FBUW5FLE1BQU0sd0JBQXdCLEdBQUc7SUFDN0IsS0FBSztJQUNMLE1BQU07SUFDTixLQUFLO0lBQ0wsUUFBUTtJQUNSLE9BQU87SUFDUCxTQUFTO0lBQ1QsTUFBTTtJQUNOLEtBQUs7Q0FDUixDQUFDO0FBRUYsTUFBTSw2QkFBNkIsR0FBRyxDQUNsQyxJQUEyRCxFQUNwRCxFQUFFLENBQ1QsaUJBQWlCO0tBQ1osa0JBQWtCLENBQUMsSUFBSSxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDekMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7SUFDaEIsSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDOUQsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVELE9BQU8sU0FBUyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUN0QyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQ1QsUUFBUSxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsT0FBTztRQUN4QyxRQUFRLENBQUMsS0FBSyxLQUFLLHFCQUFxQixDQUMvQyxD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
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type UploadedFileShouldBeValidatedOptions = [
|
|
2
|
+
{
|
|
3
|
+
additionalFileValidationDecorators: string[];
|
|
4
|
+
additionalFileValidationPipes: string[];
|
|
5
|
+
}
|
|
6
|
+
];
|
|
7
|
+
declare const rule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingFileValidation", UploadedFileShouldBeValidatedOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
export default rule;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../../utils/createRule.js";
|
|
3
|
+
import { decoratorArgumentsContainNamedConstruct, getUploadedFileDecorators, methodHasMulterFileSizeLimit, nodeHasAnyDecoratorNamed, } from "../../utils/nestFileUpload.js";
|
|
4
|
+
const rule = createRule({
|
|
5
|
+
name: "uploaded-file-should-be-validated",
|
|
6
|
+
meta: {
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Requires uploaded files to be validated by a file pipe or constrained by a Multer file-size limit.",
|
|
9
|
+
},
|
|
10
|
+
messages: {
|
|
11
|
+
missingFileValidation: "Validate this uploaded file with ParseFilePipe/ParseFilePipeBuilder, a configured custom validation pipe, or a Multer limits.fileSize option.",
|
|
12
|
+
},
|
|
13
|
+
schema: [
|
|
14
|
+
{
|
|
15
|
+
type: "object",
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
properties: {
|
|
18
|
+
additionalFileValidationDecorators: {
|
|
19
|
+
description: "Custom method or controller decorators that establish file-upload validation.",
|
|
20
|
+
type: "array",
|
|
21
|
+
items: { type: "string", minLength: 1 },
|
|
22
|
+
minItems: 0,
|
|
23
|
+
},
|
|
24
|
+
additionalFileValidationPipes: {
|
|
25
|
+
description: "Custom pipe constructor names accepted as uploaded-file validation.",
|
|
26
|
+
type: "array",
|
|
27
|
+
items: { type: "string", minLength: 1 },
|
|
28
|
+
minItems: 0,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
hasSuggestions: false,
|
|
34
|
+
type: "problem",
|
|
35
|
+
},
|
|
36
|
+
defaultOptions: [
|
|
37
|
+
{
|
|
38
|
+
additionalFileValidationDecorators: [],
|
|
39
|
+
additionalFileValidationPipes: [],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
create(context) {
|
|
43
|
+
const { additionalFileValidationDecorators, additionalFileValidationPipes, } = context.options[0] ?? {
|
|
44
|
+
additionalFileValidationDecorators: [],
|
|
45
|
+
additionalFileValidationPipes: [],
|
|
46
|
+
};
|
|
47
|
+
const acceptedPipeNames = new Set([
|
|
48
|
+
"ParseFilePipe",
|
|
49
|
+
"ParseFilePipeBuilder",
|
|
50
|
+
...additionalFileValidationPipes,
|
|
51
|
+
]);
|
|
52
|
+
return {
|
|
53
|
+
MethodDefinition(node) {
|
|
54
|
+
const uploadDecorators = getUploadedFileDecorators(node);
|
|
55
|
+
if (uploadDecorators.length === 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const containingClass = node.parent.parent;
|
|
59
|
+
const hasCustomValidationDecorator = nodeHasAnyDecoratorNamed(node, additionalFileValidationDecorators) ||
|
|
60
|
+
(containingClass.type === AST_NODE_TYPES.ClassDeclaration &&
|
|
61
|
+
nodeHasAnyDecoratorNamed(containingClass, additionalFileValidationDecorators));
|
|
62
|
+
if (hasCustomValidationDecorator ||
|
|
63
|
+
methodHasMulterFileSizeLimit(node)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const decorator of uploadDecorators) {
|
|
67
|
+
if (!decoratorArgumentsContainNamedConstruct(decorator, acceptedPipeNames)) {
|
|
68
|
+
context.report({
|
|
69
|
+
node: decorator,
|
|
70
|
+
messageId: "missingFileValidation",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
export default rule;
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkZWRGaWxlU2hvdWxkQmVWYWxpZGF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVsZXMvdXBsb2FkZWRGaWxlU2hvdWxkQmVWYWxpZGF0ZWQvdXBsb2FkZWRGaWxlU2hvdWxkQmVWYWxpZGF0ZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGNBQWMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRCxPQUFPLEVBQ0gsdUNBQXVDLEVBQ3ZDLHlCQUF5QixFQUN6Qiw0QkFBNEIsRUFDNUIsd0JBQXdCLEdBQzNCLE1BQU0sK0JBQStCLENBQUM7QUFTdkMsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUdyQjtJQUNFLElBQUksRUFBRSxtQ0FBbUM7SUFDekMsSUFBSSxFQUFFO1FBQ0YsSUFBSSxFQUFFO1lBQ0YsV0FBVyxFQUNQLG9HQUFvRztTQUMzRztRQUNELFFBQVEsRUFBRTtZQUNOLHFCQUFxQixFQUNqQiwrSUFBK0k7U0FDdEo7UUFDRCxNQUFNLEVBQUU7WUFDSjtnQkFDSSxJQUFJLEVBQUUsUUFBUTtnQkFDZCxvQkFBb0IsRUFBRSxLQUFLO2dCQUMzQixVQUFVLEVBQUU7b0JBQ1Isa0NBQWtDLEVBQUU7d0JBQ2hDLFdBQVcsRUFDUCwrRUFBK0U7d0JBQ25GLElBQUksRUFBRSxPQUFPO3dCQUNiLEtBQUssRUFBRSxFQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBQzt3QkFDckMsUUFBUSxFQUFFLENBQUM7cUJBQ2Q7b0JBQ0QsNkJBQTZCLEVBQUU7d0JBQzNCLFdBQVcsRUFDUCxxRUFBcUU7d0JBQ3pFLElBQUksRUFBRSxPQUFPO3dCQUNiLEtBQUssRUFBRSxFQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBQzt3QkFDckMsUUFBUSxFQUFFLENBQUM7cUJBQ2Q7aUJBQ0o7YUFDSjtTQUNKO1FBQ0QsY0FBYyxFQUFFLEtBQUs7UUFDckIsSUFBSSxFQUFFLFNBQVM7S0FDbEI7SUFDRCxjQUFjLEVBQUU7UUFDWjtZQUNJLGtDQUFrQyxFQUFFLEVBQUU7WUFDdEMsNkJBQTZCLEVBQUUsRUFBRTtTQUNwQztLQUNKO0lBQ0QsTUFBTSxDQUFDLE9BQU87UUFDVixNQUFNLEVBQ0Ysa0NBQWtDLEVBQ2xDLDZCQUE2QixHQUNoQyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDdEIsa0NBQWtDLEVBQUUsRUFBRTtZQUN0Qyw2QkFBNkIsRUFBRSxFQUFFO1NBQ3BDLENBQUM7UUFDRixNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxDQUFDO1lBQzlCLGVBQWU7WUFDZixzQkFBc0I7WUFDdEIsR0FBRyw2QkFBNkI7U0FDbkMsQ0FBQyxDQUFDO1FBRUgsT0FBTztZQUNILGdCQUFnQixDQUFDLElBQStCO2dCQUM1QyxNQUFNLGdCQUFnQixHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN6RCxJQUFJLGdCQUFnQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDaEMsT0FBTztnQkFDWCxDQUFDO2dCQUVELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO2dCQUMzQyxNQUFNLDRCQUE0QixHQUM5Qix3QkFBd0IsQ0FDcEIsSUFBSSxFQUNKLGtDQUFrQyxDQUNyQztvQkFDRCxDQUFDLGVBQWUsQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDLGdCQUFnQjt3QkFDckQsd0JBQXdCLENBQ3BCLGVBQWUsRUFDZixrQ0FBa0MsQ0FDckMsQ0FBQyxDQUFDO2dCQUVYLElBQ0ksNEJBQTRCO29CQUM1Qiw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsRUFDcEMsQ0FBQztvQkFDQyxPQUFPO2dCQUNYLENBQUM7Z0JBRUQsS0FBSyxNQUFNLFNBQVMsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO29CQUN2QyxJQUNJLENBQUMsdUNBQXVDLENBQ3BDLFNBQVMsRUFDVCxpQkFBaUIsQ0FDcEIsRUFDSCxDQUFDO3dCQUNDLE9BQU8sQ0FBQyxNQUFNLENBQUM7NEJBQ1gsSUFBSSxFQUFFLFNBQVM7NEJBQ2YsU0FBUyxFQUFFLHVCQUF1Qjt5QkFDckMsQ0FBQyxDQUFDO29CQUNQLENBQUM7Z0JBQ0wsQ0FBQztZQUNMLENBQUM7U0FDSixDQUFDO0lBQ04sQ0FBQztDQUNKLENBQUMsQ0FBQztBQUVILGVBQWUsSUFBSSxDQUFDIn0=
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
export const getParameterDecorators = (parameter) => {
|
|
3
|
+
if (parameter.type === AST_NODE_TYPES.TSParameterProperty) {
|
|
4
|
+
return parameter.decorators;
|
|
5
|
+
}
|
|
6
|
+
return parameter.decorators ?? [];
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9kZWNvcmF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxjQUFjLEVBQVcsTUFBTSwwQkFBMEIsQ0FBQztBQUVsRSxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxDQUNsQyxTQUE2QixFQUNULEVBQUU7SUFDdEIsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQ3hELE9BQU8sU0FBUyxDQUFDLFVBQVUsQ0FBQztJQUNoQyxDQUFDO0lBRUQsT0FBTyxTQUFTLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztBQUN0QyxDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TSESTree } from "@typescript-eslint/utils";
|
|
2
|
+
export declare const getUploadedFileDecorators: (method: TSESTree.MethodDefinition) => TSESTree.Decorator[];
|
|
3
|
+
export declare const decoratorArgumentsContainNamedConstruct: (decorator: TSESTree.Decorator, names: Set<string>) => boolean;
|
|
4
|
+
export declare const methodHasMulterFileSizeLimit: (method: TSESTree.MethodDefinition) => boolean;
|
|
5
|
+
export declare const nodeHasAnyDecoratorNamed: (node: TSESTree.MethodDefinition | TSESTree.ClassDeclaration, decoratorNames: string[]) => boolean;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { getParameterDecorators } from "./decorators.js";
|
|
3
|
+
import { typedTokenHelpers } from "./typedTokenHelpers.js";
|
|
4
|
+
const fileUploadDecoratorNames = new Set(["UploadedFile", "UploadedFiles"]);
|
|
5
|
+
const fileInterceptorNames = new Set([
|
|
6
|
+
"FileInterceptor",
|
|
7
|
+
"FilesInterceptor",
|
|
8
|
+
"FileFieldsInterceptor",
|
|
9
|
+
"AnyFilesInterceptor",
|
|
10
|
+
]);
|
|
11
|
+
const isNode = (value) => typeof value === "object" &&
|
|
12
|
+
value !== null &&
|
|
13
|
+
"type" in value &&
|
|
14
|
+
typeof value.type === "string";
|
|
15
|
+
const walkNode = (node, predicate) => {
|
|
16
|
+
if (predicate(node)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
for (const [key, value] of Object.entries(node)) {
|
|
20
|
+
if (["parent", "loc", "range", "tokens", "comments"].includes(key)) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (isNode(value) && walkNode(value, predicate)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(value) &&
|
|
27
|
+
value.some((item) => isNode(item) && walkNode(item, predicate))) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
const getCallName = (node) => {
|
|
34
|
+
if (node.callee.type === AST_NODE_TYPES.Identifier) {
|
|
35
|
+
return node.callee.name;
|
|
36
|
+
}
|
|
37
|
+
if (node.callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
38
|
+
node.callee.property.type === AST_NODE_TYPES.Identifier) {
|
|
39
|
+
return node.callee.property.name;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
};
|
|
43
|
+
const getPropertyName = (property) => {
|
|
44
|
+
if (property.key.type === AST_NODE_TYPES.Identifier) {
|
|
45
|
+
return property.key.name;
|
|
46
|
+
}
|
|
47
|
+
if (property.key.type === AST_NODE_TYPES.Literal &&
|
|
48
|
+
typeof property.key.value === "string") {
|
|
49
|
+
return property.key.value;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
const objectHasFileSizeLimit = (node) => walkNode(node, (candidate) => {
|
|
54
|
+
if (candidate.type !== AST_NODE_TYPES.Property) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (getPropertyName(candidate) !== "limits" ||
|
|
58
|
+
candidate.value.type !== AST_NODE_TYPES.ObjectExpression) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return candidate.value.properties.some((property) => property.type === AST_NODE_TYPES.Property &&
|
|
62
|
+
getPropertyName(property) === "fileSize");
|
|
63
|
+
});
|
|
64
|
+
export const getUploadedFileDecorators = (method) => method.value.params.flatMap((parameter) => getParameterDecorators(parameter).filter((decorator) => {
|
|
65
|
+
const name = typedTokenHelpers.getDecoratorName(decorator);
|
|
66
|
+
return name !== null && fileUploadDecoratorNames.has(name);
|
|
67
|
+
}));
|
|
68
|
+
export const decoratorArgumentsContainNamedConstruct = (decorator, names) => {
|
|
69
|
+
if (decorator.expression.type !== AST_NODE_TYPES.CallExpression) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return decorator.expression.arguments.some((argument) => argument.type !== AST_NODE_TYPES.SpreadElement &&
|
|
73
|
+
walkNode(argument, (candidate) => {
|
|
74
|
+
if (candidate.type === AST_NODE_TYPES.Identifier) {
|
|
75
|
+
return names.has(candidate.name);
|
|
76
|
+
}
|
|
77
|
+
if (candidate.type !== AST_NODE_TYPES.CallExpression &&
|
|
78
|
+
candidate.type !== AST_NODE_TYPES.NewExpression) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
const name = getCallName(candidate);
|
|
82
|
+
return name !== null && names.has(name);
|
|
83
|
+
}));
|
|
84
|
+
};
|
|
85
|
+
export const methodHasMulterFileSizeLimit = (method) => {
|
|
86
|
+
const containingClass = method.parent.parent;
|
|
87
|
+
const decorators = [
|
|
88
|
+
...method.decorators,
|
|
89
|
+
...(containingClass.type === AST_NODE_TYPES.ClassDeclaration ||
|
|
90
|
+
containingClass.type === AST_NODE_TYPES.ClassExpression
|
|
91
|
+
? containingClass.decorators
|
|
92
|
+
: []),
|
|
93
|
+
];
|
|
94
|
+
return decorators.some((decorator) => {
|
|
95
|
+
if (typedTokenHelpers.getDecoratorName(decorator) !==
|
|
96
|
+
"UseInterceptors" ||
|
|
97
|
+
decorator.expression.type !== AST_NODE_TYPES.CallExpression) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return decorator.expression.arguments.some((argument) => argument.type !== AST_NODE_TYPES.SpreadElement &&
|
|
101
|
+
walkNode(argument, (candidate) => {
|
|
102
|
+
if (candidate.type !== AST_NODE_TYPES.CallExpression) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const callName = getCallName(candidate);
|
|
106
|
+
return (callName !== null &&
|
|
107
|
+
fileInterceptorNames.has(callName) &&
|
|
108
|
+
candidate.arguments.some((callArgument) => callArgument.type !==
|
|
109
|
+
AST_NODE_TYPES.SpreadElement &&
|
|
110
|
+
objectHasFileSizeLimit(callArgument)));
|
|
111
|
+
}));
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
export const nodeHasAnyDecoratorNamed = (node, decoratorNames) => decoratorNames.length > 0 &&
|
|
115
|
+
typedTokenHelpers.nodeHasDecoratorsNamed(node, decoratorNames);
|
|
116
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVzdEZpbGVVcGxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvbmVzdEZpbGVVcGxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGNBQWMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQztBQUM1RSxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDO0lBQ2pDLGlCQUFpQjtJQUNqQixrQkFBa0I7SUFDbEIsdUJBQXVCO0lBQ3ZCLHFCQUFxQjtDQUN4QixDQUFDLENBQUM7QUFFSCxNQUFNLE1BQU0sR0FBRyxDQUFDLEtBQWMsRUFBMEIsRUFBRSxDQUN0RCxPQUFPLEtBQUssS0FBSyxRQUFRO0lBQ3pCLEtBQUssS0FBSyxJQUFJO0lBQ2QsTUFBTSxJQUFJLEtBQUs7SUFDZixPQUFRLEtBQTBCLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQztBQUV6RCxNQUFNLFFBQVEsR0FBRyxDQUNiLElBQW1CLEVBQ25CLFNBQWdELEVBQ3pDLEVBQUU7SUFDVCxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ2xCLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzlDLElBQUksQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darraghor/eslint-plugin-nestjs-typed",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "Eslint rules for nestjs projects",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rm -Rf ./dist/",
|
|
@@ -114,6 +114,6 @@
|
|
|
114
114
|
"lint",
|
|
115
115
|
"style"
|
|
116
116
|
],
|
|
117
|
-
"packageManager": "pnpm@
|
|
117
|
+
"packageManager": "pnpm@11.24.0",
|
|
118
118
|
"license": "ISC"
|
|
119
119
|
}
|