@checkdigit/eslint-plugin 7.11.0 → 7.12.0-PR.45-1e1c

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.
@@ -29,6 +29,7 @@ import objectLiteralResponse from "./object-literal-response.mjs";
29
29
  import regexComment from "./regular-expression-comment.mjs";
30
30
  import requireAssertPredicateRejectsThrows from "./require-assert-predicate-rejects-throws.mjs";
31
31
  import requireStrictAssert from "./require-strict-assert.mjs";
32
+ import requireAssertMessage from "./require-assert-message.mjs";
32
33
  import requireTsExtensionImportsExports from "./require-ts-extension-imports-exports.mjs";
33
34
  var rules = {
34
35
  "file-path-comment": filePathComment,
@@ -37,6 +38,7 @@ var rules = {
37
38
  "no-random-v4-uuid": noRandomV4UUID,
38
39
  "no-status-code-assert": noStatusCodeAssert,
39
40
  "no-uuid": noUuid,
41
+ "require-assert-message": requireAssertMessage,
40
42
  "require-strict-assert": requireStrictAssert,
41
43
  "require-ts-extension-imports-exports": requireTsExtensionImportsExports,
42
44
  "no-test-import": noTestImport,
@@ -72,6 +74,7 @@ var configs = {
72
74
  "@checkdigit/no-random-v4-uuid": "error",
73
75
  "@checkdigit/no-status-code-assert": "error",
74
76
  "@checkdigit/no-uuid": "error",
77
+ "@checkdigit/require-assert-message": "error",
75
78
  "@checkdigit/require-strict-assert": "error",
76
79
  "@checkdigit/require-ts-extension-imports-exports": "error",
77
80
  "@checkdigit/no-wallaby-comment": "error",
@@ -108,6 +111,7 @@ var configs = {
108
111
  "@checkdigit/no-random-v4-uuid": "error",
109
112
  "@checkdigit/no-status-code-assert": "error",
110
113
  "@checkdigit/no-uuid": "error",
114
+ "@checkdigit/require-assert-message": "error",
111
115
  "@checkdigit/require-strict-assert": "error",
112
116
  "@checkdigit/require-ts-extension-imports-exports": "error",
113
117
  "@checkdigit/no-wallaby-comment": "off",
@@ -137,4 +141,4 @@ var src_default = defaultToExport;
137
141
  export {
138
142
  src_default as default
139
143
  };
140
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVVBLE9BQU8sd0JBQXdCLFVBQVUsa0NBQWtDO0FBQzNFLE9BQU8sdUJBQXVCLFVBQVUsaUNBQWlDO0FBQ3pFLE9BQU8seUJBQXlCLFVBQVUsbUNBQW1DO0FBQzdFLE9BQU8sMkJBQTJCLFVBQVUscUNBQXFDO0FBQ2pGLE9BQU8sd0JBQXdCO0FBQy9CLE9BQU87QUFBQSxFQUNMLFVBQVU7QUFBQSxPQUNMO0FBQ1AsT0FBTztBQUFBLEVBQ0wsVUFBVTtBQUFBLE9BQ0w7QUFDUCxPQUFPO0FBQUEsRUFDTCxVQUFVO0FBQUEsT0FDTDtBQUNQLE9BQU8sa0JBQWtCLFVBQVUsNEJBQTRCO0FBQy9ELE9BQU87QUFBQSxFQUNMLFVBQVU7QUFBQSxPQUNMO0FBQ1AsT0FBTyxxQkFBcUI7QUFDNUIsT0FBTyxtQkFBbUI7QUFDMUIsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sb0JBQW9CO0FBQzNCLE9BQU8sa0JBQWtCO0FBQ3pCLE9BQU8sWUFBWTtBQUNuQixPQUFPLHNCQUFzQjtBQUM3QixPQUFPLDJCQUEyQjtBQUNsQyxPQUFPLGtCQUFrQjtBQUN6QixPQUFPLHlDQUF5QztBQUNoRCxPQUFPLHlCQUF5QjtBQUNoQyxPQUFPLHNDQUFzQztBQUU3QyxJQUFNLFFBQXNEO0FBQUEsRUFDMUQscUJBQXFCO0FBQUEsRUFDckIsbUJBQW1CO0FBQUEsRUFDbkIsV0FBVztBQUFBLEVBQ1gscUJBQXFCO0FBQUEsRUFDckIseUJBQXlCO0FBQUEsRUFDekIsV0FBVztBQUFBLEVBQ1gseUJBQXlCO0FBQUEsRUFDekIsd0NBQXdDO0FBQUEsRUFDeEMsa0JBQWtCO0FBQUEsRUFDbEIsc0JBQXNCO0FBQUEsRUFDdEIsbUJBQW1CO0FBQUEsRUFDbkIsOEJBQThCO0FBQUEsRUFDOUIsMkNBQTJDO0FBQUEsRUFDM0MsMkJBQTJCO0FBQUEsRUFDM0IsQ0FBQywwQkFBMEIsR0FBRztBQUFBLEVBQzlCLENBQUMsNkJBQTZCLEdBQUc7QUFBQSxFQUNqQyxDQUFDLDJCQUEyQixHQUFHO0FBQUEsRUFDL0IsQ0FBQyxnQ0FBZ0MsR0FBRztBQUFBLEVBQ3BDLENBQUMseUJBQXlCLEdBQUc7QUFBQSxFQUM3QixDQUFDLG9CQUFvQixHQUFHO0FBQUEsRUFDeEIsQ0FBQywyQ0FBMkMsR0FBRztBQUFBLEVBQy9DLENBQUMsZ0NBQWdDLEdBQUc7QUFBQSxFQUNwQyxDQUFDLHFDQUFxQyxHQUFHO0FBQzNDO0FBRUEsSUFBTSxTQUFxQztBQUFBLEVBQ3pDO0FBQ0Y7QUFFQSxJQUFNLFVBQXdEO0FBQUEsRUFDNUQsS0FBSztBQUFBLElBQ0g7QUFBQSxNQUNFLE9BQU8sQ0FBQyxTQUFTO0FBQUEsTUFDakIsU0FBUztBQUFBLFFBQ1AsZUFBZTtBQUFBLE1BQ2pCO0FBQUEsTUFDQSxPQUFPO0FBQUEsUUFDTCwrQkFBK0I7QUFBQSxRQUMvQix1QkFBdUI7QUFBQSxRQUN2QixpQ0FBaUM7QUFBQSxRQUNqQyxpQ0FBaUM7QUFBQSxRQUNqQyxxQ0FBcUM7QUFBQSxRQUNyQyx1QkFBdUI7QUFBQSxRQUN2QixxQ0FBcUM7QUFBQSxRQUNyQyxvREFBb0Q7QUFBQSxRQUNwRCxrQ0FBa0M7QUFBQSxRQUNsQywrQkFBK0I7QUFBQSxVQUM3QjtBQUFBLFVBQ0EsRUFBRSxxQkFBcUIsQ0FBQyxVQUFVLFNBQVMsT0FBTyxhQUFhLFlBQVksRUFBRTtBQUFBLFFBQy9FO0FBQUEsUUFDQSwwQ0FBMEM7QUFBQSxRQUMxQyx1REFBdUQ7QUFBQSxRQUN2RCx1Q0FBdUM7QUFBQSxRQUN2Qyw4QkFBOEI7QUFBQSxRQUM5QixDQUFDLGVBQWUsMEJBQTBCLEVBQUUsR0FBRztBQUFBLFFBQy9DLENBQUMsZUFBZSw2QkFBNkIsRUFBRSxHQUFHO0FBQUEsUUFDbEQsQ0FBQyxlQUFlLDJCQUEyQixFQUFFLEdBQUc7QUFBQSxRQUNoRCxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSx5QkFBeUIsRUFBRSxHQUFHO0FBQUEsUUFDOUMsQ0FBQyxlQUFlLGdDQUFnQyxFQUFFLEdBQUc7QUFBQSxRQUNyRCxDQUFDLGVBQWUscUNBQXFDLEVBQUUsR0FBRztBQUFBLFFBQzFELENBQUMsZUFBZSxvQkFBb0IsRUFBRSxHQUFHO0FBQUEsUUFDekMsQ0FBQyxlQUFlLDJDQUEyQyxFQUFFLEdBQUc7QUFBQSxNQUNsRTtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxhQUFhO0FBQUEsSUFDWDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLHVCQUF1QjtBQUFBLFFBQ3ZCLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHFDQUFxQztBQUFBLFFBQ3JDLHVCQUF1QjtBQUFBLFFBQ3ZCLHFDQUFxQztBQUFBLFFBQ3JDLG9EQUFvRDtBQUFBLFFBQ3BELGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQjtBQUFBLFFBQy9CLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxRQUN6QyxDQUFDLGVBQWUsMkNBQTJDLEVBQUUsR0FBRztBQUFBLE1BQ2xFO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjtBQUVBLElBQU0sa0JBRUY7QUFBQSxFQUNGLEdBQUc7QUFBQSxFQUNIO0FBQ0Y7QUFDQSxJQUFPLGNBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
144
+ //# sourceMappingURL=data:application/json;base64,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Z0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSx5QkFBeUIsRUFBRSxHQUFHO0FBQUEsUUFDOUMsQ0FBQyxlQUFlLGdDQUFnQyxFQUFFLEdBQUc7QUFBQSxRQUNyRCxDQUFDLGVBQWUscUNBQXFDLEVBQUUsR0FBRztBQUFBLFFBQzFELENBQUMsZUFBZSxvQkFBb0IsRUFBRSxHQUFHO0FBQUEsUUFDekMsQ0FBQyxlQUFlLDJDQUEyQyxFQUFFLEdBQUc7QUFBQSxNQUNsRTtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxhQUFhO0FBQUEsSUFDWDtBQUFBLE1BQ0UsT0FBTyxDQUFDLFNBQVM7QUFBQSxNQUNqQixTQUFTO0FBQUEsUUFDUCxlQUFlO0FBQUEsTUFDakI7QUFBQSxNQUNBLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLHVCQUF1QjtBQUFBLFFBQ3ZCLGlDQUFpQztBQUFBLFFBQ2pDLGlDQUFpQztBQUFBLFFBQ2pDLHFDQUFxQztBQUFBLFFBQ3JDLHVCQUF1QjtBQUFBLFFBQ3ZCLHNDQUFzQztBQUFBLFFBQ3RDLHFDQUFxQztBQUFBLFFBQ3JDLG9EQUFvRDtBQUFBLFFBQ3BELGtDQUFrQztBQUFBLFFBQ2xDLCtCQUErQjtBQUFBLFFBQy9CLDBDQUEwQztBQUFBLFFBQzFDLHVEQUF1RDtBQUFBLFFBQ3ZELHVDQUF1QztBQUFBLFFBQ3ZDLDhCQUE4QjtBQUFBLFFBQzlCLENBQUMsZUFBZSwwQkFBMEIsRUFBRSxHQUFHO0FBQUEsUUFDL0MsQ0FBQyxlQUFlLDZCQUE2QixFQUFFLEdBQUc7QUFBQSxRQUNsRCxDQUFDLGVBQWUsMkJBQTJCLEVBQUUsR0FBRztBQUFBLFFBQ2hELENBQUMsZUFBZSxnQ0FBZ0MsRUFBRSxHQUFHO0FBQUEsUUFDckQsQ0FBQyxlQUFlLHlCQUF5QixFQUFFLEdBQUc7QUFBQSxRQUM5QyxDQUFDLGVBQWUsZ0NBQWdDLEVBQUUsR0FBRztBQUFBLFFBQ3JELENBQUMsZUFBZSxxQ0FBcUMsRUFBRSxHQUFHO0FBQUEsUUFDMUQsQ0FBQyxlQUFlLG9CQUFvQixFQUFFLEdBQUc7QUFBQSxRQUN6QyxDQUFDLGVBQWUsMkNBQTJDLEVBQUUsR0FBRztBQUFBLE1BQ2xFO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjtBQUVBLElBQU0sa0JBRUY7QUFBQSxFQUNGLEdBQUc7QUFBQSxFQUNIO0FBQ0Y7QUFDQSxJQUFPLGNBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,80 @@
1
+ // src/require-assert-message.ts
2
+ import { strict as assert } from "node:assert";
3
+ import { ESLintUtils } from "@typescript-eslint/utils";
4
+ import { TSESTree } from "@typescript-eslint/types";
5
+ import getDocumentationUrl from "./get-documentation-url.mjs";
6
+ var ruleId = "require-assert-message";
7
+ var MISSING_ASSERT_MESSAGE = "MISSING_ASSERT_MESSAGE";
8
+ var methodsRequiringMessage = Object.keys(assert).filter((key) => typeof assert[key] === "function");
9
+ var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
10
+ var rule = createRule({
11
+ name: ruleId,
12
+ meta: {
13
+ type: "problem",
14
+ docs: {
15
+ description: "Validate that message argument is always supplied to node:assert methods"
16
+ },
17
+ schema: [],
18
+ messages: {
19
+ [MISSING_ASSERT_MESSAGE]: "Missing message argument in {{methodName}}() method."
20
+ }
21
+ },
22
+ defaultOptions: [],
23
+ create(context) {
24
+ let assertAlias = "assert";
25
+ const parserServices = ESLintUtils.getParserServices(context);
26
+ const checker = parserServices.program.getTypeChecker();
27
+ const messageIndexCache = {};
28
+ return {
29
+ ImportDeclaration(node) {
30
+ if (node.source.value === "node:assert") {
31
+ const specifier = node.specifiers.find(
32
+ (importSpecifier) => importSpecifier.type === TSESTree.AST_NODE_TYPES.ImportDefaultSpecifier || importSpecifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier
33
+ );
34
+ if (specifier) {
35
+ assertAlias = specifier.local.name;
36
+ }
37
+ }
38
+ },
39
+ CallExpression(node) {
40
+ const callee = node.callee;
41
+ if (callee.type === TSESTree.AST_NODE_TYPES.MemberExpression && callee.object.type === TSESTree.AST_NODE_TYPES.Identifier && callee.property.type === TSESTree.AST_NODE_TYPES.Identifier) {
42
+ const objectName = callee.object.name;
43
+ const methodName = callee.property.name;
44
+ if (objectName === assertAlias && methodsRequiringMessage.includes(methodName)) {
45
+ if (!(methodName in messageIndexCache)) {
46
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
47
+ const signature = checker.getResolvedSignature(tsNode);
48
+ const messageParameterIndex = signature?.getParameters().findIndex((param) => param.name === "message");
49
+ messageIndexCache[methodName] = messageParameterIndex ?? 2;
50
+ }
51
+ const messageIndex = messageIndexCache[methodName];
52
+ if (messageIndex !== void 0 && node.arguments.length <= messageIndex) {
53
+ context.report({
54
+ node,
55
+ messageId: MISSING_ASSERT_MESSAGE,
56
+ data: {
57
+ methodName
58
+ }
59
+ });
60
+ }
61
+ }
62
+ } else if (callee.type === TSESTree.AST_NODE_TYPES.Identifier && callee.name === assertAlias && node.arguments.length < 2) {
63
+ context.report({
64
+ node,
65
+ messageId: MISSING_ASSERT_MESSAGE,
66
+ data: {
67
+ methodName: "assert"
68
+ }
69
+ });
70
+ }
71
+ }
72
+ };
73
+ }
74
+ });
75
+ var require_assert_message_default = rule;
76
+ export {
77
+ require_assert_message_default as default,
78
+ ruleId
79
+ };
80
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3JlcXVpcmUtYXNzZXJ0LW1lc3NhZ2UudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFDakMsU0FBUyxtQkFBNkI7QUFDdEMsU0FBUyxnQkFBZ0I7QUFDekIsT0FBTyx5QkFBeUI7QUFFekIsSUFBTSxTQUFTO0FBQ3RCLElBQU0seUJBQXlCO0FBRS9CLElBQU0sMEJBQTBCLE9BQU8sS0FBSyxNQUFNLEVBQUUsT0FBTyxDQUFDLFFBQVEsT0FBUSxPQUFpQixHQUFHLE1BQU0sVUFBVTtBQUVoSCxJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxvQkFBb0IsSUFBSSxDQUFDO0FBQzlFLElBQU0sT0FBK0MsV0FBVztBQUFBLEVBQzlELE1BQU07QUFBQSxFQUNOLE1BQU07QUFBQSxJQUNKLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxNQUNKLGFBQWE7QUFBQSxJQUNmO0FBQUEsSUFDQSxRQUFRLENBQUM7QUFBQSxJQUNULFVBQVU7QUFBQSxNQUNSLENBQUMsc0JBQXNCLEdBQUc7QUFBQSxJQUM1QjtBQUFBLEVBQ0Y7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsUUFBSSxjQUFjO0FBQ2xCLFVBQU0saUJBQWlCLFlBQVksa0JBQWtCLE9BQU87QUFDNUQsVUFBTSxVQUFVLGVBQWUsUUFBUSxlQUFlO0FBQ3RELFVBQU0sb0JBQTRDLENBQUM7QUFFbkQsV0FBTztBQUFBLE1BQ0wsa0JBQWtCLE1BQWtDO0FBQ2xELFlBQUksS0FBSyxPQUFPLFVBQVUsZUFBZTtBQUN2QyxnQkFBTSxZQUFZLEtBQUssV0FBVztBQUFBLFlBQ2hDLENBQUMsb0JBQ0MsZ0JBQWdCLFNBQVMsU0FBUyxlQUFlLDBCQUNqRCxnQkFBZ0IsU0FBUyxTQUFTLGVBQWU7QUFBQSxVQUNyRDtBQUNBLGNBQUksV0FBVztBQUNiLDBCQUFjLFVBQVUsTUFBTTtBQUFBLFVBQ2hDO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFBQSxNQUNBLGVBQWUsTUFBK0I7QUFDNUMsY0FBTSxTQUFTLEtBQUs7QUFDcEIsWUFDRSxPQUFPLFNBQVMsU0FBUyxlQUFlLG9CQUN4QyxPQUFPLE9BQU8sU0FBUyxTQUFTLGVBQWUsY0FDL0MsT0FBTyxTQUFTLFNBQVMsU0FBUyxlQUFlLFlBQ2pEO0FBQ0EsZ0JBQU0sYUFBYSxPQUFPLE9BQU87QUFDakMsZ0JBQU0sYUFBYSxPQUFPLFNBQVM7QUFFbkMsY0FBSSxlQUFlLGVBQWUsd0JBQXdCLFNBQVMsVUFBVSxHQUFHO0FBQzlFLGdCQUFJLEVBQUUsY0FBYyxvQkFBb0I7QUFDdEMsb0JBQU0sU0FBUyxlQUFlLHNCQUFzQixJQUFJLElBQUk7QUFDNUQsb0JBQU0sWUFBWSxRQUFRLHFCQUFxQixNQUFNO0FBQ3JELG9CQUFNLHdCQUF3QixXQUFXLGNBQWMsRUFBRSxVQUFVLENBQUMsVUFBVSxNQUFNLFNBQVMsU0FBUztBQUN0RyxnQ0FBa0IsVUFBVSxJQUFJLHlCQUF5QjtBQUFBLFlBQzNEO0FBRUEsa0JBQU0sZUFBZSxrQkFBa0IsVUFBVTtBQUNqRCxnQkFBSSxpQkFBaUIsVUFBYSxLQUFLLFVBQVUsVUFBVSxjQUFjO0FBQ3ZFLHNCQUFRLE9BQU87QUFBQSxnQkFDYjtBQUFBLGdCQUNBLFdBQVc7QUFBQSxnQkFDWCxNQUFNO0FBQUEsa0JBQ0o7QUFBQSxnQkFDRjtBQUFBLGNBQ0YsQ0FBQztBQUFBLFlBQ0g7QUFBQSxVQUNGO0FBQUEsUUFDRixXQUNFLE9BQU8sU0FBUyxTQUFTLGVBQWUsY0FDeEMsT0FBTyxTQUFTLGVBQ2hCLEtBQUssVUFBVSxTQUFTLEdBQ3hCO0FBQ0Esa0JBQVEsT0FBTztBQUFBLFlBQ2I7QUFBQSxZQUNBLFdBQVc7QUFBQSxZQUNYLE1BQU07QUFBQSxjQUNKLFlBQVk7QUFBQSxZQUNkO0FBQUEsVUFDRixDQUFDO0FBQUEsUUFDSDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLGlDQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,4 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const ruleId = "require-assert-message";
3
+ declare const rule: TSESLint.RuleModule<string, unknown[]>;
4
+ export default rule;
package/package.json CHANGED
@@ -1,96 +1 @@
1
- {
2
- "name": "@checkdigit/eslint-plugin",
3
- "version": "7.11.0",
4
- "description": "Check Digit eslint plugins",
5
- "keywords": [
6
- "eslint",
7
- "eslintplugin"
8
- ],
9
- "homepage": "https://github.com/checkdigit/eslint-plugin#readme",
10
- "bugs": {
11
- "url": "https://github.com/checkdigit/eslint-plugin/issues"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "https://github.com/checkdigit/eslint-plugin"
16
- },
17
- "license": "MIT",
18
- "author": "Check Digit, LLC",
19
- "sideEffects": false,
20
- "type": "module",
21
- "exports": {
22
- ".": {
23
- "types": "./dist-types/index.d.ts",
24
- "import": "./dist-mjs/index.mjs",
25
- "default": "./dist-mjs/index.mjs"
26
- }
27
- },
28
- "files": [
29
- "src",
30
- "dist-types",
31
- "dist-mjs",
32
- "!src/**/test/**",
33
- "!src/**/*.test.ts",
34
- "!src/**/*.spec.ts",
35
- "!dist-types/**/test/**",
36
- "!dist-types/**/*.test.d.ts",
37
- "!dist-types/**/*.spec.d.ts",
38
- "!dist-mjs/**/test/**",
39
- "!dist-mjs/**/*.test.mjs",
40
- "!dist-mjs/**/*.spec.mjs",
41
- "SECURITY.md"
42
- ],
43
- "scripts": {
44
- "build:dist-mjs": "rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs",
45
- "build:dist-types": "rimraf dist-types && npx builder --type=types --outDir=dist-types",
46
- "ci:compile": "tsc --noEmit",
47
- "ci:coverage": "NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true",
48
- "ci:lint": "npm run lint",
49
- "ci:style": "npm run prettier",
50
- "ci:test": "NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false",
51
- "lint": "eslint --max-warnings 0 .",
52
- "lint:fix": "eslint --max-warnings 0 --fix .",
53
- "prepare": "",
54
- "prepublishOnly": "npm run build:dist-types && npm run build:dist-mjs",
55
- "prettier": "prettier --ignore-path .gitignore --list-different .",
56
- "prettier:fix": "prettier --ignore-path .gitignore --write .",
57
- "test": "npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"
58
- },
59
- "prettier": "@checkdigit/prettier-config",
60
- "jest": {
61
- "preset": "@checkdigit/jest-config"
62
- },
63
- "dependencies": {
64
- "@typescript-eslint/type-utils": "^8.23.0",
65
- "@typescript-eslint/utils": "^8.23.0",
66
- "http-status-codes": "^2.3.0",
67
- "ts-api-utils": "^2.0.1"
68
- },
69
- "devDependencies": {
70
- "@checkdigit/jest-config": "^6.0.2",
71
- "@checkdigit/prettier-config": "^6.1.0",
72
- "@checkdigit/typescript-config": "^9.0.0",
73
- "@eslint/js": "^9.19.0",
74
- "@types/eslint": "^9.6.1",
75
- "@types/eslint-config-prettier": "^6.11.3",
76
- "@typescript-eslint/parser": "^8.23.0",
77
- "@typescript-eslint/rule-tester": "^8.23.0",
78
- "eslint": "^9.19.0",
79
- "eslint-config-prettier": "^10.0.1",
80
- "eslint-import-resolver-typescript": "^3.7.0",
81
- "eslint-plugin-eslint-plugin": "^6.4.0",
82
- "eslint-plugin-import": "^2.31.0",
83
- "eslint-plugin-no-only-tests": "^3.3.0",
84
- "eslint-plugin-no-secrets": "^2.2.1",
85
- "eslint-plugin-node": "^11.1.0",
86
- "eslint-plugin-sonarjs": "1.0.4",
87
- "rimraf": "^6.0.1",
88
- "typescript-eslint": "^8.23.0"
89
- },
90
- "peerDependencies": {
91
- "eslint": ">=9 <10"
92
- },
93
- "engines": {
94
- "node": ">=20.17"
95
- }
96
- }
1
+ {"name":"@checkdigit/eslint-plugin","version":"7.12.0-PR.45-1e1c","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.23.0","@typescript-eslint/utils":"^8.23.0","http-status-codes":"^2.3.0","ts-api-utils":"^2.0.1"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^6.1.0","@checkdigit/typescript-config":"^9.0.0","@eslint/js":"^9.19.0","@types/eslint":"^9.6.1","@types/eslint-config-prettier":"^6.11.3","@typescript-eslint/parser":"^8.23.0","@typescript-eslint/rule-tester":"^8.23.0","eslint":"^9.19.0","eslint-config-prettier":"^10.0.1","eslint-import-resolver-typescript":"^3.7.0","eslint-plugin-eslint-plugin":"^6.4.0","eslint-plugin-import":"^2.31.0","eslint-plugin-no-only-tests":"^3.3.0","eslint-plugin-no-secrets":"^2.2.1","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"1.0.4","rimraf":"^6.0.1","typescript-eslint":"^8.23.0"},"peerDependencies":{"eslint":">=9 <10"},"engines":{"node":">=22.11"}}
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ import objectLiteralResponse from './object-literal-response.ts';
38
38
  import regexComment from './regular-expression-comment.ts';
39
39
  import requireAssertPredicateRejectsThrows from './require-assert-predicate-rejects-throws.ts';
40
40
  import requireStrictAssert from './require-strict-assert.ts';
41
+ import requireAssertMessage from './require-assert-message';
41
42
  import requireTsExtensionImportsExports from './require-ts-extension-imports-exports.ts';
42
43
 
43
44
  const rules: Record<string, TSESLint.LooseRuleDefinition> = {
@@ -47,6 +48,7 @@ const rules: Record<string, TSESLint.LooseRuleDefinition> = {
47
48
  'no-random-v4-uuid': noRandomV4UUID,
48
49
  'no-status-code-assert': noStatusCodeAssert,
49
50
  'no-uuid': noUuid,
51
+ 'require-assert-message': requireAssertMessage,
50
52
  'require-strict-assert': requireStrictAssert,
51
53
  'require-ts-extension-imports-exports': requireTsExtensionImportsExports,
52
54
  'no-test-import': noTestImport,
@@ -84,6 +86,7 @@ const configs: Record<string, TSESLint.FlatConfig.Config[]> = {
84
86
  '@checkdigit/no-random-v4-uuid': 'error',
85
87
  '@checkdigit/no-status-code-assert': 'error',
86
88
  '@checkdigit/no-uuid': 'error',
89
+ '@checkdigit/require-assert-message': 'error',
87
90
  '@checkdigit/require-strict-assert': 'error',
88
91
  '@checkdigit/require-ts-extension-imports-exports': 'error',
89
92
  '@checkdigit/no-wallaby-comment': 'error',
@@ -120,6 +123,7 @@ const configs: Record<string, TSESLint.FlatConfig.Config[]> = {
120
123
  '@checkdigit/no-random-v4-uuid': 'error',
121
124
  '@checkdigit/no-status-code-assert': 'error',
122
125
  '@checkdigit/no-uuid': 'error',
126
+ '@checkdigit/require-assert-message': 'error',
123
127
  '@checkdigit/require-strict-assert': 'error',
124
128
  '@checkdigit/require-ts-extension-imports-exports': 'error',
125
129
  '@checkdigit/no-wallaby-comment': 'off',
@@ -0,0 +1,99 @@
1
+ // require-assert-message.ts
2
+
3
+ /*
4
+ * Copyright (c) 2022-2025 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import { strict as assert } from 'node:assert';
10
+ import { ESLintUtils, TSESLint } from '@typescript-eslint/utils';
11
+ import { TSESTree } from '@typescript-eslint/types';
12
+ import getDocumentationUrl from './get-documentation-url.ts';
13
+
14
+ export const ruleId = 'require-assert-message';
15
+ const MISSING_ASSERT_MESSAGE = 'MISSING_ASSERT_MESSAGE';
16
+
17
+ const methodsRequiringMessage = Object.keys(assert).filter((key) => typeof (assert as never)[key] === 'function');
18
+
19
+ const createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
20
+ const rule: TSESLint.RuleModule<string, unknown[]> = createRule({
21
+ name: ruleId,
22
+ meta: {
23
+ type: 'problem',
24
+ docs: {
25
+ description: 'Validate that message argument is always supplied to node:assert methods',
26
+ },
27
+ schema: [],
28
+ messages: {
29
+ [MISSING_ASSERT_MESSAGE]: 'Missing message argument in {{methodName}}() method.',
30
+ },
31
+ },
32
+ defaultOptions: [],
33
+ create(context) {
34
+ let assertAlias = 'assert';
35
+ const parserServices = ESLintUtils.getParserServices(context);
36
+ const checker = parserServices.program.getTypeChecker();
37
+ const messageIndexCache: Record<string, number> = {};
38
+
39
+ return {
40
+ ImportDeclaration(node: TSESTree.ImportDeclaration) {
41
+ if (node.source.value === 'node:assert') {
42
+ const specifier = node.specifiers.find(
43
+ (importSpecifier) =>
44
+ importSpecifier.type === TSESTree.AST_NODE_TYPES.ImportDefaultSpecifier ||
45
+ importSpecifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier,
46
+ );
47
+ if (specifier) {
48
+ assertAlias = specifier.local.name;
49
+ }
50
+ }
51
+ },
52
+ CallExpression(node: TSESTree.CallExpression) {
53
+ const callee = node.callee;
54
+ if (
55
+ callee.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
56
+ callee.object.type === TSESTree.AST_NODE_TYPES.Identifier &&
57
+ callee.property.type === TSESTree.AST_NODE_TYPES.Identifier
58
+ ) {
59
+ const objectName = callee.object.name;
60
+ const methodName = callee.property.name;
61
+
62
+ if (objectName === assertAlias && methodsRequiringMessage.includes(methodName)) {
63
+ if (!(methodName in messageIndexCache)) {
64
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
65
+ const signature = checker.getResolvedSignature(tsNode);
66
+ const messageParameterIndex = signature?.getParameters().findIndex((param) => param.name === 'message');
67
+ messageIndexCache[methodName] = messageParameterIndex ?? 2;
68
+ }
69
+
70
+ const messageIndex = messageIndexCache[methodName];
71
+ if (messageIndex !== undefined && node.arguments.length <= messageIndex) {
72
+ context.report({
73
+ node,
74
+ messageId: MISSING_ASSERT_MESSAGE,
75
+ data: {
76
+ methodName,
77
+ },
78
+ });
79
+ }
80
+ }
81
+ } else if (
82
+ callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
83
+ callee.name === assertAlias &&
84
+ node.arguments.length < 2
85
+ ) {
86
+ context.report({
87
+ node,
88
+ messageId: MISSING_ASSERT_MESSAGE,
89
+ data: {
90
+ methodName: 'assert',
91
+ },
92
+ });
93
+ }
94
+ },
95
+ };
96
+ },
97
+ });
98
+
99
+ export default rule;