eslint-plugin-drizzle 0.2.2 → 0.2.3-a4d758d
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/package.json +2 -1
- package/readme.md +8 -0
- package/src/enforce-delete-with-where.js +5 -1
- package/src/enforce-update-with-where.js +5 -1
- package/src/utils/ast.js +42 -0
- package/src/utils/options.js +20 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-drizzle",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3-a4d758d",
|
|
4
4
|
"description": "Eslint plugin for drizzle users to avoid common pitfalls",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"license": "Apache-2.0",
|
|
24
24
|
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.10.1",
|
|
25
26
|
"@typescript-eslint/parser": "^6.10.0",
|
|
26
27
|
"@typescript-eslint/rule-tester": "^6.10.0",
|
|
27
28
|
"@typescript-eslint/utils": "^6.10.0",
|
package/readme.md
CHANGED
|
@@ -9,7 +9,9 @@ For cases where it's impossible to perform type checks for specific scenarios, o
|
|
|
9
9
|
```sh
|
|
10
10
|
[ npm | yarn | pnpm | bun ] install eslint eslint-plugin-drizzle
|
|
11
11
|
```
|
|
12
|
+
|
|
12
13
|
You can install those packages for typescript support in your IDE
|
|
14
|
+
|
|
13
15
|
```sh
|
|
14
16
|
[ npm | yarn | pnpm | bun ] install @typescript-eslint/eslint-plugin @typescript-eslint/parser
|
|
15
17
|
```
|
|
@@ -65,6 +67,7 @@ plugins:
|
|
|
65
67
|
Optionally, you can define a `drizzleObjectName` in the plugin options that accept a `string` or `string[]`. This is useful when you have objects or classes with a delete method that's not from Drizzle. Such a `delete` method will trigger the ESLint rule. To avoid that, you can define the name of the Drizzle object that you use in your codebase (like db) so that the rule would only trigger if the delete method comes from this object:
|
|
66
68
|
|
|
67
69
|
Example, config 1:
|
|
70
|
+
|
|
68
71
|
```json
|
|
69
72
|
"rules": {
|
|
70
73
|
"drizzle/enforce-delete-with-where": ["error"]
|
|
@@ -89,11 +92,13 @@ db.delete()
|
|
|
89
92
|
```
|
|
90
93
|
|
|
91
94
|
Example, config 2:
|
|
95
|
+
|
|
92
96
|
```json
|
|
93
97
|
"rules": {
|
|
94
98
|
"drizzle/enforce-delete-with-where": ["error", { "drizzleObjectName": ["db"] }],
|
|
95
99
|
}
|
|
96
100
|
```
|
|
101
|
+
|
|
97
102
|
```ts
|
|
98
103
|
class MyClass {
|
|
99
104
|
public delete() {
|
|
@@ -116,6 +121,7 @@ db.delete()
|
|
|
116
121
|
Optionally, you can define a `drizzleObjectName` in the plugin options that accept a `string` or `string[]`. This is useful when you have objects or classes with a delete method that's not from Drizzle. Such as `update` method will trigger the ESLint rule. To avoid that, you can define the name of the Drizzle object that you use in your codebase (like db) so that the rule would only trigger if the delete method comes from this object:
|
|
117
122
|
|
|
118
123
|
Example, config 1:
|
|
124
|
+
|
|
119
125
|
```json
|
|
120
126
|
"rules": {
|
|
121
127
|
"drizzle/enforce-update-with-where": ["error"]
|
|
@@ -140,11 +146,13 @@ db.update()
|
|
|
140
146
|
```
|
|
141
147
|
|
|
142
148
|
Example, config 2:
|
|
149
|
+
|
|
143
150
|
```json
|
|
144
151
|
"rules": {
|
|
145
152
|
"drizzle/enforce-update-with-where": ["error", { "drizzleObjectName": ["db"] }],
|
|
146
153
|
}
|
|
147
154
|
```
|
|
155
|
+
|
|
148
156
|
```ts
|
|
149
157
|
class MyClass {
|
|
150
158
|
public update() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("@typescript-eslint/utils");
|
|
4
|
+
const ast_1 = require("./utils/ast");
|
|
4
5
|
const options_1 = require("./utils/options");
|
|
5
6
|
const createRule = utils_1.ESLintUtils.RuleCreator(() => 'https://github.com/drizzle-team/eslint-plugin-drizzle');
|
|
6
7
|
let lastNodeName = '';
|
|
@@ -14,7 +15,7 @@ const deleteRule = createRule({
|
|
|
14
15
|
},
|
|
15
16
|
fixable: 'code',
|
|
16
17
|
messages: {
|
|
17
|
-
enforceDeleteWithWhere: "Without `.where(...)` you will delete all the rows in a table. If you didn't want to do it, please use `
|
|
18
|
+
enforceDeleteWithWhere: "Without `.where(...)` you will delete all the rows in a table. If you didn't want to do it, please use `{{ drizzleObjName }}.delete(...).where(...)` instead. Otherwise you can ignore this rule here",
|
|
18
19
|
},
|
|
19
20
|
schema: [{
|
|
20
21
|
type: 'object',
|
|
@@ -34,6 +35,9 @@ const deleteRule = createRule({
|
|
|
34
35
|
context.report({
|
|
35
36
|
node,
|
|
36
37
|
messageId: 'enforceDeleteWithWhere',
|
|
38
|
+
data: {
|
|
39
|
+
drizzleObjName: (0, ast_1.resolveMemberExpressionPath)(node),
|
|
40
|
+
},
|
|
37
41
|
});
|
|
38
42
|
}
|
|
39
43
|
lastNodeName = node.property.name;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("@typescript-eslint/utils");
|
|
4
|
+
const ast_1 = require("./utils/ast");
|
|
4
5
|
const options_1 = require("./utils/options");
|
|
5
6
|
const createRule = utils_1.ESLintUtils.RuleCreator(() => 'https://github.com/drizzle-team/eslint-plugin-drizzle');
|
|
6
7
|
let lastNodeName = '';
|
|
@@ -14,7 +15,7 @@ const updateRule = createRule({
|
|
|
14
15
|
},
|
|
15
16
|
fixable: 'code',
|
|
16
17
|
messages: {
|
|
17
|
-
enforceUpdateWithWhere:
|
|
18
|
+
enforceUpdateWithWhere: "Without `.where(...)` you will update all the rows in a table. If you didn't want to do it, please use `{{ drizzleObjName }}.update(...).set(...).where(...)` instead. Otherwise you can ignore this rule here",
|
|
18
19
|
},
|
|
19
20
|
schema: [{
|
|
20
21
|
type: 'object',
|
|
@@ -40,6 +41,9 @@ const updateRule = createRule({
|
|
|
40
41
|
context.report({
|
|
41
42
|
node,
|
|
42
43
|
messageId: 'enforceUpdateWithWhere',
|
|
44
|
+
data: {
|
|
45
|
+
drizzleObjName: (0, ast_1.resolveMemberExpressionPath)(node.object.callee),
|
|
46
|
+
},
|
|
43
47
|
});
|
|
44
48
|
}
|
|
45
49
|
lastNodeName = node.property.name;
|
package/src/utils/ast.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveMemberExpressionPath = void 0;
|
|
4
|
+
const resolveMemberExpressionPath = (node) => {
|
|
5
|
+
let objectExpression = node.object;
|
|
6
|
+
let fullName = '';
|
|
7
|
+
const addToFullName = (name) => {
|
|
8
|
+
const prefix = fullName ? '.' : '';
|
|
9
|
+
fullName = `${name}${prefix}${fullName}`;
|
|
10
|
+
};
|
|
11
|
+
while (objectExpression) {
|
|
12
|
+
if (objectExpression.type === 'MemberExpression') {
|
|
13
|
+
if (objectExpression.property.type === 'Identifier') {
|
|
14
|
+
addToFullName(objectExpression.property.name);
|
|
15
|
+
}
|
|
16
|
+
objectExpression = objectExpression.object;
|
|
17
|
+
}
|
|
18
|
+
else if (objectExpression.type === 'CallExpression' && objectExpression.callee.type === 'Identifier') {
|
|
19
|
+
addToFullName(`${objectExpression.callee.name}(...)`);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
else if (objectExpression.type === 'CallExpression' && objectExpression.callee.type === 'MemberExpression') {
|
|
23
|
+
if (objectExpression.callee.property.type === 'Identifier') {
|
|
24
|
+
addToFullName(`${objectExpression.callee.property.name}(...)`);
|
|
25
|
+
}
|
|
26
|
+
objectExpression = objectExpression.callee.object;
|
|
27
|
+
}
|
|
28
|
+
else if (objectExpression.type === 'Identifier') {
|
|
29
|
+
addToFullName(objectExpression.name);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
else if (objectExpression.type === 'ThisExpression') {
|
|
33
|
+
addToFullName('this');
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return fullName;
|
|
41
|
+
};
|
|
42
|
+
exports.resolveMemberExpressionPath = resolveMemberExpressionPath;
|
package/src/utils/options.js
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isDrizzleObj = void 0;
|
|
4
|
+
const isDrizzleObjName = (name, drizzleObjectName) => {
|
|
5
|
+
if (typeof drizzleObjectName === 'string') {
|
|
6
|
+
return name === drizzleObjectName;
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(drizzleObjectName)) {
|
|
9
|
+
if (drizzleObjectName.length === 0) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return drizzleObjectName.includes(name);
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
4
16
|
const isDrizzleObj = (node, options) => {
|
|
5
17
|
const drizzleObjectName = options[0].drizzleObjectName;
|
|
6
18
|
if (node.object.type === 'Identifier') {
|
|
7
|
-
|
|
8
|
-
&& node.object.name === drizzleObjectName) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
if (Array.isArray(drizzleObjectName)) {
|
|
12
|
-
if (drizzleObjectName.length === 0) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
if (drizzleObjectName.includes(node.object.name)) {
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
+
return isDrizzleObjName(node.object.name, drizzleObjectName);
|
|
19
20
|
}
|
|
20
21
|
else if (node.object.type === 'MemberExpression' && node.object.property.type === 'Identifier') {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
return isDrizzleObjName(node.object.property.name, drizzleObjectName);
|
|
23
|
+
}
|
|
24
|
+
else if (node.object.type === 'CallExpression') {
|
|
25
|
+
if (node.object.callee.type === 'Identifier') {
|
|
26
|
+
return isDrizzleObjName(node.object.callee.name, drizzleObjectName);
|
|
24
27
|
}
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
if (drizzleObjectName.includes(node.object.property.name)) {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
28
|
+
else if (node.object.callee.type === 'MemberExpression' && node.object.callee.property.type === 'Identifier') {
|
|
29
|
+
return isDrizzleObjName(node.object.callee.property.name, drizzleObjectName);
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
return false;
|