@checkdigit/eslint-plugin 7.17.1 → 8.0.0-PR.141-7ea9

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.
Files changed (64) hide show
  1. package/dist-mjs/aws/is-aws-sdk-v3-used.mjs +7 -3
  2. package/dist-mjs/aws/require-aws-bare-bones.mjs +23 -5
  3. package/dist-mjs/aws/require-aws-config.mjs +5 -2
  4. package/dist-mjs/aws/require-consistent-read.mjs +12 -4
  5. package/dist-mjs/file-path-comment.mjs +15 -6
  6. package/dist-mjs/index.mjs +25 -9
  7. package/dist-mjs/invalid-json-stringify.mjs +8 -3
  8. package/dist-mjs/library/format.mjs +1 -1
  9. package/dist-mjs/library/tree.mjs +7 -2
  10. package/dist-mjs/library/ts-tree.mjs +7 -2
  11. package/dist-mjs/no-card-numbers.mjs +1 -1
  12. package/dist-mjs/no-duplicated-imports.mjs +25 -7
  13. package/dist-mjs/no-legacy-service-typing.mjs +18 -7
  14. package/dist-mjs/no-promise-instance-method.mjs +1 -1
  15. package/dist-mjs/no-random-v4-uuid.mjs +5 -2
  16. package/dist-mjs/no-side-effects.mjs +11 -7
  17. package/dist-mjs/no-status-code-assert.mjs +5 -2
  18. package/dist-mjs/no-test-import.mjs +5 -2
  19. package/dist-mjs/no-util.mjs +1 -1
  20. package/dist-mjs/no-uuid.mjs +1 -1
  21. package/dist-mjs/no-wallaby-comment.mjs +25 -7
  22. package/dist-mjs/object-literal-response.mjs +1 -1
  23. package/dist-mjs/regular-expression-comment.mjs +4 -2
  24. package/dist-mjs/require-assert-message.mjs +1 -1
  25. package/dist-mjs/require-assert-predicate-rejects-throws.mjs +1 -1
  26. package/dist-mjs/require-fixed-services-import.mjs +21 -6
  27. package/dist-mjs/require-resolve-full-response.mjs +32 -11
  28. package/dist-mjs/require-service-call-response-declaration.mjs +12 -4
  29. package/dist-mjs/require-strict-assert.mjs +5 -2
  30. package/dist-mjs/require-ts-extension-imports-exports.mjs +1 -1
  31. package/dist-mjs/require-type-out-of-type-only-imports.mjs +6 -2
  32. package/dist-types/no-legacy-service-typing.d.ts +3 -1
  33. package/package.json +1 -96
  34. package/src/aws/is-aws-sdk-v3-used.ts +6 -2
  35. package/src/aws/require-aws-bare-bones.ts +65 -42
  36. package/src/aws/require-aws-config.ts +85 -63
  37. package/src/aws/require-consistent-read.ts +97 -60
  38. package/src/file-path-comment.ts +12 -3
  39. package/src/index.ts +28 -10
  40. package/src/invalid-json-stringify.ts +9 -3
  41. package/src/library/format.ts +4 -1
  42. package/src/library/tree.ts +8 -2
  43. package/src/library/ts-tree.ts +24 -7
  44. package/src/no-card-numbers.ts +6 -1
  45. package/src/no-duplicated-imports.ts +48 -18
  46. package/src/no-legacy-service-typing.ts +25 -8
  47. package/src/no-promise-instance-method.ts +8 -3
  48. package/src/no-random-v4-uuid.ts +36 -11
  49. package/src/no-side-effects.ts +78 -29
  50. package/src/no-status-code-assert.ts +21 -7
  51. package/src/no-test-import.ts +8 -2
  52. package/src/no-util.ts +3 -1
  53. package/src/no-uuid.ts +8 -2
  54. package/src/no-wallaby-comment.ts +40 -9
  55. package/src/object-literal-response.ts +25 -9
  56. package/src/regular-expression-comment.ts +9 -3
  57. package/src/require-assert-message.ts +13 -5
  58. package/src/require-assert-predicate-rejects-throws.ts +6 -3
  59. package/src/require-fixed-services-import.ts +31 -10
  60. package/src/require-resolve-full-response.ts +221 -172
  61. package/src/require-service-call-response-declaration.ts +23 -8
  62. package/src/require-strict-assert.ts +21 -8
  63. package/src/require-ts-extension-imports-exports.ts +19 -6
  64. package/src/require-type-out-of-type-only-imports.ts +12 -4
@@ -10,8 +10,10 @@ import getDocumentationUrl from './get-documentation-url.ts';
10
10
  */
11
11
 
12
12
  export const ruleId = 'no-promise-instance-method';
