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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-drizzle",
3
- "version": "0.2.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 `db.delete(...).where(...)` instead. Otherwise you can ignore this rule here",
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: 'Without `.where(...)` you will update all the rows in a table. If you didn\'t want to do it, please use `db.update(...).set(...).where(...)` instead. Otherwise you can ignore this rule here'
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;
@@ -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;
@@ -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
- if (typeof drizzleObjectName === 'string'
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
- if (typeof drizzleObjectName === 'string'
22
- && node.object.property.name === drizzleObjectName) {
23
- return true;
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 (Array.isArray(drizzleObjectName)) {
26
- if (drizzleObjectName.length === 0) {
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;