@adonisjs/eslint-plugin 1.1.2 → 1.1.3
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 +34 -0
- package/dist/bin/test.js +0 -8
- package/dist/src/rules/prefer_lazy_controller_import.js +31 -23
- package/dist/src/rules/prefer_lazy_listener_import.js +84 -0
- package/dist/tests/prefer_lazy_controller_import.spec.js +9 -0
- package/dist/tests/prefer_lazy_listener_import.spec.js +42 -0
- package/package.json +16 -4
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# `@adonisjs/eslint-plugin`
|
|
2
|
+
|
|
3
|
+
ESLint plugin to enforce AdonisJS specific linting rules. Following is the list of available rules.
|
|
4
|
+
|
|
5
|
+
- `prefer-lazy-controller-import`: Enforces and auto fixes standard HTTP controller imports inside the routes file to lazy imports. Lazy imports improves the application load time.
|
|
6
|
+
- `prefer-lazy-listener-import`: Enforces and auto fixes standard event listener imports inside the events file to lazy imports. Lazy imports improves the application load time.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Install the package as a development dependency from the npm packages registry.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm i -D @adonisjs/eslint-plugin
|
|
14
|
+
|
|
15
|
+
# For yarn lovers
|
|
16
|
+
yarn add -D @adonisjs/eslint-plugin
|
|
17
|
+
|
|
18
|
+
# For pnpm believers
|
|
19
|
+
pnpm add -D @adonisjs/eslint-plugin
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
Add the following rule to your eslint config file.
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
{
|
|
28
|
+
plugins: ['@adonisjs/eslint-plugin'],
|
|
29
|
+
rules: {
|
|
30
|
+
'@adonisjs/prefer-lazy-controller-import': 'error',
|
|
31
|
+
'@adonisjs/prefer-lazy-listener-import': 'error',
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
```
|
package/dist/bin/test.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* @adonisjs/mail
|
|
4
|
-
*
|
|
5
|
-
* (c) AdonisJS
|
|
6
|
-
*
|
|
7
|
-
* For the full copyright and license information, please view the LICENSE
|
|
8
|
-
* file that was distributed with this source code.
|
|
9
|
-
*/
|
|
10
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
3
|
const assert_1 = require("@japa/assert");
|
|
12
4
|
const spec_reporter_1 = require("@japa/spec-reporter");
|
|
@@ -10,12 +10,12 @@ exports.default = (0, utils_2.createEslintRule)({
|
|
|
10
10
|
type: 'problem',
|
|
11
11
|
fixable: 'code',
|
|
12
12
|
docs: {
|
|
13
|
-
description: 'Prefer lazy controller import over
|
|
13
|
+
description: 'Prefer lazy controller import over standard import',
|
|
14
14
|
recommended: 'error',
|
|
15
15
|
},
|
|
16
16
|
schema: [],
|
|
17
17
|
messages: {
|
|
18
|
-
preferLazyControllerImport: '
|
|
18
|
+
preferLazyControllerImport: 'Replace standard import with lazy controller import',
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
21
|
create: function (context) {
|
|
@@ -47,29 +47,37 @@ exports.default = (0, utils_2.createEslintRule)({
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
/**
|
|
51
|
-
* Check if we are calling router.get() or any other http method
|
|
52
|
-
*/
|
|
53
50
|
CallExpression(node) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Check if we are calling router.get() or any other http method
|
|
53
|
+
*/
|
|
54
|
+
if (!isRouteCallExpression(node, routerIdentifier)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Ensure the second argument is an array
|
|
59
|
+
*/
|
|
60
|
+
const secondArgument = node.arguments[1];
|
|
61
|
+
if (secondArgument.type !== utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
for (const element of secondArgument.elements) {
|
|
65
|
+
/**
|
|
66
|
+
* If we are dealing with an Identifier that was imported
|
|
67
|
+
* through a standard import, then report it as an error
|
|
68
|
+
*/
|
|
69
|
+
if (element.type !== 'Identifier' || !importIdentifiers.includes(element.name)) {
|
|
70
|
+
continue;
|
|
72
71
|
}
|
|
72
|
+
context.report({
|
|
73
|
+
node: importNodes[element.name],
|
|
74
|
+
messageId: 'preferLazyControllerImport',
|
|
75
|
+
fix(fixer) {
|
|
76
|
+
const importPath = importNodes[element.name].source.raw;
|
|
77
|
+
const newImportDeclaration = `const ${element.name} = () => import(${importPath})`;
|
|
78
|
+
return fixer.replaceText(importNodes[element.name], newImportDeclaration);
|
|
79
|
+
},
|
|
80
|
+
});
|
|
73
81
|
}
|
|
74
82
|
},
|
|
75
83
|
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
4
|
+
const utils_2 = require("../utils");
|
|
5
|
+
exports.default = (0, utils_2.createEslintRule)({
|
|
6
|
+
name: 'prefer-lazy-listener-import',
|
|
7
|
+
defaultOptions: [],
|
|
8
|
+
meta: {
|
|
9
|
+
type: 'problem',
|
|
10
|
+
fixable: 'code',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Prefer lazy listener import over standard import',
|
|
13
|
+
recommended: 'error',
|
|
14
|
+
},
|
|
15
|
+
schema: [],
|
|
16
|
+
messages: {
|
|
17
|
+
preferLazyListenerImport: 'Replace standard import with lazy listener import',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create: function (context) {
|
|
21
|
+
let importIdentifiers = [];
|
|
22
|
+
let emitterIdentifier = '';
|
|
23
|
+
let importNodes = [];
|
|
24
|
+
function isEmitterOnCallExpression(node, routerIdentifier) {
|
|
25
|
+
return (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
26
|
+
node.callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
27
|
+
node.callee.object.name === routerIdentifier &&
|
|
28
|
+
node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
29
|
+
node.callee.property.name === 'on');
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
/**
|
|
33
|
+
* Track all imported identifiers
|
|
34
|
+
* Also get the local name of the emitter import
|
|
35
|
+
*/
|
|
36
|
+
ImportDeclaration(node) {
|
|
37
|
+
for (const specifier of node.specifiers) {
|
|
38
|
+
if (specifier.type === 'ImportDefaultSpecifier' || specifier.type === 'ImportSpecifier') {
|
|
39
|
+
importIdentifiers.push(specifier.local.name);
|
|
40
|
+
importNodes[specifier.local.name] = node;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (node.source.value === '@adonisjs/core/services/emitter') {
|
|
44
|
+
if (node.specifiers[0] && node.specifiers[0].type === 'ImportDefaultSpecifier') {
|
|
45
|
+
emitterIdentifier = node.specifiers[0].local.name;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
CallExpression(node) {
|
|
50
|
+
/**
|
|
51
|
+
* Check if we are calling emitter.on()
|
|
52
|
+
*/
|
|
53
|
+
if (!isEmitterOnCallExpression(node, emitterIdentifier)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Ensure the second argument is an array
|
|
58
|
+
*/
|
|
59
|
+
const secondArgument = node.arguments[1];
|
|
60
|
+
if (secondArgument.type !== utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
for (const element of secondArgument.elements) {
|
|
64
|
+
/**
|
|
65
|
+
* If we are dealing with an Identifier that was imported
|
|
66
|
+
* through a standard import, then report it as an error
|
|
67
|
+
*/
|
|
68
|
+
if (element.type !== 'Identifier' || !importIdentifiers.includes(element.name)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
context.report({
|
|
72
|
+
node: importNodes[element.name],
|
|
73
|
+
messageId: 'preferLazyListenerImport',
|
|
74
|
+
fix(fixer) {
|
|
75
|
+
const importPath = importNodes[element.name].source.raw;
|
|
76
|
+
const newImportDeclaration = `const ${element.name} = () => import(${importPath})`;
|
|
77
|
+
return fixer.replaceText(importNodes[element.name], newImportDeclaration);
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
});
|
|
@@ -10,6 +10,15 @@ const valids = [
|
|
|
10
10
|
|
|
11
11
|
router.get("/", "HomeController.index")
|
|
12
12
|
router.get("/test", [lazyController, 'index'])
|
|
13
|
+
`,
|
|
14
|
+
`
|
|
15
|
+
import router from "@adonisjs/core/services/router"
|
|
16
|
+
import middleware from '#start/middleware'
|
|
17
|
+
|
|
18
|
+
const lazyController = () => import("./controller")
|
|
19
|
+
|
|
20
|
+
router.get("/", "HomeController.index").middleware(middleware.auth())
|
|
21
|
+
router.get("/test", [lazyController, 'index']).middleware(middleware.auth())
|
|
13
22
|
`,
|
|
14
23
|
];
|
|
15
24
|
const invalids = [
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const runner_1 = require("@japa/runner");
|
|
4
|
+
const ts_eslint_1 = require("@typescript-eslint/utils/dist/ts-eslint");
|
|
5
|
+
const prefer_lazy_listener_import_1 = require("../src/rules/prefer_lazy_listener_import");
|
|
6
|
+
const valids = [
|
|
7
|
+
`
|
|
8
|
+
import emitter from '@adonisjs/core/services/emitter'
|
|
9
|
+
const SendVerificationEmail = () => import('#listeners/send_verification_email')
|
|
10
|
+
|
|
11
|
+
emitter.on('user:registered', [SendVerificationEmail, 'handle'])
|
|
12
|
+
`,
|
|
13
|
+
];
|
|
14
|
+
const invalids = [
|
|
15
|
+
[
|
|
16
|
+
`
|
|
17
|
+
import emitter from '@adonisjs/core/services/emitter'
|
|
18
|
+
import SendVerificationEmail from '#listeners/send_verification_email'
|
|
19
|
+
|
|
20
|
+
emitter.on('user:registered', [SendVerificationEmail, 'handle'])
|
|
21
|
+
`,
|
|
22
|
+
`
|
|
23
|
+
import emitter from '@adonisjs/core/services/emitter'
|
|
24
|
+
const SendVerificationEmail = () => import('#listeners/send_verification_email')
|
|
25
|
+
|
|
26
|
+
emitter.on('user:registered', [SendVerificationEmail, 'handle'])
|
|
27
|
+
`,
|
|
28
|
+
],
|
|
29
|
+
];
|
|
30
|
+
(0, runner_1.test)('Prefer lazy event listener import', ({ assert }) => {
|
|
31
|
+
const ruleTester = new ts_eslint_1.RuleTester({
|
|
32
|
+
parser: require.resolve('@typescript-eslint/parser'),
|
|
33
|
+
});
|
|
34
|
+
ruleTester.run('prefer-lazy-listener-import', prefer_lazy_listener_import_1.default, {
|
|
35
|
+
valid: valids,
|
|
36
|
+
invalid: invalids.map((invalid) => ({
|
|
37
|
+
code: invalid[0],
|
|
38
|
+
output: invalid[1],
|
|
39
|
+
errors: [{ messageId: 'preferLazyListenerImport' }],
|
|
40
|
+
})),
|
|
41
|
+
});
|
|
42
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonisjs/eslint-plugin",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "ESLint plugin to enforce AdonisJS app specific linting rules",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
7
7
|
],
|
|
8
8
|
"main": "dist/src/index.js",
|
|
9
|
-
"
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/src/index.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"eslint",
|
|
14
|
+
"adonisjs",
|
|
15
|
+
"eslint-plugin"
|
|
16
|
+
],
|
|
10
17
|
"author": "Julien Ripouteau <julien@ripouteau.com>",
|
|
11
|
-
"
|
|
18
|
+
"contributors": [
|
|
19
|
+
"virk",
|
|
20
|
+
"adonisjs"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT",
|
|
12
23
|
"dependencies": {
|
|
13
24
|
"@typescript-eslint/utils": "^5.59.11"
|
|
14
25
|
},
|
|
@@ -23,6 +34,7 @@
|
|
|
23
34
|
},
|
|
24
35
|
"scripts": {
|
|
25
36
|
"build": "tsc --outDir dist",
|
|
37
|
+
"test": "ts-node bin/test.ts",
|
|
26
38
|
"quick:test": "ts-node bin/test.ts"
|
|
27
39
|
}
|
|
28
40
|
}
|