13
- export const NO_PROMISE_INSTANCE_METHOD_THEN = 'NO_PROMISE_INSTANCE_METHOD_THEN';
14
- export const NO_PROMISE_INSTANCE_METHOD_CATCH_FINALLY = 'NO_PROMISE_INSTANCE_METHOD_CATCH_FINALLY';
13
+ export const NO_PROMISE_INSTANCE_METHOD_THEN =
14
+ 'NO_PROMISE_INSTANCE_METHOD_THEN';
15
+ export const NO_PROMISE_INSTANCE_METHOD_CATCH_FINALLY =
16
+ 'NO_PROMISE_INSTANCE_METHOD_CATCH_FINALLY';
15
17
 
16
18
  export default {
17
19
  meta: {
@@ -29,7 +31,10 @@ export default {
29
31
  create(context) {
30
32
  return {
31
33
  MemberExpression(node) {
32
- if (node.property.type === 'Identifier' && ['then', 'catch', 'finally'].includes(node.property.name)) {
34
+ if (
35
+ node.property.type === 'Identifier' &&
36
+ ['then', 'catch', 'finally'].includes(node.property.name)
37
+ ) {
33
38
  context.report({
34
39
  node,
35
40
  messageId:
@@ -6,7 +6,12 @@
6
6
  * This code is licensed under the MIT license (see LICENSE.txt for details).
7
7
  */
8
8
 
9
- import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils';
9
+ import {
10
+ AST_NODE_TYPES,
11
+ ESLintUtils,
12
+ TSESLint,
13
+ TSESTree,
14
+ } from '@typescript-eslint/utils';
10
15
  import getDocumentationUrl from './get-documentation-url.ts';
11
16
 
12
17
  export const ruleId = 'no-random-v4-uuid';
@@ -21,7 +26,10 @@ interface Aliases {
21
26
  nodeCryptoRandomUUIDAlias?: string;
22
27
  }
23
28
 
24
- const processImportDeclaration = (node: TSESTree.ImportDeclaration, aliases: Aliases) => {
29
+ const processImportDeclaration = (
30
+ node: TSESTree.ImportDeclaration,
31
+ aliases: Aliases,
32
+ ) => {
25
33
  node.specifiers.forEach((specifier) => {
26
34
  if (specifier.type === AST_NODE_TYPES.ImportSpecifier) {
27
35
  if (
@@ -37,39 +45,54 @@ const processImportDeclaration = (node: TSESTree.ImportDeclaration, aliases: Ali
37
45
  ) {
38
46
  aliases.nodeCryptoRandomUUIDAlias = specifier.local.name;
39
47
  }
40
- } else if (specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier && node.source.value === 'uuid') {
48
+ } else if (
49
+ specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier &&
50
+ node.source.value === 'uuid'
51
+ ) {
41
52
  aliases.uuidDefaultAlias = specifier.local.name;
42
53
  }
43
54
  });
44
55
  };
45
56
 
46
- const isUuid4Call = (node: TSESTree.CallExpression, aliases: Aliases): boolean =>
47
- (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === aliases.uuid4Alias) ||
57
+ const isUuid4Call = (
58
+ node: TSESTree.CallExpression,
59
+ aliases: Aliases,
60
+ ): boolean =>
61
+ (node.callee.type === AST_NODE_TYPES.Identifier &&
62
+ node.callee.name === aliases.uuid4Alias) ||
48
63
  (node.callee.type === AST_NODE_TYPES.MemberExpression &&
49
64
  node.callee.object.type === AST_NODE_TYPES.Identifier &&
50
65
  node.callee.object.name === aliases.uuidDefaultAlias &&
51
66
  node.callee.property.type === AST_NODE_TYPES.Identifier &&
52
67
  node.callee.property.name === 'v4');
53
68
 
54
- const isCryptoRandomUUIDCall = (node: TSESTree.CallExpression, alias?: string): boolean =>
55
- (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === alias) ||
69
+ const isCryptoRandomUUIDCall = (
70
+ node: TSESTree.CallExpression,
71
+ alias?: string,
72
+ ): boolean =>
73
+ (node.callee.type === AST_NODE_TYPES.Identifier &&
74
+ node.callee.name === alias) ||
56
75
  (node.callee.type === AST_NODE_TYPES.MemberExpression &&
57
76
  node.callee.object.type === AST_NODE_TYPES.Identifier &&
58
77
  node.callee.object.name === 'crypto' &&
59
78
  node.callee.property.type === AST_NODE_TYPES.Identifier &&
60
79
  node.callee.property.name === 'randomUUID');
61
80
 
62
- const rule: TSESLint.RuleModule<typeof NO_RANDOM_V4_UUID | typeof NO_UUID_MODULE_FOR_V4> = createRule({
81
+ const rule: TSESLint.RuleModule<
82
+ typeof NO_RANDOM_V4_UUID | typeof NO_UUID_MODULE_FOR_V4
83
+ > = createRule({
63
84
  name: ruleId,
64
85
  meta: {
65
86
  type: 'problem',
66
87
  docs: {
67
- description: 'Disallow the use of `uuid.v4` and `crypto.randomUUID` for generating random v4 UUIDs.',
88
+ description:
89
+ 'Disallow the use of `uuid.v4` and `crypto.randomUUID` for generating random v4 UUIDs.',
68
90
  },
69
91
  schema: [],
70
92
  messages: {
71
93
  [NO_RANDOM_V4_UUID]: 'Avoid generating v4 UUIDs',
72
- [NO_UUID_MODULE_FOR_V4]: 'Avoid using the `uuid` module for v4 UUID generation',
94
+ [NO_UUID_MODULE_FOR_V4]:
95
+ 'Avoid using the `uuid` module for v4 UUID generation',
73
96
  },
74
97
  },
75
98
  defaultOptions: [],
@@ -86,7 +109,9 @@ const rule: TSESLint.RuleModule<typeof NO_RANDOM_V4_UUID | typeof NO_UUID_MODULE
86
109
  node,
87
110
  messageId: NO_UUID_MODULE_FOR_V4,
88
111
  });
89
- } else if (isCryptoRandomUUIDCall(node, aliases.nodeCryptoRandomUUIDAlias)) {
112
+ } else if (
113
+ isCryptoRandomUUIDCall(node, aliases.nodeCryptoRandomUUIDAlias)
114
+ ) {
90
115
  context.report({
91
116
  node,
92
117
  messageId: NO_RANDOM_V4_UUID,
@@ -20,12 +20,15 @@ const NO_SIDE_EFFECTS = 'NO_SIDE_EFFECTS';
20
20
  // Type guards
21
21
 
22
22
  // Checks if a node is an ExpressionStatement
23
- const isExpressionStatement = (node: TSESTree.Node): node is TSESTree.ExpressionStatement =>
23
+ const isExpressionStatement = (
24
+ node: TSESTree.Node,
25
+ ): node is TSESTree.ExpressionStatement =>
24
26
  node.type === TSESTree.AST_NODE_TYPES.ExpressionStatement;
25
27
 
26
28
  // Checks if a statement is an AwaitExpression
27
29
  const isAwaitExpression = (statement: TSESTree.Node): boolean =>
28
- isExpressionStatement(statement) && statement.expression.type === TSESTree.AST_NODE_TYPES.AwaitExpression;
30
+ isExpressionStatement(statement) &&
31
+ statement.expression.type === TSESTree.AST_NODE_TYPES.AwaitExpression;
29
32
 
30
33
  // Checks if a node is a VariableDeclaration with an AwaitExpression
31
34
  const isVariableDeclarationAwaitExpression = (node: TSESTree.Node): boolean =>
@@ -35,7 +38,9 @@ const isVariableDeclarationAwaitExpression = (node: TSESTree.Node): boolean =>
35
38
 
36
39
  // Checks if a node is a VariableDeclaration that is not const or using
37
40
  const isNotValidVariableDeclaration = (node: TSESTree.Node): boolean =>
38
- node.type === TSESTree.AST_NODE_TYPES.VariableDeclaration && node.kind !== 'const' && node.kind !== 'using';
41
+ node.type === TSESTree.AST_NODE_TYPES.VariableDeclaration &&
42
+ node.kind !== 'const' &&
43
+ node.kind !== 'using';
39
44
 
40
45
  // Checks if a node is a control flow statement
41
46
  const isControlFlowStatement = (node: TSESTree.Node): boolean =>
@@ -56,36 +61,59 @@ const isAssignmentExpression = (node: TSESTree.Node): boolean =>
56
61
  // Helper functions
57
62
 
58
63
  // Checks if the callee is an identifier and not excluded
59
- const isIdentifierCallee = (node: TSESTree.CallExpression, excludedIdentifiers: string[]): boolean =>
60
- node.callee.type === TSESTree.AST_NODE_TYPES.Identifier && !excludedIdentifiers.includes(node.callee.name);
64
+ const isIdentifierCallee = (
65
+ node: TSESTree.CallExpression,
66
+ excludedIdentifiers: string[],
67
+ ): boolean =>
68
+ node.callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
69
+ !excludedIdentifiers.includes(node.callee.name);
61
70
 
62
71
  // Checks if the callee is a member expression and not excluded
63
- const isMemberExpressionCallee = (node: TSESTree.CallExpression, excludedIdentifiers: string[]): boolean =>
72
+ const isMemberExpressionCallee = (
73
+ node: TSESTree.CallExpression,
74
+ excludedIdentifiers: string[],
75
+ ): boolean =>
64
76
  node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
65
77
  node.callee.object.type === TSESTree.AST_NODE_TYPES.Identifier &&
66
78
  node.callee.property.type === TSESTree.AST_NODE_TYPES.Identifier &&
67
- !excludedIdentifiers.includes(`${node.callee.object.name}.${node.callee.property.name}`);
79
+ !excludedIdentifiers.includes(
80
+ `${node.callee.object.name}.${node.callee.property.name}`,
81
+ );
68
82
 
69
83
  // Checks if the callee is a member expression with a non-identifier object
70
- const isNonIdentifierObjectMemberExpressionCallee = (node: TSESTree.CallExpression): boolean =>
84
+ const isNonIdentifierObjectMemberExpressionCallee = (
85
+ node: TSESTree.CallExpression,
86
+ ): boolean =>
71
87
  node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
72
88
  node.callee.object.type !== TSESTree.AST_NODE_TYPES.Identifier;
73
89
 
74
90
  // Checks if a statement is a CallExpression with a member expression callee
75
- const isCallExpressionCalleeMemberExpression = (statement: TSESTree.Node, excludedIdentifiers: string[]): boolean =>
91
+ const isCallExpressionCalleeMemberExpression = (
92
+ statement: TSESTree.Node,
93
+ excludedIdentifiers: string[],
94
+ ): boolean =>
76
95
  isExpressionStatement(statement) &&
77
96
  statement.expression.type === TSESTree.AST_NODE_TYPES.CallExpression &&
78
- statement.expression.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
79
- statement.expression.callee.object.type === TSESTree.AST_NODE_TYPES.Identifier &&
80
- statement.expression.callee.property.type === TSESTree.AST_NODE_TYPES.Identifier &&
97
+ statement.expression.callee.type ===
98
+ TSESTree.AST_NODE_TYPES.MemberExpression &&
99
+ statement.expression.callee.object.type ===
100
+ TSESTree.AST_NODE_TYPES.Identifier &&
101
+ statement.expression.callee.property.type ===
102
+ TSESTree.AST_NODE_TYPES.Identifier &&
81
103
  !excludedIdentifiers.includes(statement.expression.callee.object.name) &&
82
104
  !excludedIdentifiers.includes(
83
105
  `${statement.expression.callee.object.name}.${statement.expression.callee.property.name}`,
84
106
  );
85
107
 
86
108
  // Checks if a node is a VariableDeclaration with a CallExpression
87
- const isVariableDeclarationCallExpression = (node: TSESTree.Node, excludedIdentifiers: string[]): boolean => {
88
- if (node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration || node.declarations.length === 0) {
109
+ const isVariableDeclarationCallExpression = (
110
+ node: TSESTree.Node,
111
+ excludedIdentifiers: string[],
112
+ ): boolean => {
113
+ if (
114
+ node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration ||
115
+ node.declarations.length === 0
116
+ ) {
89
117
  return false;
90
118
  }
91
119
 
@@ -110,28 +138,43 @@ const isVariableDeclarationCallExpression = (node: TSESTree.Node, excludedIdenti
110
138
  };
111
139
 
112
140
  // Checks if an ExportNamedDeclaration has side effects
113
- const isExportNamedDeclarationWithSideEffects = (statement: TSESTree.Node, excludedIdentifiers: string[]): boolean =>
141
+ const isExportNamedDeclarationWithSideEffects = (
142
+ statement: TSESTree.Node,
143
+ excludedIdentifiers: string[],
144
+ ): boolean =>
114
145
  statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration &&
115
146
  statement.declaration !== null &&
116
147
  (isVariableDeclarationAwaitExpression(statement.declaration) ||
117
- isVariableDeclarationCallExpression(statement.declaration, excludedIdentifiers));
148
+ isVariableDeclarationCallExpression(
149
+ statement.declaration,
150
+ excludedIdentifiers,
151
+ ));
118
152
 
119
153
  // Checks if an ExpressionStatement has side effects
120
- const isExpressionStatementWithSideEffects = (statement: TSESTree.Node, excludedIdentifiers: string[]): boolean =>
154
+ const isExpressionStatementWithSideEffects = (
155
+ statement: TSESTree.Node,
156
+ excludedIdentifiers: string[],
157
+ ): boolean =>
121
158
  statement.type === TSESTree.AST_NODE_TYPES.ExpressionStatement &&
122
159
  statement.expression.type === TSESTree.AST_NODE_TYPES.CallExpression &&
123
160
  ((statement.expression.callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
124
161
  !excludedIdentifiers.includes(statement.expression.callee.name)) ||
125
- (statement.expression.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
126
- statement.expression.callee.object.type === TSESTree.AST_NODE_TYPES.Identifier &&
127
- statement.expression.callee.property.type === TSESTree.AST_NODE_TYPES.Identifier &&
162
+ (statement.expression.callee.type ===
163
+ TSESTree.AST_NODE_TYPES.MemberExpression &&
164
+ statement.expression.callee.object.type ===
165
+ TSESTree.AST_NODE_TYPES.Identifier &&
166
+ statement.expression.callee.property.type ===
167
+ TSESTree.AST_NODE_TYPES.Identifier &&
128
168
  !excludedIdentifiers.includes(
129
169
  `${statement.expression.callee.object.name}.${statement.expression.callee.property.name}`,
130
170
  )));
131
171
 
132
172
  // Checks if a node is a VariableDeclaration with a NewExpression
133
173
  const isVariableDeclarationNewExpression = (node: TSESTree.Node): boolean => {
134
- if (node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration || node.declarations.length === 0) {
174
+ if (
175
+ node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration ||
176
+ node.declarations.length === 0
177
+ ) {
135
178
  return false;
136
179
  }
137
180
 
@@ -140,7 +183,10 @@ const isVariableDeclarationNewExpression = (node: TSESTree.Node): boolean => {
140
183
  };
141
184
 
142
185
  // Update the hasSideEffects function to return a string indicating the type of side effect
143
- const hasSideEffects = (statement: TSESTree.Node, excludedIdentifiers: string[]): string | null => {
186
+ const hasSideEffects = (
187
+ statement: TSESTree.Node,
188
+ excludedIdentifiers: string[],
189
+ ): string | null => {
144
190
  if (isAwaitExpression(statement)) {
145
191
  return TSESTree.AST_NODE_TYPES.AwaitExpression;
146
192
  }
@@ -174,21 +220,22 @@ const hasSideEffects = (statement: TSESTree.Node, excludedIdentifiers: string[])
174
220
  return null;
175
221
  };
176
222
 
177
- const createRule: ReturnType<typeof ESLintUtils.RuleCreator> = ESLintUtils.RuleCreator((name) =>
178
- getDocumentationUrl(name),
179
- );
223
+ const createRule: ReturnType<typeof ESLintUtils.RuleCreator> =
224
+ ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
180
225
 
181
226
  const rule: ReturnType<typeof createRule> = createRule({
182
227
  name: ruleId,
183
228
  meta: {
184
229
  type: 'problem',
185
230
  docs: {
186
- description: 'Ensure no side effects can occur at the module-level only if exporting module',
231
+ description:
232
+ 'Ensure no side effects can occur at the module-level only if exporting module',
187
233
  },
188
234
  schema: [
189
235
  {
190
236
  type: 'object',
191
237
  properties: {
238
+ // eslint-disable-next-line eslint-plugin/require-meta-schema-description
192
239
  excludedIdentifiers: {
193
240
  type: 'array',
194
241
  items: { type: 'string' },
@@ -197,20 +244,22 @@ const rule: ReturnType<typeof createRule> = createRule({
197
244
  additionalProperties: false,
198
245
  },
199
246
  ],
247
+ defaultOptions: [{ excludedIdentifiers: [''] }],
200
248
  messages: {
201
249
  [NO_SIDE_EFFECTS]: 'No side effects can occur at the module-level',
202
250
  },
203
251
  },
204
- defaultOptions: [{ excludedIdentifiers: [''] }],
205
252
  create(context) {
206
253
  const options: RuleOptions = context.options[0] as RuleOptions;
207
- const excludedIdentifiers = options.excludedIdentifiers.length > 0 ? options.excludedIdentifiers : [];
254
+ const excludedIdentifiers =
255
+ options.excludedIdentifiers.length > 0 ? options.excludedIdentifiers : [];
208
256
  return {
209
257
  Program(node: TSESTree.Program) {
210
258
  const hasExport = node.body.some(
211
259
  (statement: TSESTree.Node) =>
212
260
  statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration ||
213
- statement.type === TSESTree.AST_NODE_TYPES.ExportDefaultDeclaration ||
261
+ statement.type ===
262
+ TSESTree.AST_NODE_TYPES.ExportDefaultDeclaration ||
214
263
  statement.type === TSESTree.AST_NODE_TYPES.ExportAllDeclaration,
215
264
  );
216
265
 
@@ -7,8 +7,13 @@
7
7
  */
8
8
 
9
9
  import { StatusCodes } from 'http-status-codes';
10
- import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils';
11
- import getDocumentationUrl from './get-documentation-url';
10
+ import {
11
+ AST_NODE_TYPES,
12
+ ESLintUtils,
13
+ TSESLint,
14
+ TSESTree,
15
+ } from '@typescript-eslint/utils';
16
+ import getDocumentationUrl from './get-documentation-url.ts';
12
17
 
13
18
  export const ruleId = 'no-status-code-assert';
14
19
  const NO_STATUS_CODE_ASSERT = 'NO_STATUS_CODE_ASSERT';
@@ -31,7 +36,10 @@ const hasStatusCodeOrValue = (arg: TSESTree.Node): boolean => {
31
36
  break;
32
37
  }
33
38
  case AST_NODE_TYPES.Literal:
34
- if (typeof arg.value === 'number' && Object.values(StatusCodes).includes(arg.value)) {
39
+ if (
40
+ typeof arg.value === 'number' &&
41
+ Object.values(StatusCodes).includes(arg.value)
42
+ ) {
35
43
  return true;
36
44
  }
37
45
  break;
@@ -52,19 +60,25 @@ const isAssertMemberExpression = (node: TSESTree.Node): boolean =>
52
60
  node.object.name === 'assert' &&
53
61
  node.property.type === AST_NODE_TYPES.Identifier;
54
62
 
55
- const isAssertCallWithStatusCode = (callee: TSESTree.Node, args: TSESTree.Node[]): boolean =>
56
- (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) && args.some((arg) => hasStatusCodeOrValue(arg));
63
+ const isAssertCallWithStatusCode = (
64
+ callee: TSESTree.Node,
65
+ args: TSESTree.Node[],
66
+ ): boolean =>
67
+ (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) &&
68
+ args.some((arg) => hasStatusCodeOrValue(arg));
57
69
 
58
70
  const rule: TSESLint.RuleModule<typeof NO_STATUS_CODE_ASSERT> = createRule({
59
71
  name: ruleId,
60
72
  meta: {
61
73
  type: 'problem',
62
74
  docs: {
63
- description: 'Disallow using status codes in assertions; use error handling instead',
75
+ description:
76
+ 'Disallow using status codes in assertions; use error handling instead',
64
77
  },
65
78
  schema: [],
66
79
  messages: {
67
- [NO_STATUS_CODE_ASSERT]: 'Do not use status codes in assertions; use error handling instead',
80
+ [NO_STATUS_CODE_ASSERT]:
81
+ 'Do not use status codes in assertions; use error handling instead',
68
82
  },
69
83
  },
70
84
  defaultOptions: [],
@@ -43,12 +43,18 @@ export default {
43
43
  },
44
44
  },
45
45
  create(context) {
46
- const options = { ...DEFAULT_OPTIONS, ...(context.options[0] as NoTestImportRuleOptions) };
46
+ const options = {
47
+ ...DEFAULT_OPTIONS,
48
+ ...(context.options[0] as NoTestImportRuleOptions),
49
+ };
47
50
  const testFileRegexp = new RegExp(options.testFilePattern, 'u');
48
51
 
49
52
  return {
50
53
  ImportDeclaration(node) {
51
- if (typeof node.source.value === 'string' && testFileRegexp.test(node.source.value)) {
54
+ if (
55
+ typeof node.source.value === 'string' &&
56
+ testFileRegexp.test(node.source.value)
57
+ ) {
52
58
  context.report({
53
59
  node,
54
60
  messageId: NO_TEST_IMPORT,
package/src/no-util.ts CHANGED
@@ -35,7 +35,9 @@ const rule: ESLintUtils.RuleModule<typeof NO_UTIL> = createRule({
35
35
  const sourceCode = context.sourceCode;
36
36
  const tokens = sourceCode.tokensAndComments;
37
37
  const firstNonCommentToken = tokens.find(
38
- (token) => token.type !== AST_TOKEN_TYPES.Block && token.type !== AST_TOKEN_TYPES.Line,
38
+ (token) =>
39
+ token.type !== AST_TOKEN_TYPES.Block &&
40
+ token.type !== AST_TOKEN_TYPES.Line,
39
41
  );
40
42
  if (firstNonCommentToken !== undefined) {
41
43
  context.report({
package/src/no-uuid.ts CHANGED
@@ -11,9 +11,15 @@ import type { Rule } from 'eslint';
11
11
 
12
12
  const UUID_FOUND = 'UUID_FOUND';
13
13
  const UUIDS_FOUND = 'UUIDS_FOUND';
14
- const uuidRegex = /[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/gmu;
14
+ const uuidRegex =
15
+ /[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/gmu;
15
16
 
16
- function checkForUuid(value: string, context: Rule.RuleContext, node?: Node, loc?: SourceLocation) {
17
+ function checkForUuid(
18
+ value: string,
19
+ context: Rule.RuleContext,
20
+ node?: Node,
21
+ loc?: SourceLocation,
22
+ ) {
17
23
  const matches = value.match(uuidRegex);
18
24
  if (matches === null) {
19
25
  return;
@@ -9,9 +9,17 @@
9
9
  import type { Rule, SourceCode } from 'eslint';
10
10
  import type { Comment } from 'estree';
11
11
 
12
+ // eslint-disable-next-line sonarjs/slow-regex
12
13
  const wallabyRegex = /(?<=(?:^|\*\/)\s*)[?]{1,2}|file\.only|file\.skip/gu;
13
- const commentRegex = /\s*(?:\/\/|<!--)\s*(?<comment>\?{1,2}\.?\s*|file\.(?:only|skip))\s*/gu;
14
- function removeWallabyComment(context: Rule.RuleContext, sourceCode: SourceCode, start: number, end: number): void {
14
+ const commentRegex =
15
+ // eslint-disable-next-line sonarjs/slow-regex
16
+ /\s*(?:\/\/|<!--)\s*(?:\?{1,2}\.?\s*|file\.(?:only|skip))\s*/gu;
17
+ function removeWallabyComment(
18
+ context: Rule.RuleContext,
19
+ sourceCode: SourceCode,
20
+ start: number,
21
+ end: number,
22
+ ): void {
15
23
  context.report({
16
24
  loc: {
17
25
  start: sourceCode.getLocFromIndex(start),
@@ -22,21 +30,35 @@ function removeWallabyComment(context: Rule.RuleContext, sourceCode: SourceCode,
22
30
  });
23
31
  }
24
32
 
25
- function processLineComment(context: Rule.RuleContext, sourceCode: SourceCode, comment: Comment): void {
33
+ function processLineComment(
34
+ context: Rule.RuleContext,
35
+ sourceCode: SourceCode,
36
+ comment: Comment,
37
+ ): void {
26
38
  if (comment.loc) {
27
39
  const line = sourceCode.getLines()[comment.loc.start.line - 1];
28
40
  if (line !== undefined) {
29
41
  let match;
30
42
  while ((match = commentRegex.exec(line)) !== null) {
31
- const start = sourceCode.getIndexFromLoc({ line: comment.loc.start.line, column: match.index });
32
- const end = sourceCode.getIndexFromLoc({ line: comment.loc.start.line, column: comment.loc.end.column });
43
+ const start = sourceCode.getIndexFromLoc({
44
+ line: comment.loc.start.line,
45
+ column: match.index,
46
+ });
47
+ const end = sourceCode.getIndexFromLoc({
48
+ line: comment.loc.start.line,
49
+ column: comment.loc.end.column,
50
+ });
33
51
  removeWallabyComment(context, sourceCode, start, end);
34
52
  }
35
53
  }
36
54
  }
37
55
  }
38
56
 
39
- function processBlockComment(context: Rule.RuleContext, sourceCode: SourceCode, comment: Comment): void {
57
+ function processBlockComment(
58
+ context: Rule.RuleContext,
59
+ sourceCode: SourceCode,
60
+ comment: Comment,
61
+ ): void {
40
62
  const commentValues = comment.value.split('\n');
41
63
  const blockCommentRegex = /^(?:\s*\*\s*)?(?:file\.only|file\.skip)$/gu;
42
64
  commentValues.forEach((commentValue) => {
@@ -49,8 +71,14 @@ function processBlockComment(context: Rule.RuleContext, sourceCode: SourceCode,
49
71
  while (comment.loc && (match = wallabyRegex.exec(commentValue)) !== null) {
50
72
  const removeEntireComment = blockCommentRegex.test(comment.value.trim());
51
73
  if (removeEntireComment) {
52
- start = sourceCode.getIndexFromLoc({ line: comment.loc.start.line, column: comment.loc.start.column });
53
- end = sourceCode.getIndexFromLoc({ line: comment.loc.end.line, column: comment.loc.end.column });
74
+ start = sourceCode.getIndexFromLoc({
75
+ line: comment.loc.start.line,
76
+ column: comment.loc.start.column,
77
+ });
78
+ end = sourceCode.getIndexFromLoc({
79
+ line: comment.loc.end.line,
80
+ column: comment.loc.end.column,
81
+ });
54
82
  } else {
55
83
  let lineNumber = 0;
56
84
  while (startLine <= endLine) {
@@ -61,7 +89,10 @@ function processBlockComment(context: Rule.RuleContext, sourceCode: SourceCode,
61
89
  }
62
90
  startLine++;
63
91
  }
64
- start = sourceCode.getIndexFromLoc({ line: lineNumber + 1, column: comment.loc.start.column });
92
+ start = sourceCode.getIndexFromLoc({
93
+ line: lineNumber + 1,
94
+ column: comment.loc.start.column,
95
+ });
65
96
  end = sourceCode.getIndexFromLoc({ line: lineNumber + 2, column: 0 });
66
97
  }
67
98
  removeWallabyComment(context, sourceCode, start, end);
@@ -9,10 +9,12 @@
9
9
  import type { CallExpression, Property } from 'estree';
10
10
  import type { Rule } from 'eslint';
11
11
 
12
- export const REQUIRE_OBJECT_LITERAL_MESSAGE_ID = 'REQUIRE_OBJECT_LITERAL_MESSAGE_ID';
12
+ export const REQUIRE_OBJECT_LITERAL_MESSAGE_ID =
13
+ 'REQUIRE_OBJECT_LITERAL_MESSAGE_ID';
13
14
  export const REQUIRE_OBJECT_LITERAL_FOR_ERROR_RESPONSE_MESSAGE_ID =
14
15
  'REQUIRE_OBJECT_LITERAL_FOR_ERROR_RESPONSE_MESSAGE_ID';
15
- export const REQUIRE_OBJECT_LITERAL_FOR_HEADERS_MESSAGE_ID = 'REQUIRE_OBJECT_LITERAL_FOR_HEADERS_MESSAGE_ID';
16
+ export const REQUIRE_OBJECT_LITERAL_FOR_HEADERS_MESSAGE_ID =
17
+ 'REQUIRE_OBJECT_LITERAL_FOR_HEADERS_MESSAGE_ID';
16
18
 
17
19
  // eslint-disable-next-line no-magic-numbers
18
20
  const GOOD_STATUS_VALUES = [200, 201, 202, 203, 204, 205, 206, 207];
@@ -47,7 +49,10 @@ export default {
47
49
  return {
48
50
  // eslint-disable-next-line sonarjs/cognitive-complexity
49
51
  CallExpression(node: CallExpression) {
50
- if (node.callee.type === 'Identifier' && node.callee.name === 'setResponse') {
52
+ if (
53
+ node.callee.type === 'Identifier' &&
54
+ node.callee.name === 'setResponse'
55
+ ) {
51
56
  const responseContext = node.arguments[1];
52
57
 
53
58
  // check top level object literal
@@ -62,9 +67,14 @@ export default {
62
67
  if (responseContext?.type === 'ObjectExpression') {
63
68
  const headers = responseContext.properties.find(
64
69
  (property) =>
65
- property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'headers',
70
+ property.type === 'Property' &&
71
+ property.key.type === 'Identifier' &&
72
+ property.key.name === 'headers',
66
73
  ) as Property | undefined;
67
- if (headers !== undefined && headers.value.type !== 'ObjectExpression') {
74
+ if (
75
+ headers !== undefined &&
76
+ headers.value.type !== 'ObjectExpression'
77
+ ) {
68
78
  context.report({
69
79
  node: headers,
70
80
  messageId: REQUIRE_OBJECT_LITERAL_FOR_HEADERS_MESSAGE_ID,
@@ -76,7 +86,9 @@ export default {
76
86
  if (responseContext?.type === 'ObjectExpression') {
77
87
  const status = responseContext.properties.find(
78
88
  (property) =>
79
- property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'status',
89
+ property.type === 'Property' &&
90
+ property.key.type === 'Identifier' &&
91
+ property.key.name === 'status',
80
92
  ) as Property;
81
93
  let isSuccessfulResponse;
82
94
  if (status.value.type === 'MemberExpression') {
@@ -87,13 +99,16 @@ export default {
87
99
  GOOD_STATUS_ENUM_NAMES.includes(status.value.property.name);
88
100
  } else if (status.value.type === 'Literal') {
89
101
  isSuccessfulResponse =
90
- typeof status.value.value === 'number' && GOOD_STATUS_VALUES.includes(status.value.value);
102
+ typeof status.value.value === 'number' &&
103
+ GOOD_STATUS_VALUES.includes(status.value.value);
91
104
  }
92
105
  if (isSuccessfulResponse === false) {
93
106
  // handle error response
94
107
  const body = responseContext.properties.find(
95
108
  (property) =>
96
- property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'body',
109
+ property.type === 'Property' &&
110
+ property.key.type === 'Identifier' &&
111
+ property.key.name === 'body',
97
112
  ) as Property | undefined;
98
113
  if (body === undefined) {
99
114
  return; // no body to lint for
@@ -102,7 +117,8 @@ export default {
102
117
  if (body.value.type !== 'ObjectExpression') {
103
118
  context.report({
104
119
  node: body,
105
- messageId: REQUIRE_OBJECT_LITERAL_FOR_ERROR_RESPONSE_MESSAGE_ID,
120
+ messageId:
121
+ REQUIRE_OBJECT_LITERAL_FOR_ERROR_RESPONSE_MESSAGE_ID,
106
122
  });
107
123
  }
108
124
  }
@@ -12,7 +12,8 @@ export default {
12
12
  meta: {
13
13
  type: 'problem',
14
14
  docs: {
15
- description: 'Require comments for regular expressions before or on the same line',
15
+ description:
16
+ 'Require comments for regular expressions before or on the same line',
16
17
  url: 'https://github.com/checkdigit/eslint-plugin',
17
18
  },
18
19
  },
@@ -27,7 +28,9 @@ export default {
27
28
  const previousLineComment = lines[previousLine - 1];
28
29
 
29
30
  // Check if the regular expression contains any simple text
30
- const isSimpleTextPattern = /^[0-9:./,\sa-zA-Z-]*$/gu.test(node.value.source);
31
+ const isSimpleTextPattern = /^[0-9:./,\sa-zA-Z-]*$/gu.test(
32
+ node.value.source,
33
+ );
31
34
  if (isSimpleTextPattern) {
32
35
  return;
33
36
  }
@@ -40,7 +43,10 @@ export default {
40
43
  // This regex is to check if the line starts with or without spaces and followed by two or more consecutive slashes // or start with /* and may have one or more asterisks, continuing until the first occurrence of */.
41
44
  const commentRegularExpressionLine = /^\s*(?:\/{2,}|\/\*+)/gu;
42
45
  const hasComment = regularExpression.test(comment.value.trim());
43
- if (comment.type === 'Line' || comment.loc.start.line === comment.loc.end.line) {
46
+ if (
47
+ comment.type === 'Line' ||
48
+ comment.loc.start.line === comment.loc.end.line
49
+ ) {
44
50
  return (
45
51
  (comment.loc.end.line === previousLine &&
46
52
  previousLineComment !== undefined &&