@automattic/eslint-plugin-wpvip 0.11.0 → 0.12.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/configs/testing.js +19 -1
- package/configs/typescript.js +14 -0
- package/package.json +1 -1
- package/rules/README.md +10 -0
- package/rules/index.js +1 -0
- package/rules/nestjs-route-prefix.js +46 -0
package/configs/testing.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
const isPackageInstalled = require( '../utils/is-package-installed' );
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Based on:
|
|
3
5
|
* - https://github.com/WordPress/gutenberg/blob/%40wordpress/eslint-plugin%4014.1.0/packages/eslint-plugin/configs/test-unit.js
|
|
4
6
|
* - https://github.com/WordPress/gutenberg/blob/%40wordpress/eslint-plugin%4014.1.0/packages/eslint-plugin/configs/test-e2e.js
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
const config = {
|
|
8
10
|
extends: [ 'plugin:jest/recommended' ],
|
|
9
11
|
|
|
10
12
|
env: {
|
|
@@ -13,3 +15,19 @@ module.exports = {
|
|
|
13
15
|
|
|
14
16
|
plugins: [ 'jest' ],
|
|
15
17
|
};
|
|
18
|
+
|
|
19
|
+
if ( isPackageInstalled( 'typescript' ) ) {
|
|
20
|
+
// Add an override for TypeScript's overzealous unbound-method rule that allows
|
|
21
|
+
// Jest mocks to be inspected without being bound to a variable.
|
|
22
|
+
config.overrides = [
|
|
23
|
+
{
|
|
24
|
+
files: [ '__tests__/**/*.ts', '**/*.test.ts', '**/*.spec.ts' ],
|
|
25
|
+
rules: {
|
|
26
|
+
'@typescript-eslint/unbound-method': 'off',
|
|
27
|
+
'jest/unbound-method': 'error',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = config;
|
package/configs/typescript.js
CHANGED
|
@@ -23,6 +23,20 @@ module.exports = {
|
|
|
23
23
|
},
|
|
24
24
|
|
|
25
25
|
rules: {
|
|
26
|
+
// Ensures NestJS route prefixes are correctly formatted.
|
|
27
|
+
'@automattic/wpvip/nestjs-route-prefix': 'error',
|
|
28
|
+
|
|
29
|
+
// Require explicity visibility for class methods and properties to avoid
|
|
30
|
+
// implicit public access. Allow constructors to be implicitly public.
|
|
31
|
+
'@typescript-eslint/explicit-member-accessibility': [
|
|
32
|
+
'error',
|
|
33
|
+
{
|
|
34
|
+
overrides: {
|
|
35
|
+
constructors: 'off',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
|
|
26
40
|
// TypeScript `any` type must not be used. This is a warning in the base
|
|
27
41
|
// config, and is elevated to an error here.
|
|
28
42
|
'@typescript-eslint/no-explicit-any': 'error',
|
package/package.json
CHANGED
package/rules/README.md
CHANGED
|
@@ -34,3 +34,13 @@ console.log( 'done! but not really' );
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
In the example above, `'done! but not really'` is logged before the promises returned by `processLetter` have resolved. This is because the array is iterated immediately and execution proceeds without awaiting promise resolution.
|
|
37
|
+
|
|
38
|
+
## `nestjs-route-prefix`
|
|
39
|
+
|
|
40
|
+
This rule checks Nest.js controller route decorators for specific conventions related to route configuration. These constraints are enforced in an effort to improve code readability and searchability within the application.
|
|
41
|
+
|
|
42
|
+
The `@Controller` and HTTP method decorators (`@Get`, `@Post`, `@Put`, `@Delete`, `@Patch`, `@Options`, `@Head`) are examined in this process.
|
|
43
|
+
|
|
44
|
+
- The `@Controller` decorator should not have any route prefixes. For example, this means `@Controller('users')` will be flagged as incorrect.
|
|
45
|
+
|
|
46
|
+
- The HTTP method decorators (`@Get`, `@Post`, etc.) should have a route that starts with `/` and does not end with `/`. For example, `@Get('/users/')` would be flagged as incorrect.
|
package/rules/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
module.exports = {
|
|
5
5
|
'dependency-group': require( './dependency-group' ),
|
|
6
|
+
'nestjs-route-prefix': require( './nestjs-route-prefix' ),
|
|
6
7
|
'no-async-foreach': require( './no-async-foreach' ),
|
|
7
8
|
'no-unguarded-get-range-at': require( './no-unguarded-get-range-at' ),
|
|
8
9
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: @automattic/wpvip/nestjs-route-prefix
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const nestJsControllerDecorators = [ 'Controller' ];
|
|
6
|
+
const nestJsRouteDecorators = [ 'Get', 'Post', 'Put', 'Delete', 'Patch', 'Options', 'Head' ];
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
create( context ) {
|
|
10
|
+
return {
|
|
11
|
+
Decorator( node ) {
|
|
12
|
+
if ( ! node.expression.callee?.name ) {
|
|
13
|
+
// If it's not a callable method, bail out since Nest.js route controller decorators always a callable method.
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const decoratorName = node.expression.callee.name;
|
|
18
|
+
const argument = node.expression?.arguments[ 0 ] ?? [];
|
|
19
|
+
|
|
20
|
+
if ( nestJsControllerDecorators.includes( decoratorName ) ) {
|
|
21
|
+
if ( argument && argument.type === 'Literal' && argument.value !== '' ) {
|
|
22
|
+
context.report( {
|
|
23
|
+
node,
|
|
24
|
+
message: '@Controller should not have route prefixes.',
|
|
25
|
+
} );
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if ( nestJsRouteDecorators.includes( decoratorName ) ) {
|
|
31
|
+
if (
|
|
32
|
+
! argument ||
|
|
33
|
+
argument.type !== 'Literal' ||
|
|
34
|
+
! argument.value.startsWith( '/' ) ||
|
|
35
|
+
argument.value.endsWith( '/' )
|
|
36
|
+
) {
|
|
37
|
+
context.report( {
|
|
38
|
+
node,
|
|
39
|
+
message: `@${ decoratorName } should have a route starting with '/' and not ending with '/'.`,
|
|
40
|
+
} );
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
};
|