@1024pix/eslint-plugin 1.2.2 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # [1.3.0](https://github.com/1024pix/eslint-plugin/compare/v1.2.2...v1.3.0) (2024-07-16)
2
+
3
+ ### :rocket: Amélioration
4
+
5
+ - [#25](https://github.com/1024pix/eslint-plugin/pull/25) Ajout d'une règle forcant l'ajout d'un commentaire sur les colonnes.
6
+
1
7
  ## [1.2.2](https://github.com/1024pix/eslint-plugin/compare/v1.2.1...v1.2.2) (2024-07-16)
2
8
 
3
9
  ### :bug: Correction
package/config.js CHANGED
@@ -87,6 +87,7 @@ module.exports = [
87
87
  },
88
88
  ],
89
89
  '@1024pix/no-sinon-stub-with-args-oneliner': 'error',
90
+ '@1024pix/no-column-migration-without-comment': 'error',
90
91
  },
91
92
  },
92
93
  ];
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
  const noSinonStubWithArgsOneliner = require('./rules/no-sinon-stub-with-args-oneliner.js');
3
+ const noColumnMigrationWithoutComment = require('./rules/no-column-migration-without-comment.js');
3
4
 
4
5
  module.exports = {
5
- rules: { 'no-sinon-stub-with-args-oneliner': noSinonStubWithArgsOneliner },
6
+ rules: { 'no-sinon-stub-with-args-oneliner': noSinonStubWithArgsOneliner, 'no-column-migration-without-comment': noColumnMigrationWithoutComment },
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1024pix/eslint-plugin",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Des règles de lint pour les projets 1024pix",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ function report(context, node) {
4
+ context.report({
5
+ node: node,
6
+ messageId: 'chainError',
7
+ });
8
+ }
9
+
10
+
11
+ function getIdentifierName(node, stackName = []) {
12
+ switch (node.type) {
13
+ case 'Identifier':
14
+ return { identifier: node.name, callStack: stackName };
15
+ case 'MemberExpression':
16
+ return getIdentifierName(node.object, [...stackName, node.property.name])
17
+ case 'CallExpression':
18
+ return getIdentifierName(node.callee, stackName);
19
+ case 'AwaitExpression':
20
+ return getIdentifierName(node.argument, stackName);
21
+ }
22
+ }
23
+
24
+ const VALID_MEMBER_EXPRESSIONS = ['dropColumn', 'foreign', 'unique', 'index', 'dropUnique', 'dropIndex'];
25
+
26
+ module.exports = {
27
+ meta: {
28
+ type: 'problem',
29
+ docs: {
30
+ description:
31
+ 'All columns should have a comment explaining their purpose',
32
+ },
33
+ messages: {
34
+ chainError:
35
+ '`table.column()` should have a comment explaining its purpose',
36
+ },
37
+ },
38
+ create: function(context) {
39
+ return {
40
+ CallExpression(node) {
41
+ const { callee } = node;
42
+
43
+ if (
44
+ callee.type === 'MemberExpression' &&
45
+ callee.object &&
46
+ callee.object.object &&
47
+ callee.object.object.name === 'knex' &&
48
+ callee.object.property &&
49
+ callee.object.property.name === 'schema' &&
50
+ ['alterTable', 'createTable', 'table'].includes(callee.property.name)
51
+ ) {
52
+ const callback = node.arguments[1];
53
+
54
+ if (callback && callback.type === 'ArrowFunctionExpression') {
55
+ const tableParam = callback.params[0];
56
+
57
+ if (tableParam && tableParam.type === 'Identifier') {
58
+
59
+ const body = callback.body.body ?? [{ expression: callback.body }];
60
+
61
+ body.forEach(statement => {
62
+ const columnExpression = statement.expression;
63
+
64
+ const { identifier: identifierName, callStack } = getIdentifierName(columnExpression);
65
+
66
+ if (!callStack.some((call) => VALID_MEMBER_EXPRESSIONS.includes(call))) {
67
+ if (identifierName === tableParam.name) {
68
+ const hasComment = callStack.includes('comment');
69
+
70
+ if (!hasComment) {
71
+ report(context, node);
72
+ }
73
+ }
74
+ }
75
+
76
+ });
77
+ }
78
+ }
79
+ }
80
+ }
81
+ };
82
+ }
83
+ };
@@ -0,0 +1,260 @@
1
+ 'use strict';
2
+
3
+ const rule = require('./no-column-migration-without-comment.js'),
4
+ RuleTester = require('eslint').RuleTester;
5
+
6
+ const ruleTester = new RuleTester({
7
+ parserOptions: { ecmaVersion: 2021, sourceType: 'module' },
8
+ });
9
+
10
+ ruleTester.run('no-column-migration-without-comment', rule, {
11
+ valid: [
12
+ // createTable
13
+ {
14
+ name: 'With comment',
15
+ code: `
16
+ const up = function (knex) {
17
+ return knex.schema.createTable(TABLE_NAME, (table) => {
18
+ table.boolean(COLUMN_NAME).comment('This is a comment');
19
+ });
20
+ };
21
+ `,
22
+ },
23
+
24
+ {
25
+ name: 'Without using table callback',
26
+ code: `
27
+ const up = function (knex) {
28
+ return knex.schema.createTable(TABLE_NAME, (table) => {
29
+ toto.maFunction();
30
+ });
31
+ };
32
+ `,
33
+ },
34
+
35
+ // alterTable
36
+ {
37
+ name: 'With comment',
38
+ code: `
39
+ const up = function (knex) {
40
+ return knex.schema.alterTable(TABLE_NAME, (table) => {
41
+ table.boolean(COLUMN_NAME).comment('This is a comment');
42
+ });
43
+ };
44
+ `,
45
+ },
46
+
47
+ {
48
+ name: 'Without using table callback',
49
+ code: `
50
+ const up = function (knex) {
51
+ return knex.schema.alterTable(TABLE_NAME, (table) => {
52
+ toto.maFunction();
53
+ });
54
+ };
55
+ `,
56
+ },
57
+
58
+ // table
59
+
60
+ {
61
+ name: 'With comment',
62
+ code: `
63
+ const up = function (knex) {
64
+ return knex.schema.table(TABLE_NAME, (table) => {
65
+ table.boolean(COLUMN_NAME).comment('This is a comment');
66
+ });
67
+ };
68
+ `,
69
+ },
70
+
71
+ {
72
+ name: 'Without using table callback',
73
+ code: `
74
+ const up = function (knex) {
75
+ return knex.schema.table(TABLE_NAME, (table) => {
76
+ toto.maFunction();
77
+ });
78
+ };
79
+ `,
80
+ },
81
+
82
+
83
+ {
84
+ name: 'With down function',
85
+ code: `
86
+ const down = function (knex) {
87
+ return knex.schema.table(TABLE_NAME, (table) => {
88
+ table.boolean('toto').comment('This is a comment');
89
+ });
90
+ };
91
+ `,
92
+ },
93
+
94
+
95
+ {
96
+ name: 'With dropColumn',
97
+ code: `
98
+ const up = function (knex) {
99
+ return knex.schema.table(TABLE_NAME, (table) => {
100
+ table.dropColumn('toto');
101
+ });
102
+ };
103
+ `,
104
+ },
105
+
106
+ {
107
+ name: 'With foreign',
108
+ code: `
109
+ const up = function (knex) {
110
+ return knex.schema.table(TABLE_NAME, (table) => {
111
+ table.foreign('toto');
112
+ });
113
+ };
114
+ `,
115
+ },
116
+
117
+ {
118
+ name: 'With unique',
119
+ code: `
120
+ const up = function (knex) {
121
+ return knex.schema.table(TABLE_NAME, (table) => {
122
+ table.unique('toto');
123
+ });
124
+ };
125
+ `,
126
+ },
127
+
128
+ {
129
+ name: 'With index',
130
+ code: `
131
+ const up = function (knex) {
132
+ return knex.schema.table(TABLE_NAME, (table) => {
133
+ table.index('toto');
134
+ });
135
+ };
136
+ `,
137
+ },
138
+
139
+ {
140
+ name: 'With dropUnique',
141
+ code: `
142
+ const up = function (knex) {
143
+ return knex.schema.table(TABLE_NAME, (table) => {
144
+ table.dropUnique('toto');
145
+ });
146
+ };
147
+ `,
148
+ },
149
+
150
+ {
151
+ name: 'With dropIndex',
152
+ code: `
153
+ const up = function (knex) {
154
+ return knex.schema.table(TABLE_NAME, (table) => {
155
+ table.dropIndex('toto');
156
+ });
157
+ };
158
+ `,
159
+ },
160
+
161
+ {
162
+ name: 'With oneliner',
163
+ code: `
164
+ const up = function (knex) {
165
+ return knex.schema.table(TABLE_NAME, (table) => table.boolean('toto').comment('comment'));
166
+ };
167
+ `,
168
+ },
169
+
170
+ {
171
+ name: 'With await',
172
+ code: `
173
+ const up = async function (knex) {
174
+ return knex.schema.alterTable(TABLE_NAME, async (table) => {
175
+ await table.decimal(COLUMN, 5, 2).notNullable().alter().comment('toto');
176
+ });
177
+ };
178
+ `,
179
+ },
180
+ ],
181
+
182
+ invalid: [
183
+
184
+ // CreateTable
185
+ {
186
+ name: 'Create column without comment',
187
+ code: `
188
+ const up = function (knex) {
189
+ return knex.schema.createTable(TABLE_NAME, (table) => {
190
+ table.boolean(COLUMN_NAME).defaultTo(false);
191
+ });
192
+ };
193
+ `,
194
+ errors: [{ messageId: 'chainError' }],
195
+ },
196
+ {
197
+ name: 'Create column without comment',
198
+ code: `
199
+ const up = function (knex) {
200
+ return knex.schema.createTable(TABLE_NAME, (table) => {
201
+ table.boolean(COLUMN_NAME).defaultTo(false).comment('toto');
202
+ table.boolean(COLUMN_NAME_2).defaultTo(false);
203
+ });
204
+ };
205
+ `,
206
+ errors: [{ messageId: 'chainError' }],
207
+ },
208
+
209
+ // AlterTable
210
+
211
+ {
212
+ name: 'Create column without comment',
213
+ code: `
214
+ const up = function (knex) {
215
+ return knex.schema.alterTable(TABLE_NAME, (table) => {
216
+ table.boolean(COLUMN_NAME).defaultTo(false);
217
+ });
218
+ };
219
+ `,
220
+ errors: [{ messageId: 'chainError' }],
221
+ },
222
+ {
223
+ name: 'Create column without comment',
224
+ code: `
225
+ const up = function (knex) {
226
+ return knex.schema.alterTable(TABLE_NAME, (table) => {
227
+ table.boolean(COLUMN_NAME).defaultTo(false).comment('toto');
228
+ table.boolean(COLUMN_NAME_2).defaultTo(false);
229
+ });
230
+ };
231
+ `,
232
+ errors: [{ messageId: 'chainError' }],
233
+ },
234
+
235
+ // table
236
+ {
237
+ name: 'Create column without comment',
238
+ code: `
239
+ const up = function (knex) {
240
+ return knex.schema.table(TABLE_NAME, (table) => {
241
+ table.boolean(COLUMN_NAME).defaultTo(false);
242
+ });
243
+ };
244
+ `,
245
+ errors: [{ messageId: 'chainError' }],
246
+ },
247
+ {
248
+ name: 'Create column without comment',
249
+ code: `
250
+ const up = function (knex) {
251
+ return knex.schema.table(TABLE_NAME, (table) => {
252
+ table.boolean(COLUMN_NAME).defaultTo(false).comment('toto');
253
+ table.boolean(COLUMN_NAME_2).defaultTo(false);
254
+ });
255
+ };
256
+ `,
257
+ errors: [{ messageId: 'chainError' }],
258
+ },
259
+ ],
260
+ });