@checkdigit/eslint-plugin 7.7.1-PR.101-95b3 → 7.8.0-PR.97-d090

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.
@@ -3,6 +3,7 @@ import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from "./in
3
3
  import noDuplicatedImports, { ruleId as noDuplicatedImportsRuleId } from "./no-duplicated-imports.mjs";
4
4
  import noLegacyServiceTyping, { ruleId as noLegacyServiceTypingRuleId } from "./no-legacy-service-typing.mjs";
5
5
  import noPromiseInstanceMethod, { ruleId as noPromiseInstanceMethodRuleId } from "./no-promise-instance-method.mjs";
6
+ import noStatusCodeAssert from "./no-status-code-assert.mjs";
6
7
  import requireFixedServicesImport, {
7
8
  ruleId as requireFixedServicesImportRuleId
8
9
  } from "./require-fixed-services-import.mjs";
@@ -29,6 +30,7 @@ var rules = {
29
30
  "file-path-comment": filePathComment,
30
31
  "no-card-numbers": noCardNumbers,
31
32
  "no-random-v4-uuid": noRandomV4UUID,
33
+ "no-status-code-assert": noStatusCodeAssert,
32
34
  "no-uuid": noUuid,
33
35
  "require-strict-assert": requireStrictAssert,
34
36
  "require-ts-extension-imports": requireTsExtensionImports,
@@ -61,14 +63,12 @@ var configs = {
61
63
  "@checkdigit/no-card-numbers": "error",
62
64
  "@checkdigit/file-path-comment": "error",
63
65
  "@checkdigit/no-random-v4-uuid": "error",
66
+ "@checkdigit/no-status-code-assert": "error",
64
67
  "@checkdigit/no-uuid": "error",
65
68
  "@checkdigit/require-strict-assert": "error",
66
69
  "@checkdigit/require-ts-extension-imports": "error",
67
70
  "@checkdigit/no-wallaby-comment": "error",
68
- "@checkdigit/no-side-effects": [
69
- "error",
70
- { excludedIdentifiers: ["assert", "debug", "log", "promisify", "Symbol.for"] }
71
- ],
71
+ "@checkdigit/no-side-effects": ["error", { excludedIdentifiers: ["assert", "debug", "log", "promisify"] }],
72
72
  "@checkdigit/regular-expression-comment": "error",
73
73
  "@checkdigit/require-assert-predicate-rejects-throws": "error",
74
74
  "@checkdigit/object-literal-response": "error",
@@ -94,6 +94,7 @@ var configs = {
94
94
  "@checkdigit/no-card-numbers": "error",
95
95
  "@checkdigit/file-path-comment": "off",
96
96
  "@checkdigit/no-random-v4-uuid": "error",
97
+ "@checkdigit/no-status-code-assert": "error",
97
98
  "@checkdigit/no-uuid": "error",
98
99
  "@checkdigit/require-strict-assert": "error",
99
100
  "@checkdigit/require-ts-extension-imports": "error",
@@ -123,4 +124,4 @@ var src_default = defaultToExport;
123
124
  export {
124
125
  src_default as default
125
126
  };
126
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVVBLE9BQU8sd0JBQXdCLFVBQVUsa0NBQWtDO0FBQzNFLE9BQU8sdUJBQXVCLFVBQVUsaUNBQWlDO0FBQ3pFLE9BQU8seUJBQXlCLFVBQVUsbUNBQW1DO0FBQzdFLE9BQU8sMkJBQTJCLFVBQVUscUNBQXFDO0FBQ2pGLE9BQU87QUFBQSxFQUNMLFVBQVU7QUFBQSxPQUNMO0FBQ1AsT0FBTztBQUFBLEVBQ0wsVUFBVTtBQUFBLE9BQ0w7QUFDUCxPQUFPO0FBQUEsRUFDTCxVQUFVO0FBQUEsT0FDTDtBQUNQLE9BQU8sa0JBQWtCLFVBQVUsNEJBQTRCO0FBQy9ELE9BQU8scUJBQXFCO0FBQzVCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sb0JBQW9CO0FBQzNCLE9BQU8sa0JBQWtCO0FBQ3pCLE9BQU8sWUFBWTtBQUNuQixPQUFPLHNCQUFzQjtBQUM3QixPQUFPLDJCQUEyQjtBQUNsQyxPQUFPLGtCQUFrQjtBQUN6QixPQUFPLHlDQUF5QztBQUNoRCxPQUFPLHlCQUF5QjtBQUNoQyxPQUFPLCtCQUErQjtBQUV0QyxJQUFNLFFBQXNEO0FBQUEsRUFDMUQscUJBQXFCO0FBQUEsRUFDckIsbUJBQW1CO0FBQUEsRUFDbkIscUJBQXFCO0FBQUEsRUFDckIsV0FBVztBQUFBLEVBQ1gseUJBQXlCO0FBQUEsRUFDekIsZ0NBQWdDO0FBQUEsRUFDaEMsa0JBQWtCO0FBQUEsRUFDbEIsc0JBQXNCO0FBQUEsRUFDdEIsbUJBQW1CO0FBQUEsRUFDbkIsOEJBQThCO0FBQUEsRUFDOUIsMkNBQTJDO0FBQUEsRUFDM0MsMkJBQTJCO0FBQUEsRUFDM0IsQ0FBQywwQkFBMEIsR0FBRztBQUFBLEVBQzlCLENBQUMsNkJBQTZCLEdBQUc7QUFBQSxFQUNqQyxDQUFDLDJCQUEyQixHQUFHO0FBQUEsRUFDL0IsQ0FBQyxnQ0FBZ0MsR0FBRztBQUFBLEVBQ3BDLENBQUMseUJBQXlCLEdBQUc7QUFBQSxFQUM3QixDQUFDLG9CQUFvQixHQUFHO0FBQUEsRUFDeEIsQ0FBQyxnQ0FBZ0MsR0FBRztBQUFBLEVBQ3BDLENBQUMscUNBQXFDLEdBQUc7QUFDM0M7QUFFQSxJQUFNLFNBQXFDO0FBQUEsRUFDekM7QUFDRjtBQUVBLElBQU0sVUFBd0Q7QUFBQSxFQUM1RCxLQUFLO0FBQUEsSUFDSDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHVCQUF1QjtBQUFBLFFBQ3ZCLHFDQUFxQztBQUFBLFFBQ3JDLDRDQUE0QztBQUFBLFFBQzVDLGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQjtBQUFBLFVBQzdCO0FBQUEsVUFDQSxFQUFFLHFCQUFxQixDQUFDLFVBQVUsU0FBUyxPQUFPLGFBQWEsWUFBWSxFQUFFO0FBQUEsUUFDL0U7QUFBQSxRQUNBLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxNQUMzQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxhQUFhO0FBQUEsSUFDWDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHVCQUF1QjtBQUFBLFFBQ3ZCLHFDQUFxQztBQUFBLFFBQ3JDLDRDQUE0QztBQUFBLFFBQzVDLGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQjtBQUFBLFFBQy9CLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxNQUMzQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0Y7QUFFQSxJQUFNLGtCQUVGO0FBQUEsRUFDRixHQUFHO0FBQUEsRUFDSDtBQUNGO0FBQ0EsSUFBTyxjQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
127
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVVBLE9BQU8sd0JBQXdCLFVBQVUsa0NBQWtDO0FBQzNFLE9BQU8sdUJBQXVCLFVBQVUsaUNBQWlDO0FBQ3pFLE9BQU8seUJBQXlCLFVBQVUsbUNBQW1DO0FBQzdFLE9BQU8sMkJBQTJCLFVBQVUscUNBQXFDO0FBQ2pGLE9BQU8sd0JBQXdCO0FBQy9CLE9BQU87QUFBQSxFQUNMLFVBQVU7QUFBQSxPQUNMO0FBQ1AsT0FBTztBQUFBLEVBQ0wsVUFBVTtBQUFBLE9BQ0w7QUFDUCxPQUFPO0FBQUEsRUFDTCxVQUFVO0FBQUEsT0FDTDtBQUNQLE9BQU8sa0JBQWtCLFVBQVUsNEJBQTRCO0FBQy9ELE9BQU8scUJBQXFCO0FBQzVCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sb0JBQW9CO0FBQzNCLE9BQU8sa0JBQWtCO0FBQ3pCLE9BQU8sWUFBWTtBQUNuQixPQUFPLHNCQUFzQjtBQUM3QixPQUFPLDJCQUEyQjtBQUNsQyxPQUFPLGtCQUFrQjtBQUN6QixPQUFPLHlDQUF5QztBQUNoRCxPQUFPLHlCQUF5QjtBQUNoQyxPQUFPLCtCQUErQjtBQUV0QyxJQUFNLFFBQXNEO0FBQUEsRUFDMUQscUJBQXFCO0FBQUEsRUFDckIsbUJBQW1CO0FBQUEsRUFDbkIscUJBQXFCO0FBQUEsRUFDckIseUJBQXlCO0FBQUEsRUFDekIsV0FBVztBQUFBLEVBQ1gseUJBQXlCO0FBQUEsRUFDekIsZ0NBQWdDO0FBQUEsRUFDaEMsa0JBQWtCO0FBQUEsRUFDbEIsc0JBQXNCO0FBQUEsRUFDdEIsbUJBQW1CO0FBQUEsRUFDbkIsOEJBQThCO0FBQUEsRUFDOUIsMkNBQTJDO0FBQUEsRUFDM0MsMkJBQTJCO0FBQUEsRUFDM0IsQ0FBQywwQkFBMEIsR0FBRztBQUFBLEVBQzlCLENBQUMsNkJBQTZCLEdBQUc7QUFBQSxFQUNqQyxDQUFDLDJCQUEyQixHQUFHO0FBQUEsRUFDL0IsQ0FBQyxnQ0FBZ0MsR0FBRztBQUFBLEVBQ3BDLENBQUMseUJBQXlCLEdBQUc7QUFBQSxFQUM3QixDQUFDLG9CQUFvQixHQUFHO0FBQUEsRUFDeEIsQ0FBQyxnQ0FBZ0MsR0FBRztBQUFBLEVBQ3BDLENBQUMscUNBQXFDLEdBQUc7QUFDM0M7QUFFQSxJQUFNLFNBQXFDO0FBQUEsRUFDekM7QUFDRjtBQUVBLElBQU0sVUFBd0Q7QUFBQSxFQUM1RCxLQUFLO0FBQUEsSUFDSDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHFDQUFxQztBQUFBLFFBQ3JDLHVCQUF1QjtBQUFBLFFBQ3ZCLHFDQUFxQztBQUFBLFFBQ3JDLDRDQUE0QztBQUFBLFFBQzVDLGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQixDQUFDLFNBQVMsRUFBRSxxQkFBcUIsQ0FBQyxVQUFVLFNBQVMsT0FBTyxXQUFXLEVBQUUsQ0FBQztBQUFBLFFBQ3pHLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxNQUMzQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxhQUFhO0FBQUEsSUFDWDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHFDQUFxQztBQUFBLFFBQ3JDLHVCQUF1QjtBQUFBLFFBQ3ZCLHFDQUFxQztBQUFBLFFBQ3JDLDRDQUE0QztBQUFBLFFBQzVDLGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQjtBQUFBLFFBQy9CLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxNQUMzQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0Y7QUFFQSxJQUFNLGtCQUVGO0FBQUEsRUFDRixHQUFHO0FBQUEsRUFDSDtBQUNGO0FBQ0EsSUFBTyxjQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -15,27 +15,8 @@ function isCallExpressionCalleeMemberExpression(statement, excludedIdentifiers)
15
15
  function isVariableDeclarationAwaitExpression(node) {
16
16
  return node.type === TSESTree.AST_NODE_TYPES.VariableDeclaration && node.declarations.length > 0 && node.declarations[0]?.init?.type === TSESTree.AST_NODE_TYPES.AwaitExpression;
17
17
  }
18
- function isIdentifierCallee(node, excludedIdentifiers) {
19
- return node.callee.type === TSESTree.AST_NODE_TYPES.Identifier && !excludedIdentifiers.includes(node.callee.name);
20
- }
21
- function isMemberExpressionCallee(node, excludedIdentifiers) {
22
- return node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression && node.callee.object.type === TSESTree.AST_NODE_TYPES.Identifier && node.callee.property.type === TSESTree.AST_NODE_TYPES.Identifier && !excludedIdentifiers.includes(`${node.callee.object.name}.${node.callee.property.name}`);
23
- }
24
- function isNonIdentifierObjectMemberExpressionCallee(node) {
25
- return node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression && node.callee.object.type !== TSESTree.AST_NODE_TYPES.Identifier;
26
- }
27
18
  function isVariableDeclarationCallExpression(node, excludedIdentifiers) {
28
- if (node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration || node.declarations.length === 0) {
29
- return false;
30
- }
31
- const init = node.declarations[0]?.init;
32
- if (init?.type !== TSESTree.AST_NODE_TYPES.CallExpression) {
33
- return false;
34
- }
35
- return isIdentifierCallee(init, excludedIdentifiers) || isMemberExpressionCallee(init, excludedIdentifiers) || isNonIdentifierObjectMemberExpressionCallee(init);
36
- }
37
- function hasSideEffects(statement, excludedIdentifiers) {
38
- return isAwaitExpression(statement) || isCallExpressionCalleeMemberExpression(statement, excludedIdentifiers) || isVariableDeclarationAwaitExpression(statement) || isVariableDeclarationCallExpression(statement, excludedIdentifiers) || statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration !== null && (isVariableDeclarationAwaitExpression(statement.declaration) || isVariableDeclarationCallExpression(statement.declaration, excludedIdentifiers));
19
+ return node.type === TSESTree.AST_NODE_TYPES.VariableDeclaration && node.declarations.length > 0 && node.declarations[0]?.init?.type === TSESTree.AST_NODE_TYPES.CallExpression && (node.declarations[0].init.callee.type === TSESTree.AST_NODE_TYPES.Identifier && !excludedIdentifiers.includes(node.declarations[0].init.callee.name) || node.declarations[0].init.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression);
39
20
  }
40
21
  var createRule = ESLintUtils.RuleCreator((name) => name);
41
22
  var rule = createRule({
@@ -67,14 +48,8 @@ var rule = createRule({
67
48
  const excludedIdentifiers = options.excludedIdentifiers.length > 0 ? options.excludedIdentifiers : [];
68
49
  return {
69
50
  Program(node) {
70
- const hasExport = node.body.some(
71
- (statement) => statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === TSESTree.AST_NODE_TYPES.ExportDefaultDeclaration || statement.type === TSESTree.AST_NODE_TYPES.ExportAllDeclaration
72
- );
73
- if (!hasExport) {
74
- return;
75
- }
76
51
  node.body.forEach((statement) => {
77
- if (hasSideEffects(statement, excludedIdentifiers)) {
52
+ if (isAwaitExpression(statement) || isCallExpressionCalleeMemberExpression(statement, excludedIdentifiers) || isVariableDeclarationAwaitExpression(statement) || isVariableDeclarationCallExpression(statement, excludedIdentifiers)) {
78
53
  context.report({
79
54
  node: statement,
80
55
  messageId: NO_SIDE_EFFECTS
@@ -90,4 +65,4 @@ export {
90
65
  no_side_effects_default as default,
91
66
  ruleId
92
67
  };
93
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLXNpZGUtZWZmZWN0cy50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLG1CQUFtQjtBQUM1QixTQUFTLGdCQUFnQjtBQU1sQixJQUFNLFNBQVM7QUFDdEIsSUFBTSxrQkFBa0I7QUFHeEIsU0FBUyxzQkFBc0IsTUFBMkQ7QUFDeEYsU0FBTyxLQUFLLFNBQVMsU0FBUyxlQUFlO0FBQy9DO0FBR0EsU0FBUyxrQkFBa0IsV0FBbUM7QUFDNUQsU0FBTyxzQkFBc0IsU0FBUyxLQUFLLFVBQVUsV0FBVyxTQUFTLFNBQVMsZUFBZTtBQUNuRztBQUdBLFNBQVMsdUNBQXVDLFdBQTBCLHFCQUF3QztBQUNoSCxTQUNFLHNCQUFzQixTQUFTLEtBQy9CLFVBQVUsV0FBVyxTQUFTLFNBQVMsZUFBZSxrQkFDdEQsVUFBVSxXQUFXLE9BQU8sU0FBUyxTQUFTLGVBQWUsb0JBQzdELFVBQVUsV0FBVyxPQUFPLE9BQU8sU0FBUyxTQUFTLGVBQWUsY0FDcEUsQ0FBQyxvQkFBb0IsU0FBUyxVQUFVLFdBQVcsT0FBTyxPQUFPLElBQUk7QUFFekU7QUFHQSxTQUFTLHFDQUFxQyxNQUE4QjtBQUMxRSxTQUNFLEtBQUssU0FBUyxTQUFTLGVBQWUsdUJBQ3RDLEtBQUssYUFBYSxTQUFTLEtBQzNCLEtBQUssYUFBYSxDQUFDLEdBQUcsTUFBTSxTQUFTLFNBQVMsZUFBZTtBQUVqRTtBQUdBLFNBQVMsbUJBQW1CLE1BQStCLHFCQUF3QztBQUNqRyxTQUFPLEtBQUssT0FBTyxTQUFTLFNBQVMsZUFBZSxjQUFjLENBQUMsb0JBQW9CLFNBQVMsS0FBSyxPQUFPLElBQUk7QUFDbEg7QUFHQSxTQUFTLHlCQUF5QixNQUErQixxQkFBd0M7QUFDdkcsU0FDRSxLQUFLLE9BQU8sU0FBUyxTQUFTLGVBQWUsb0JBQzdDLEtBQUssT0FBTyxPQUFPLFNBQVMsU0FBUyxlQUFlLGNBQ3BELEtBQUssT0FBTyxTQUFTLFNBQVMsU0FBUyxlQUFlLGNBQ3RELENBQUMsb0JBQW9C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
68
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLXNpZGUtZWZmZWN0cy50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLG1CQUFtQjtBQUM1QixTQUFTLGdCQUFnQjtBQU1sQixJQUFNLFNBQVM7QUFDdEIsSUFBTSxrQkFBa0I7QUFHeEIsU0FBUyxzQkFBc0IsTUFBMkQ7QUFDeEYsU0FBTyxLQUFLLFNBQVMsU0FBUyxlQUFlO0FBQy9DO0FBR0EsU0FBUyxrQkFBa0IsV0FBbUM7QUFDNUQsU0FBTyxzQkFBc0IsU0FBUyxLQUFLLFVBQVUsV0FBVyxTQUFTLFNBQVMsZUFBZTtBQUNuRztBQUdBLFNBQVMsdUNBQXVDLFdBQTBCLHFCQUF3QztBQUNoSCxTQUNFLHNCQUFzQixTQUFTLEtBQy9CLFVBQVUsV0FBVyxTQUFTLFNBQVMsZUFBZSxrQkFDdEQsVUFBVSxXQUFXLE9BQU8sU0FBUyxTQUFTLGVBQWUsb0JBQzdELFVBQVUsV0FBVyxPQUFPLE9BQU8sU0FBUyxTQUFTLGVBQWUsY0FDcEUsQ0FBQyxvQkFBb0IsU0FBUyxVQUFVLFdBQVcsT0FBTyxPQUFPLElBQUk7QUFFekU7QUFHQSxTQUFTLHFDQUFxQyxNQUE4QjtBQUMxRSxTQUNFLEtBQUssU0FBUyxTQUFTLGVBQWUsdUJBQ3RDLEtBQUssYUFBYSxTQUFTLEtBQzNCLEtBQUssYUFBYSxDQUFDLEdBQUcsTUFBTSxTQUFTLFNBQVMsZUFBZTtBQUVqRTtBQUdBLFNBQVMsb0NBQW9DLE1BQXFCLHFCQUF3QztBQUN4RyxTQUNFLEtBQUssU0FBUyxTQUFTLGVBQWUsdUJBQ3RDLEtBQUssYUFBYSxTQUFTLEtBQzNCLEtBQUssYUFBYSxDQUFDLEdBQUcsTUFBTSxTQUFTLFNBQVMsZUFBZSxtQkFDM0QsS0FBSyxhQUFhLENBQUMsRUFBRSxLQUFLLE9BQU8sU0FBUyxTQUFTLGVBQWUsY0FDbEUsQ0FBQyxvQkFBb0IsU0FBUyxLQUFLLGFBQWEsQ0FBQyxFQUFFLEtBQUssT0FBTyxJQUFJLEtBQ25FLEtBQUssYUFBYSxDQUFDLEVBQUUsS0FBSyxPQUFPLFNBQVMsU0FBUyxlQUFlO0FBRXhFO0FBRUEsSUFBTSxhQUF5RCxZQUFZLFlBQVksQ0FBQyxTQUFTLElBQUk7QUFFckcsSUFBTSxPQUFzQyxXQUFXO0FBQUEsRUFDckQsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOO0FBQUEsUUFDRSxNQUFNO0FBQUEsUUFDTixZQUFZO0FBQUEsVUFDVixxQkFBcUI7QUFBQSxZQUNuQixNQUFNO0FBQUEsWUFDTixPQUFPLEVBQUUsTUFBTSxTQUFTO0FBQUEsVUFDMUI7QUFBQSxRQUNGO0FBQUEsUUFDQSxzQkFBc0I7QUFBQSxNQUN4QjtBQUFBLElBQ0Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLENBQUMsZUFBZSxHQUFHO0FBQUEsSUFDckI7QUFBQSxFQUNGO0FBQUEsRUFDQSxnQkFBZ0IsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQUEsRUFDOUMsT0FBTyxTQUFTO0FBQ2QsVUFBTSxVQUF1QixRQUFRLFFBQVEsQ0FBQztBQUM5QyxVQUFNLHNCQUFzQixRQUFRLG9CQUFvQixTQUFTLElBQUksUUFBUSxzQkFBc0IsQ0FBQztBQUVwRyxXQUFPO0FBQUEsTUFDTCxRQUFRLE1BQXdCO0FBQzlCLGFBQUssS0FBSyxRQUFRLENBQUMsY0FBYztBQUMvQixjQUNFLGtCQUFrQixTQUFTLEtBQzNCLHVDQUF1QyxXQUFXLG1CQUFtQixLQUNyRSxxQ0FBcUMsU0FBUyxLQUM5QyxvQ0FBb0MsV0FBVyxtQkFBbUIsR0FDbEU7QUFDQSxvQkFBUSxPQUFPO0FBQUEsY0FDYixNQUFNO0FBQUEsY0FDTixXQUFXO0FBQUEsWUFDYixDQUFDO0FBQUEsVUFDSDtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLDBCQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,74 @@
1
+ // src/no-status-code-assert.ts
2
+ import { StatusCodes } from "http-status-codes";
3
+ import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
+ import getDocumentationUrl from "./get-documentation-url.mjs";
5
+ var ruleId = "no-status-code-assert";
6
+ var NO_STATUS_CODE_ASSERT = "NO_STATUS_CODE_ASSERT";
7
+ var statusCodes = [
8
+ StatusCodes.OK,
9
+ StatusCodes.CREATED,
10
+ StatusCodes.BAD_REQUEST,
11
+ StatusCodes.UNAUTHORIZED,
12
+ StatusCodes.FORBIDDEN,
13
+ StatusCodes.NOT_FOUND,
14
+ StatusCodes.CONFLICT,
15
+ StatusCodes.INTERNAL_SERVER_ERROR
16
+ ];
17
+ var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
18
+ var hasStatusCodeOrValue = (arg) => {
19
+ const isStatusCodeLiteral = (value) => statusCodes.includes(value);
20
+ switch (arg.type) {
21
+ case AST_NODE_TYPES.Literal:
22
+ if (typeof arg.value === "number") {
23
+ return isStatusCodeLiteral(arg.value);
24
+ }
25
+ break;
26
+ case AST_NODE_TYPES.MemberExpression: {
27
+ const object = arg.object;
28
+ const property = arg.property;
29
+ if (object.type === AST_NODE_TYPES.Identifier && object.name === "StatusCodes" && property.type === AST_NODE_TYPES.Identifier) {
30
+ return true;
31
+ }
32
+ break;
33
+ }
34
+ case AST_NODE_TYPES.BinaryExpression:
35
+ return hasStatusCodeOrValue(arg.left) || hasStatusCodeOrValue(arg.right);
36
+ }
37
+ return false;
38
+ };
39
+ var isAssertIdentifier = (node) => node.type === AST_NODE_TYPES.Identifier && node.name === "assert";
40
+ var isAssertMemberExpression = (node) => node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.object.name === "assert" && node.property.type === AST_NODE_TYPES.Identifier;
41
+ var isAssertCallWithStatusCode = (callee, args) => (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) && args.some((arg) => hasStatusCodeOrValue(arg) && arg.type !== AST_NODE_TYPES.Identifier);
42
+ var rule = createRule({
43
+ name: ruleId,
44
+ meta: {
45
+ type: "problem",
46
+ docs: {
47
+ description: "Disallow using status codes in assertions; use error handling instead"
48
+ },
49
+ schema: [],
50
+ messages: {
51
+ [NO_STATUS_CODE_ASSERT]: "Do not use status codes in assertions; use error handling instead"
52
+ }
53
+ },
54
+ defaultOptions: [],
55
+ create(context) {
56
+ return {
57
+ CallExpression(node) {
58
+ const callee = node.callee;
59
+ if (isAssertCallWithStatusCode(callee, node.arguments)) {
60
+ context.report({
61
+ node,
62
+ messageId: NO_STATUS_CODE_ASSERT
63
+ });
64
+ }
65
+ }
66
+ };
67
+ }
68
+ });
69
+ var no_status_code_assert_default = rule;
70
+ export {
71
+ no_status_code_assert_default as default,
72
+ ruleId
73
+ };
74
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLXN0YXR1cy1jb2RlLWFzc2VydC50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLG1CQUFtQjtBQUU1QixTQUFTLGdCQUFnQixtQkFBdUM7QUFDaEUsT0FBTyx5QkFBeUI7QUFFekIsSUFBTSxTQUFTO0FBQ3RCLElBQU0sd0JBQXdCO0FBRTlCLElBQU0sY0FBYztBQUFBLEVBQ2xCLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFDZDtBQUVBLElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLG9CQUFvQixJQUFJLENBQUM7QUFROUUsSUFBTSx1QkFBdUIsQ0FBQyxRQUFnQztBQUM1RCxRQUFNLHNCQUFzQixDQUFDLFVBQTJCLFlBQVksU0FBUyxLQUFLO0FBRWxGLFVBQVEsSUFBSSxNQUFNO0FBQUEsSUFDaEIsS0FBSyxlQUFlO0FBQ2xCLFVBQUksT0FBTyxJQUFJLFVBQVUsVUFBVTtBQUNqQyxlQUFPLG9CQUFvQixJQUFJLEtBQUs7QUFBQSxNQUN0QztBQUNBO0FBQUEsSUFDRixLQUFLLGVBQWUsa0JBQWtCO0FBQ3BDLFlBQU0sU0FBUyxJQUFJO0FBQ25CLFlBQU0sV0FBVyxJQUFJO0FBQ3JCLFVBQ0UsT0FBTyxTQUFTLGVBQWUsY0FDL0IsT0FBTyxTQUFTLGlCQUNoQixTQUFTLFNBQVMsZUFBZSxZQUNqQztBQUNBLGVBQU87QUFBQSxNQUNUO0FBQ0E7QUFBQSxJQUNGO0FBQUEsSUFDQSxLQUFLLGVBQWU7QUFDbEIsYUFBTyxxQkFBcUIsSUFBSSxJQUFJLEtBQUsscUJBQXFCLElBQUksS0FBSztBQUFBLEVBQzNFO0FBQ0EsU0FBTztBQUNUO0FBUUEsSUFBTSxxQkFBcUIsQ0FBQyxTQUMxQixLQUFLLFNBQVMsZUFBZSxjQUFjLEtBQUssU0FBUztBQVEzRCxJQUFNLDJCQUEyQixDQUFDLFNBQ2hDLEtBQUssU0FBUyxlQUFlLG9CQUM3QixLQUFLLE9BQU8sU0FBUyxlQUFlLGNBQ3BDLEtBQUssT0FBTyxTQUFTLFlBQ3JCLEtBQUssU0FBUyxTQUFTLGVBQWU7QUFTeEMsSUFBTSw2QkFBNkIsQ0FBQyxRQUF1QixVQUN4RCxtQkFBbUIsTUFBTSxLQUFLLHlCQUF5QixNQUFNLE1BQzlELEtBQUssS0FBSyxDQUFDLFFBQVEscUJBQXFCLEdBQUcsS0FBSyxJQUFJLFNBQVMsZUFBZSxVQUFVO0FBRXhGLElBQU0sT0FBMEQsV0FBVztBQUFBLEVBQ3pFLE1BQU07QUFBQSxFQUNOLE1BQU07QUFBQSxJQUNKLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxNQUNKLGFBQWE7QUFBQSxJQUNmO0FBQUEsSUFDQSxRQUFRLENBQUM7QUFBQSxJQUNULFVBQVU7QUFBQSxNQUNSLENBQUMscUJBQXFCLEdBQUc7QUFBQSxJQUMzQjtBQUFBLEVBQ0Y7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsV0FBTztBQUFBLE1BQ0wsZUFBZSxNQUErQjtBQUM1QyxjQUFNLFNBQVMsS0FBSztBQUNwQixZQUFJLDJCQUEyQixRQUFRLEtBQUssU0FBUyxHQUFHO0FBQ3RELGtCQUFRLE9BQU87QUFBQSxZQUNiO0FBQUEsWUFDQSxXQUFXO0FBQUEsVUFDYixDQUFDO0FBQUEsUUFDSDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLGdDQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,5 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const ruleId = "no-status-code-assert";
3
+ declare const NO_STATUS_CODE_ASSERT = "NO_STATUS_CODE_ASSERT";
4
+ declare const rule: TSESLint.RuleModule<typeof NO_STATUS_CODE_ASSERT>;
5
+ export default rule;
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@checkdigit/eslint-plugin","version":"7.7.1-PR.101-95b3","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-mjs","!src/**/test/**","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/test/**","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-mjs/**/test/**","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 .","lint:fix":"eslint --max-warnings 0 --fix .","prepare":"","prepublishOnly":"npm run build:dist-types && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@typescript-eslint/type-utils":"^8.18.1","@typescript-eslint/utils":"^8.18.1","ts-api-utils":"^2.0.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^6.0.0","@checkdigit/typescript-config":"^9.0.0","@eslint/js":"^9.17.0","@types/eslint":"^9.6.1","@types/eslint-config-prettier":"^6.11.3","@typescript-eslint/parser":"^8.18.1","@typescript-eslint/rule-tester":"^8.18.1","eslint":"^9.17.0","eslint-config-prettier":"^9.1.0","eslint-import-resolver-typescript":"^3.7.0","eslint-plugin-eslint-plugin":"^6.3.2","eslint-plugin-import":"^2.31.0","eslint-plugin-no-only-tests":"^3.3.0","eslint-plugin-no-secrets":"^2.1.1","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"1.0.4","http-status-codes":"^2.3.0","rimraf":"^6.0.1","typescript-eslint":"^8.18.1"},"peerDependencies":{"eslint":">=9 <10"},"engines":{"node":">=20.17"}}
1
+ {"name":"@checkdigit/eslint-plugin","version":"7.8.0-PR.97-d090","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-mjs","!src/**/test/**","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/test/**","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-mjs/**/test/**","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 .","lint:fix":"eslint --max-warnings 0 --fix .","prepare":"","prepublishOnly":"npm run build:dist-types && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@typescript-eslint/type-utils":"^8.18.1","@typescript-eslint/utils":"^8.18.1","ts-api-utils":"^2.0.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^6.0.0","@checkdigit/typescript-config":"^9.0.0","@eslint/js":"^9.17.0","@types/eslint":"^9.6.1","@types/eslint-config-prettier":"^6.11.3","@typescript-eslint/parser":"^8.18.1","@typescript-eslint/rule-tester":"^8.18.1","eslint":"^9.17.0","eslint-config-prettier":"^9.1.0","eslint-import-resolver-typescript":"^3.7.0","eslint-plugin-eslint-plugin":"^6.3.2","eslint-plugin-import":"^2.31.0","eslint-plugin-no-only-tests":"^3.3.0","eslint-plugin-no-secrets":"^2.1.1","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"1.0.4","http-status-codes":"^2.3.0","rimraf":"^6.0.1","typescript-eslint":"^8.18.1"},"peerDependencies":{"eslint":">=9 <10"},"engines":{"node":">=20.17"}}
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from './in
12
12
  import noDuplicatedImports, { ruleId as noDuplicatedImportsRuleId } from './no-duplicated-imports.ts';
13
13
  import noLegacyServiceTyping, { ruleId as noLegacyServiceTypingRuleId } from './no-legacy-service-typing.ts';
14
14
  import noPromiseInstanceMethod, { ruleId as noPromiseInstanceMethodRuleId } from './no-promise-instance-method.ts';
15
+ import noStatusCodeAssert from './no-status-code-assert.ts';
15
16
  import requireFixedServicesImport, {
16
17
  ruleId as requireFixedServicesImportRuleId,
17
18
  } from './require-fixed-services-import.ts';
@@ -39,6 +40,7 @@ const rules: Record<string, TSESLint.LooseRuleDefinition> = {
39
40
  'file-path-comment': filePathComment,
40
41
  'no-card-numbers': noCardNumbers,
41
42
  'no-random-v4-uuid': noRandomV4UUID,
43
+ 'no-status-code-assert': noStatusCodeAssert,
42
44
  'no-uuid': noUuid,
43
45
  'require-strict-assert': requireStrictAssert,
44
46
  'require-ts-extension-imports': requireTsExtensionImports,
@@ -73,14 +75,12 @@ const configs: Record<string, TSESLint.FlatConfig.Config[]> = {
73
75
  '@checkdigit/no-card-numbers': 'error',
74
76
  '@checkdigit/file-path-comment': 'error',
75
77
  '@checkdigit/no-random-v4-uuid': 'error',
78
+ '@checkdigit/no-status-code-assert': 'error',
76
79
  '@checkdigit/no-uuid': 'error',
77
80
  '@checkdigit/require-strict-assert': 'error',
78
81
  '@checkdigit/require-ts-extension-imports': 'error',
79
82
  '@checkdigit/no-wallaby-comment': 'error',
80
- '@checkdigit/no-side-effects': [
81
- 'error',
82
- { excludedIdentifiers: ['assert', 'debug', 'log', 'promisify', 'Symbol.for'] },
83
- ],
83
+ '@checkdigit/no-side-effects': ['error', { excludedIdentifiers: ['assert', 'debug', 'log', 'promisify'] }],
84
84
  '@checkdigit/regular-expression-comment': 'error',
85
85
  '@checkdigit/require-assert-predicate-rejects-throws': 'error',
86
86
  '@checkdigit/object-literal-response': 'error',
@@ -106,6 +106,7 @@ const configs: Record<string, TSESLint.FlatConfig.Config[]> = {
106
106
  '@checkdigit/no-card-numbers': 'error',
107
107
  '@checkdigit/file-path-comment': 'off',
108
108
  '@checkdigit/no-random-v4-uuid': 'error',
109
+ '@checkdigit/no-status-code-assert': 'error',
109
110
  '@checkdigit/no-uuid': 'error',
110
111
  '@checkdigit/require-strict-assert': 'error',
111
112
  '@checkdigit/require-ts-extension-imports': 'error',
@@ -46,58 +46,15 @@ function isVariableDeclarationAwaitExpression(node: TSESTree.Node): boolean {
46
46
  );
47
47
  }
48
48
 
49
- // Helper function to check if the callee is an identifier and not excluded
50
- function isIdentifierCallee(node: TSESTree.CallExpression, excludedIdentifiers: string[]): boolean {
51
- return node.callee.type === TSESTree.AST_NODE_TYPES.Identifier && !excludedIdentifiers.includes(node.callee.name);
52
- }
53
-
54
- // Helper function to check if the callee is a member expression and not excluded
55
- function isMemberExpressionCallee(node: TSESTree.CallExpression, excludedIdentifiers: string[]): boolean {
56
- return (
57
- node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
58
- node.callee.object.type === TSESTree.AST_NODE_TYPES.Identifier &&
59
- node.callee.property.type === TSESTree.AST_NODE_TYPES.Identifier &&
60
- !excludedIdentifiers.includes(`${node.callee.object.name}.${node.callee.property.name}`)
61
- );
62
- }
63
-
64
- // Helper function to check if the callee is a member expression with a non-identifier object
65
- function isNonIdentifierObjectMemberExpressionCallee(node: TSESTree.CallExpression): boolean {
66
- return (
67
- node.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
68
- node.callee.object.type !== TSESTree.AST_NODE_TYPES.Identifier
69
- );
70
- }
71
-
72
- // To check if it is a variable declaration with a call expression i.e const configuration = new Class(); or Member Expressions i.e const server = http.createServer();
49
+ // To check if it is a variable declaration with a call expression
73
50
  function isVariableDeclarationCallExpression(node: TSESTree.Node, excludedIdentifiers: string[]): boolean {
74
- if (node.type !== TSESTree.AST_NODE_TYPES.VariableDeclaration || node.declarations.length === 0) {
75
- return false;
76
- }
77
-
78
- const init = node.declarations[0]?.init;
79
- if (init?.type !== TSESTree.AST_NODE_TYPES.CallExpression) {
80
- return false;
81
- }
82
-
83
- return (
84
- isIdentifierCallee(init, excludedIdentifiers) ||
85
- isMemberExpressionCallee(init, excludedIdentifiers) ||
86
- isNonIdentifierObjectMemberExpressionCallee(init)
87
- );
88
- }
89
-
90
- // Helper function to check if a given AST node (statement) has any side effects that should be reported
91
- function hasSideEffects(statement: TSESTree.Node, excludedIdentifiers: string[]): boolean {
92
51
  return (
93
- isAwaitExpression(statement) ||
94
- isCallExpressionCalleeMemberExpression(statement, excludedIdentifiers) ||
95
- isVariableDeclarationAwaitExpression(statement) ||
96
- isVariableDeclarationCallExpression(statement, excludedIdentifiers) ||
97
- (statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration &&
98
- statement.declaration !== null &&
99
- (isVariableDeclarationAwaitExpression(statement.declaration) ||
100
- isVariableDeclarationCallExpression(statement.declaration, excludedIdentifiers)))
52
+ node.type === TSESTree.AST_NODE_TYPES.VariableDeclaration &&
53
+ node.declarations.length > 0 &&
54
+ node.declarations[0]?.init?.type === TSESTree.AST_NODE_TYPES.CallExpression &&
55
+ ((node.declarations[0].init.callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
56
+ !excludedIdentifiers.includes(node.declarations[0].init.callee.name)) ||
57
+ node.declarations[0].init.callee.type === TSESTree.AST_NODE_TYPES.MemberExpression)
101
58
  );
102
59
  }
103
60
 
@@ -130,21 +87,16 @@ const rule: ReturnType<typeof createRule> = createRule({
130
87
  create(context) {
131
88
  const options: RuleOptions = context.options[0] as RuleOptions;
132
89
  const excludedIdentifiers = options.excludedIdentifiers.length > 0 ? options.excludedIdentifiers : [];
90
+
133
91
  return {
134
92
  Program(node: TSESTree.Program) {
135
- const hasExport = node.body.some(
136
- (statement: TSESTree.Node) =>
137
- statement.type === TSESTree.AST_NODE_TYPES.ExportNamedDeclaration ||
138
- statement.type === TSESTree.AST_NODE_TYPES.ExportDefaultDeclaration ||
139
- statement.type === TSESTree.AST_NODE_TYPES.ExportAllDeclaration,
140
- );
141
-
142
- if (!hasExport) {
143
- return;
144
- }
145
-
146
- node.body.forEach((statement: TSESTree.Node) => {
147
- if (hasSideEffects(statement, excludedIdentifiers)) {
93
+ node.body.forEach((statement) => {
94
+ if (
95
+ isAwaitExpression(statement) ||
96
+ isCallExpressionCalleeMemberExpression(statement, excludedIdentifiers) ||
97
+ isVariableDeclarationAwaitExpression(statement) ||
98
+ isVariableDeclarationCallExpression(statement, excludedIdentifiers)
99
+ ) {
148
100
  context.report({
149
101
  node: statement,
150
102
  messageId: NO_SIDE_EFFECTS,
@@ -0,0 +1,123 @@
1
+ // no-status-code-assert.ts
2
+
3
+ /*
4
+ * Copyright (c) 2022-2024 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import { StatusCodes } from 'http-status-codes';
10
+
11
+ import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils';
12
+ import getDocumentationUrl from './get-documentation-url';
13
+
14
+ export const ruleId = 'no-status-code-assert';
15
+ const NO_STATUS_CODE_ASSERT = 'NO_STATUS_CODE_ASSERT';
16
+
17
+ const statusCodes = [
18
+ StatusCodes.OK,
19
+ StatusCodes.CREATED,
20
+ StatusCodes.BAD_REQUEST,
21
+ StatusCodes.UNAUTHORIZED,
22
+ StatusCodes.FORBIDDEN,
23
+ StatusCodes.NOT_FOUND,
24
+ StatusCodes.CONFLICT,
25
+ StatusCodes.INTERNAL_SERVER_ERROR,
26
+ ];
27
+
28
+ const createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
29
+
30
+ /**
31
+ * Checks if a given AST node contains any status code value.
32
+ *
33
+ * @param arg - The AST node to check.
34
+ * @returns `true` if the node or its sub-nodes contain any status code value, otherwise `false`.
35
+ */
36
+ const hasStatusCodeOrValue = (arg: TSESTree.Node): boolean => {
37
+ const isStatusCodeLiteral = (value: number): boolean => statusCodes.includes(value);
38
+
39
+ switch (arg.type) {
40
+ case AST_NODE_TYPES.Literal:
41
+ if (typeof arg.value === 'number') {
42
+ return isStatusCodeLiteral(arg.value);
43
+ }
44
+ break;
45
+ case AST_NODE_TYPES.MemberExpression: {
46
+ const object = arg.object;
47
+ const property = arg.property;
48
+ if (
49
+ object.type === AST_NODE_TYPES.Identifier &&
50
+ object.name === 'StatusCodes' &&
51
+ property.type === AST_NODE_TYPES.Identifier
52
+ ) {
53
+ return true;
54
+ }
55
+ break;
56
+ }
57
+ case AST_NODE_TYPES.BinaryExpression:
58
+ return hasStatusCodeOrValue(arg.left) || hasStatusCodeOrValue(arg.right);
59
+ }
60
+ return false;
61
+ };
62
+
63
+ /**
64
+ * Checks if a given AST node is an identifier with the name 'assert'.
65
+ *
66
+ * @param node - The AST node to check.
67
+ * @returns `true` if the node is an identifier with the name 'assert', otherwise `false`.
68
+ */
69
+ const isAssertIdentifier = (node: TSESTree.Node): boolean =>
70
+ node.type === AST_NODE_TYPES.Identifier && node.name === 'assert';
71
+
72
+ /**
73
+ * Checks if a given AST node is a member expression with the object named 'assert'.
74
+ *
75
+ * @param node - The AST node to check.
76
+ * @returns `true` if the node is a member expression with the object named 'assert', otherwise `false`.
77
+ */
78
+ const isAssertMemberExpression = (node: TSESTree.Node): boolean =>
79
+ node.type === AST_NODE_TYPES.MemberExpression &&
80
+ node.object.type === AST_NODE_TYPES.Identifier &&
81
+ node.object.name === 'assert' &&
82
+ node.property.type === AST_NODE_TYPES.Identifier;
83
+
84
+ /**
85
+ * Checks if a given AST node is an identifier with the name 'assert'.
86
+ *
87
+ * @returns `true` if the node is an identifier with the name 'assert', otherwise `false`.
88
+ * @param callee
89
+ * @param args
90
+ */
91
+ const isAssertCallWithStatusCode = (callee: TSESTree.Node, args: TSESTree.Node[]): boolean =>
92
+ (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) &&
93
+ args.some((arg) => hasStatusCodeOrValue(arg) && arg.type !== AST_NODE_TYPES.Identifier);
94
+
95
+ const rule: TSESLint.RuleModule<typeof NO_STATUS_CODE_ASSERT> = createRule({
96
+ name: ruleId,
97
+ meta: {
98
+ type: 'problem',
99
+ docs: {
100
+ description: 'Disallow using status codes in assertions; use error handling instead',
101
+ },
102
+ schema: [],
103
+ messages: {
104
+ [NO_STATUS_CODE_ASSERT]: 'Do not use status codes in assertions; use error handling instead',
105
+ },
106
+ },
107
+ defaultOptions: [],
108
+ create(context) {
109
+ return {
110
+ CallExpression(node: TSESTree.CallExpression) {
111
+ const callee = node.callee;
112
+ if (isAssertCallWithStatusCode(callee, node.arguments)) {
113
+ context.report({
114
+ node,
115
+ messageId: NO_STATUS_CODE_ASSERT,
116
+ });
117
+ }
118
+ },
119
+ };
120
+ },
121
+ });
122
+
123
+ export default rule;