@checkdigit/eslint-plugin 5.0.0-PR.36-f31c → 5.0.0-PR.36-40a0

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.
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/file-path-comment.ts
21
+ var file_path_comment_exports = {};
22
+ __export(file_path_comment_exports, {
23
+ default: () => file_path_comment_default
24
+ });
25
+ module.exports = __toCommonJS(file_path_comment_exports);
26
+ var file_path_comment_default = {
27
+ meta: {
28
+ type: "suggestion",
29
+ docs: {
30
+ description: "Validate that first line of file is a path to the file",
31
+ url: "https://github.com/checkdigit/eslint-plugin"
32
+ },
33
+ fixable: "code"
34
+ },
35
+ create(context) {
36
+ const firstLine = context.getSourceCode().getLines()[0];
37
+ const expectedPath = context.getFilename().split("src/")[1];
38
+ if (expectedPath === void 0) {
39
+ return {};
40
+ }
41
+ if (!firstLine.startsWith("//")) {
42
+ if (firstLine.startsWith("/*")) {
43
+ context.report({
44
+ loc: {
45
+ start: {
46
+ line: 0,
47
+ column: 0
48
+ },
49
+ end: {
50
+ line: 0,
51
+ column: 1
52
+ }
53
+ },
54
+ message: "first line cannot be a block comment",
55
+ fix(fixer) {
56
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}
57
+
58
+ `);
59
+ }
60
+ });
61
+ } else {
62
+ context.report({
63
+ loc: {
64
+ start: {
65
+ line: 0,
66
+ column: 0
67
+ },
68
+ end: {
69
+ line: 0,
70
+ column: 1
71
+ }
72
+ },
73
+ message: "first line is not a comment with the file path",
74
+ fix(fixer) {
75
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}
76
+
77
+ `);
78
+ }
79
+ });
80
+ }
81
+ } else {
82
+ const actualComment = firstLine.split("// ")[1];
83
+ if (expectedPath !== actualComment) {
84
+ context.report({
85
+ loc: {
86
+ start: {
87
+ line: 0,
88
+ column: 0
89
+ },
90
+ end: {
91
+ line: 0,
92
+ column: 1
93
+ }
94
+ },
95
+ message: "first line is a comment but is not a path to the file",
96
+ fix(fixer) {
97
+ return fixer.replaceTextRange([0, firstLine.length], `// ${expectedPath}`);
98
+ }
99
+ });
100
+ }
101
+ }
102
+ return {};
103
+ }
104
+ };
105
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZpbGUtcGF0aC1jb21tZW50LnRzIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBVUEsSUFBTyw0QkFBUTtBQUFBLEVBQ2IsTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLE1BQ2IsS0FBSztBQUFBLElBQ1A7QUFBQSxJQUNBLFNBQVM7QUFBQSxFQUNYO0FBQUEsRUFDQSxPQUFPLFNBQVM7QUFDZCxVQUFNLFlBQVksUUFBUSxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUM7QUFDdEQsVUFBTSxlQUFlLFFBQVEsWUFBWSxFQUFFLE1BQU0sTUFBTSxFQUFFLENBQUM7QUFFMUQsUUFBSSxpQkFBaUIsUUFBVztBQUM5QixhQUFPLENBQUM7QUFBQSxJQUNWO0FBRUEsUUFBSSxDQUFDLFVBQVUsV0FBVyxJQUFJLEdBQUc7QUFDL0IsVUFBSSxVQUFVLFdBQVcsSUFBSSxHQUFHO0FBQzlCLGdCQUFRLE9BQU87QUFBQSxVQUNiLEtBQUs7QUFBQSxZQUNILE9BQU87QUFBQSxjQUNMLE1BQU07QUFBQSxjQUNOLFFBQVE7QUFBQSxZQUNWO0FBQUEsWUFDQSxLQUFLO0FBQUEsY0FDSCxNQUFNO0FBQUEsY0FDTixRQUFRO0FBQUEsWUFDVjtBQUFBLFVBQ0Y7QUFBQSxVQUNBLFNBQVM7QUFBQSxVQUNULElBQUksT0FBdUI7QUFDekIsbUJBQU8sTUFBTSxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLFlBQVk7QUFBQTtBQUFBLENBQU07QUFBQSxVQUNyRTtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0gsT0FBTztBQUNMLGdCQUFRLE9BQU87QUFBQSxVQUNiLEtBQUs7QUFBQSxZQUNILE9BQU87QUFBQSxjQUNMLE1BQU07QUFBQSxjQUNOLFFBQVE7QUFBQSxZQUNWO0FBQUEsWUFDQSxLQUFLO0FBQUEsY0FDSCxNQUFNO0FBQUEsY0FDTixRQUFRO0FBQUEsWUFDVjtBQUFBLFVBQ0Y7QUFBQSxVQUNBLFNBQVM7QUFBQSxVQUNULElBQUksT0FBdUI7QUFDekIsbUJBQU8sTUFBTSxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLFlBQVk7QUFBQTtBQUFBLENBQU07QUFBQSxVQUNyRTtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQSxJQUNGLE9BQU87QUFDTCxZQUFNLGdCQUFnQixVQUFVLE1BQU0sS0FBSyxFQUFFLENBQUM7QUFDOUMsVUFBSSxpQkFBaUIsZUFBZTtBQUNsQyxnQkFBUSxPQUFPO0FBQUEsVUFDYixLQUFLO0FBQUEsWUFDSCxPQUFPO0FBQUEsY0FDTCxNQUFNO0FBQUEsY0FDTixRQUFRO0FBQUEsWUFDVjtBQUFBLFlBQ0EsS0FBSztBQUFBLGNBQ0gsTUFBTTtBQUFBLGNBQ04sUUFBUTtBQUFBLFlBQ1Y7QUFBQSxVQUNGO0FBQUEsVUFDQSxTQUFTO0FBQUEsVUFDVCxJQUFJLE9BQXVCO0FBQ3pCLG1CQUFPLE1BQU0saUJBQWlCLENBQUMsR0FBRyxVQUFVLE1BQU0sR0FBRyxNQUFNLFlBQVksRUFBRTtBQUFBLFVBQzNFO0FBQUEsUUFDRixDQUFDO0FBQUEsTUFDSDtBQUFBLElBQ0Y7QUFFQSxXQUFPLENBQUM7QUFBQSxFQUNWO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ default: () => src_default
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+ var import_file_path_comment = __toESM(require("./file-path-comment.cjs"), 1);
37
+ var import_no_card_numbers = __toESM(require("./no-card-numbers.cjs"), 1);
38
+ var import_no_uuid = __toESM(require("./no-uuid.cjs"), 1);
39
+ var src_default = {
40
+ rules: {
41
+ "file-path-comment": import_file_path_comment.default,
42
+ "no-card-numbers": import_no_card_numbers.default,
43
+ "no-uuid": import_no_uuid.default
44
+ },
45
+ configs: {
46
+ all: {
47
+ rules: {
48
+ "@checkdigit/no-card-numbers": "error",
49
+ "@checkdigit/file-path-comment": "error",
50
+ "@checkdigit/no-uuid": "error"
51
+ }
52
+ },
53
+ recommended: {
54
+ rules: {
55
+ "@checkdigit/no-card-numbers": "error",
56
+ "@checkdigit/file-path-comment": "off",
57
+ "@checkdigit/no-uuid": "error"
58
+ }
59
+ }
60
+ }
61
+ };
62
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQVFBLCtCQUE0QjtBQUM1Qiw2QkFBMEI7QUFDMUIscUJBQW1CO0FBRW5CLElBQU8sY0FBUTtBQUFBLEVBQ2IsT0FBTztBQUFBLElBQ0wscUJBQXFCLHlCQUFBQTtBQUFBLElBQ3JCLG1CQUFtQix1QkFBQUM7QUFBQSxJQUNuQixXQUFXLGVBQUFDO0FBQUEsRUFDYjtBQUFBLEVBQ0EsU0FBUztBQUFBLElBQ1AsS0FBSztBQUFBLE1BQ0gsT0FBTztBQUFBLFFBQ0wsK0JBQStCO0FBQUEsUUFDL0IsaUNBQWlDO0FBQUEsUUFDakMsdUJBQXVCO0FBQUEsTUFDekI7QUFBQSxJQUNGO0FBQUEsSUFDQSxhQUFhO0FBQUEsTUFDWCxPQUFPO0FBQUEsUUFDTCwrQkFBK0I7QUFBQSxRQUMvQixpQ0FBaUM7QUFBQSxRQUNqQyx1QkFBdUI7QUFBQSxNQUN6QjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0Y7IiwKICAibmFtZXMiOiBbImZpbGVQYXRoQ29tbWVudCIsICJub0NhcmROdW1iZXJzIiwgIm5vVXVpZCJdCn0K
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/no-card-numbers.ts
21
+ var no_card_numbers_exports = {};
22
+ __export(no_card_numbers_exports, {
23
+ default: () => no_card_numbers_default
24
+ });
25
+ module.exports = __toCommonJS(no_card_numbers_exports);
26
+ var CARD_NUMBER_FOUND = "CARD_NUMBER_FOUND";
27
+ var CARD_NUMBERS_FOUND = "CARD_NUMBERS_FOUND";
28
+ var cardNumberRegex = /\d{15,19}/gmu;
29
+ var allowCardNumbers = [
30
+ "4111111111111111",
31
+ "111111111111111",
32
+ "000000000000000",
33
+ "0000000000000000",
34
+ "00000000000000000",
35
+ "000000000000000000",
36
+ "0000000000000000000"
37
+ ];
38
+ function luhnCheck(cardNumber) {
39
+ return cardNumber.split("").reverse().map((digit) => parseInt(digit, 10)).reduce((previousValue, currentValue, index) => {
40
+ let value = currentValue;
41
+ if (index % 2 === 1) {
42
+ value *= 2;
43
+ if (value > 9) {
44
+ value = value % 10 + 1;
45
+ }
46
+ }
47
+ return previousValue + value;
48
+ }, 0) % 10 === 0;
49
+ }
50
+ function checkForCardNumbers(value, context, node, loc) {
51
+ const matches = value.match(cardNumberRegex);
52
+ if (matches === null) {
53
+ return;
54
+ }
55
+ const cardNumbers = matches.filter(
56
+ (match) => luhnCheck(match) && allowCardNumbers.indexOf(match) === -1 && // any 16-digit number that begins with 0-1 or 7-9 is not a valid card number
57
+ match[0] !== "0" && match[0] !== "1" && match[0] !== "7" && match[0] !== "8" && match[0] !== "9"
58
+ );
59
+ if (cardNumbers.length === 1) {
60
+ if (node !== void 0) {
61
+ context.report({
62
+ messageId: CARD_NUMBER_FOUND,
63
+ data: {
64
+ number: cardNumbers[0]
65
+ },
66
+ node
67
+ });
68
+ } else if (loc !== void 0) {
69
+ context.report({
70
+ messageId: CARD_NUMBER_FOUND,
71
+ data: {
72
+ number: cardNumbers[0]
73
+ },
74
+ loc: {
75
+ start: loc.start,
76
+ end: loc.end
77
+ }
78
+ });
79
+ }
80
+ } else if (cardNumbers.length > 1) {
81
+ if (node !== void 0) {
82
+ context.report({
83
+ messageId: CARD_NUMBERS_FOUND,
84
+ data: {
85
+ numbers: matches.join(", ")
86
+ },
87
+ node
88
+ });
89
+ } else if (loc !== void 0) {
90
+ context.report({
91
+ messageId: CARD_NUMBERS_FOUND,
92
+ data: {
93
+ numbers: matches.join(", ")
94
+ },
95
+ loc: {
96
+ start: loc.start,
97
+ end: loc.end
98
+ }
99
+ });
100
+ }
101
+ }
102
+ }
103
+ var no_card_numbers_default = {
104
+ meta: {
105
+ type: "problem",
106
+ docs: {
107
+ description: "Detects if a luhn passing card number",
108
+ url: "https://github.com/checkdigit/eslint-plugin"
109
+ },
110
+ messages: {
111
+ [CARD_NUMBER_FOUND]: `Valid card number: "{{ number }}"`,
112
+ [CARD_NUMBERS_FOUND]: `Multiple valid card numbers found: "{{ numbers }}"`
113
+ }
114
+ },
115
+ create(context) {
116
+ const sourceCode = context.getSourceCode();
117
+ const comments = sourceCode.getAllComments();
118
+ comments.forEach((comment) => {
119
+ if (comment.loc !== void 0 && comment.loc !== null) {
120
+ checkForCardNumbers(comment.value, context, void 0, comment.loc);
121
+ }
122
+ });
123
+ return {
124
+ Literal(node) {
125
+ if (node.value === void 0) {
126
+ return;
127
+ }
128
+ if (typeof node.value !== "string" && typeof node.value !== "number") {
129
+ return;
130
+ }
131
+ const value = `${node.value}`;
132
+ checkForCardNumbers(value, context, node);
133
+ },
134
+ TemplateElement(node) {
135
+ if (!node.value) {
136
+ return;
137
+ }
138
+ if (typeof node.value.cooked !== "string") {
139
+ return;
140
+ }
141
+ checkForCardNumbers(node.value.cooked, context, node);
142
+ }
143
+ };
144
+ }
145
+ };
146
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLWNhcmQtbnVtYmVycy50cyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQVdBLElBQU0sb0JBQW9CO0FBQzFCLElBQU0scUJBQXFCO0FBQzNCLElBQU0sa0JBQWtCO0FBQ3hCLElBQU0sbUJBQW1CO0FBQUEsRUFDdkI7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFDRjtBQUVBLFNBQVMsVUFBVSxZQUFvQjtBQUNyQyxTQUNFLFdBQ0csTUFBTSxFQUFFLEVBQ1IsUUFBUSxFQUNSLElBQUksQ0FBQyxVQUFVLFNBQVMsT0FBTyxFQUFFLENBQUMsRUFDbEMsT0FBTyxDQUFDLGVBQWUsY0FBYyxVQUFVO0FBQzlDLFFBQUksUUFBUTtBQUNaLFFBQUksUUFBUSxNQUFNLEdBQUc7QUFDbkIsZUFBUztBQUVULFVBQUksUUFBUSxHQUFHO0FBQ2IsZ0JBQVMsUUFBUSxLQUFNO0FBQUEsTUFDekI7QUFBQSxJQUNGO0FBQ0EsV0FBTyxnQkFBZ0I7QUFBQSxFQUN6QixHQUFHLENBQUMsSUFDSixPQUNGO0FBRUo7QUFFQSxTQUFTLG9CQUFvQixPQUFlLFNBQTJCLE1BQWEsS0FBc0I7QUFDeEcsUUFBTSxVQUFVLE1BQU0sTUFBTSxlQUFlO0FBQzNDLE1BQUksWUFBWSxNQUFNO0FBQ3BCO0FBQUEsRUFDRjtBQUNBLFFBQU0sY0FBYyxRQUFRO0FBQUEsSUFDMUIsQ0FBQyxVQUNDLFVBQVUsS0FBSyxLQUNmLGlCQUFpQixRQUFRLEtBQUssTUFBTTtBQUFBLElBRXBDLE1BQU0sQ0FBQyxNQUFNLE9BQ2IsTUFBTSxDQUFDLE1BQU0sT0FDYixNQUFNLENBQUMsTUFBTSxPQUNiLE1BQU0sQ0FBQyxNQUFNLE9BQ2IsTUFBTSxDQUFDLE1BQU07QUFBQSxFQUNqQjtBQUNBLE1BQUksWUFBWSxXQUFXLEdBQUc7QUFDNUIsUUFB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
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/no-uuid.ts
21
+ var no_uuid_exports = {};
22
+ __export(no_uuid_exports, {
23
+ default: () => no_uuid_default
24
+ });
25
+ module.exports = __toCommonJS(no_uuid_exports);
26
+ var UUID_FOUND = "UUID_FOUND";
27
+ var UUIDS_FOUND = "UUIDS_FOUND";
28
+ var 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;
29
+ function checkForUuid(value, context, node, loc) {
30
+ const matches = value.match(uuidRegex);
31
+ if (matches === null) {
32
+ return;
33
+ }
34
+ if (matches.length === 1) {
35
+ if (node !== void 0) {
36
+ context.report({
37
+ messageId: UUID_FOUND,
38
+ data: {
39
+ uuid: matches[0] ?? ""
40
+ },
41
+ node
42
+ });
43
+ } else if (loc !== void 0) {
44
+ context.report({
45
+ messageId: UUID_FOUND,
46
+ data: {
47
+ uuid: matches[0] ?? ""
48
+ },
49
+ loc: {
50
+ start: loc.start,
51
+ end: loc.end
52
+ }
53
+ });
54
+ }
55
+ } else if (matches.length > 1) {
56
+ if (node !== void 0) {
57
+ context.report({
58
+ messageId: UUIDS_FOUND,
59
+ data: {
60
+ uuids: matches.join(", ")
61
+ },
62
+ node
63
+ });
64
+ } else if (loc !== void 0) {
65
+ context.report({
66
+ messageId: UUIDS_FOUND,
67
+ data: {
68
+ uuids: matches.join(", ")
69
+ },
70
+ loc: {
71
+ start: loc.start,
72
+ end: loc.end
73
+ }
74
+ });
75
+ }
76
+ }
77
+ }
78
+ var no_uuid_default = {
79
+ meta: {
80
+ type: "problem",
81
+ docs: {
82
+ description: "Detects if a string literal contains a UUID",
83
+ url: "https://github.com/checkdigit/eslint-plugin"
84
+ },
85
+ messages: {
86
+ [UUID_FOUND]: `UUID found: "{{ uuid }}"`,
87
+ [UUIDS_FOUND]: `Multiple UUIDs found: "{{ uuids }}"`
88
+ }
89
+ },
90
+ create(context) {
91
+ const sourceCode = context.getSourceCode();
92
+ const comments = sourceCode.getAllComments();
93
+ comments.forEach((comment) => {
94
+ if (comment.loc !== void 0 && comment.loc !== null) {
95
+ checkForUuid(comment.value, context, void 0, comment.loc);
96
+ }
97
+ });
98
+ return {
99
+ Literal(node) {
100
+ if (node.value === void 0) {
101
+ return;
102
+ }
103
+ if (typeof node.value !== "string") {
104
+ return;
105
+ }
106
+ const value = `${node.value}`;
107
+ checkForUuid(value, context, node);
108
+ },
109
+ TemplateElement(node) {
110
+ if (!node.value) {
111
+ return;
112
+ }
113
+ if (typeof node.value.cooked !== "string") {
114
+ return;
115
+ }
116
+ checkForUuid(node.value.cooked, context, node);
117
+ }
118
+ };
119
+ }
120
+ };
121
+ //# sourceMappingURL=data:application/json;base64,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
@@ -0,0 +1,84 @@
1
+ // src/file-path-comment.ts
2
+ var file_path_comment_default = {
3
+ meta: {
4
+ type: "suggestion",
5
+ docs: {
6
+ description: "Validate that first line of file is a path to the file",
7
+ url: "https://github.com/checkdigit/eslint-plugin"
8
+ },
9
+ fixable: "code"
10
+ },
11
+ create(context) {
12
+ const firstLine = context.getSourceCode().getLines()[0];
13
+ const expectedPath = context.getFilename().split("src/")[1];
14
+ if (expectedPath === void 0) {
15
+ return {};
16
+ }
17
+ if (!firstLine.startsWith("//")) {
18
+ if (firstLine.startsWith("/*")) {
19
+ context.report({
20
+ loc: {
21
+ start: {
22
+ line: 0,
23
+ column: 0
24
+ },
25
+ end: {
26
+ line: 0,
27
+ column: 1
28
+ }
29
+ },
30
+ message: "first line cannot be a block comment",
31
+ fix(fixer) {
32
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}
33
+
34
+ `);
35
+ }
36
+ });
37
+ } else {
38
+ context.report({
39
+ loc: {
40
+ start: {
41
+ line: 0,
42
+ column: 0
43
+ },
44
+ end: {
45
+ line: 0,
46
+ column: 1
47
+ }
48
+ },
49
+ message: "first line is not a comment with the file path",
50
+ fix(fixer) {
51
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}
52
+
53
+ `);
54
+ }
55
+ });
56
+ }
57
+ } else {
58
+ const actualComment = firstLine.split("// ")[1];
59
+ if (expectedPath !== actualComment) {
60
+ context.report({
61
+ loc: {
62
+ start: {
63
+ line: 0,
64
+ column: 0
65
+ },
66
+ end: {
67
+ line: 0,
68
+ column: 1
69
+ }
70
+ },
71
+ message: "first line is a comment but is not a path to the file",
72
+ fix(fixer) {
73
+ return fixer.replaceTextRange([0, firstLine.length], `// ${expectedPath}`);
74
+ }
75
+ });
76
+ }
77
+ }
78
+ return {};
79
+ }
80
+ };
81
+ export {
82
+ file_path_comment_default as default
83
+ };
84
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZpbGUtcGF0aC1jb21tZW50LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVVBLElBQU8sNEJBQVE7QUFBQSxFQUNiLE1BQU07QUFBQSxJQUNKLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxNQUNKLGFBQWE7QUFBQSxNQUNiLEtBQUs7QUFBQSxJQUNQO0FBQUEsSUFDQSxTQUFTO0FBQUEsRUFDWDtBQUFBLEVBQ0EsT0FBTyxTQUFTO0FBQ2QsVUFBTSxZQUFZLFFBQVEsY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQ3RELFVBQU0sZUFBZSxRQUFRLFlBQVksRUFBRSxNQUFNLE1BQU0sRUFBRSxDQUFDO0FBRTFELFFBQUksaUJBQWlCLFFBQVc7QUFDOUIsYUFBTyxDQUFDO0FBQUEsSUFDVjtBQUVBLFFBQUksQ0FBQyxVQUFVLFdBQVcsSUFBSSxHQUFHO0FBQy9CLFVBQUksVUFBVSxXQUFXLElBQUksR0FBRztBQUM5QixnQkFBUSxPQUFPO0FBQUEsVUFDYixLQUFLO0FBQUEsWUFDSCxPQUFPO0FBQUEsY0FDTCxNQUFNO0FBQUEsY0FDTixRQUFRO0FBQUEsWUFDVjtBQUFBLFlBQ0EsS0FBSztBQUFBLGNBQ0gsTUFBTTtBQUFBLGNBQ04sUUFBUTtBQUFBLFlBQ1Y7QUFBQSxVQUNGO0FBQUEsVUFDQSxTQUFTO0FBQUEsVUFDVCxJQUFJLE9BQXVCO0FBQ3pCLG1CQUFPLE1BQU0sc0JBQXNCLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxZQUFZO0FBQUE7QUFBQSxDQUFNO0FBQUEsVUFDckU7QUFBQSxRQUNGLENBQUM7QUFBQSxNQUNILE9BQU87QUFDTCxnQkFBUSxPQUFPO0FBQUEsVUFDYixLQUFLO0FBQUEsWUFDSCxPQUFPO0FBQUEsY0FDTCxNQUFNO0FBQUEsY0FDTixRQUFRO0FBQUEsWUFDVjtBQUFBLFlBQ0EsS0FBSztBQUFBLGNBQ0gsTUFBTTtBQUFBLGNBQ04sUUFBUTtBQUFBLFlBQ1Y7QUFBQSxVQUNGO0FBQUEsVUFDQSxTQUFTO0FBQUEsVUFDVCxJQUFJLE9BQXVCO0FBQ3pCLG1CQUFPLE1BQU0sc0JBQXNCLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxZQUFZO0FBQUE7QUFBQSxDQUFNO0FBQUEsVUFDckU7QUFBQSxRQUNGLENBQUM7QUFBQSxNQUNIO0FBQUEsSUFDRixPQUFPO0FBQ0wsWUFBTSxnQkFBZ0IsVUFBVSxNQUFNLEtBQUssRUFBRSxDQUFDO0FBQzlDLFVBQUksaUJBQWlCLGVBQWU7QUFDbEMsZ0JBQVEsT0FBTztBQUFBLFVBQ2IsS0FBSztBQUFBLFlBQ0gsT0FBTztBQUFBLGNBQ0wsTUFBTTtBQUFBLGNBQ04sUUFBUTtBQUFBLFlBQ1Y7QUFBQSxZQUNBLEtBQUs7QUFBQSxjQUNILE1BQU07QUFBQSxjQUNOLFFBQVE7QUFBQSxZQUNWO0FBQUEsVUFDRjtBQUFBLFVBQ0EsU0FBUztBQUFBLFVBQ1QsSUFBSSxPQUF1QjtBQUN6QixtQkFBTyxNQUFNLGlCQUFpQixDQUFDLEdBQUcsVUFBVSxNQUFNLEdBQUcsTUFBTSxZQUFZLEVBQUU7QUFBQSxVQUMzRTtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQSxJQUNGO0FBRUEsV0FBTyxDQUFDO0FBQUEsRUFDVjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,31 @@
1
+ // src/index.ts
2
+ import filePathComment from "./file-path-comment.mjs";
3
+ import noCardNumbers from "./no-card-numbers.mjs";
4
+ import noUuid from "./no-uuid.mjs";
5
+ var src_default = {
6
+ rules: {
7
+ "file-path-comment": filePathComment,
8
+ "no-card-numbers": noCardNumbers,
9
+ "no-uuid": noUuid
10
+ },
11
+ configs: {
12
+ all: {
13
+ rules: {
14
+ "@checkdigit/no-card-numbers": "error",
15
+ "@checkdigit/file-path-comment": "error",
16
+ "@checkdigit/no-uuid": "error"
17
+ }
18
+ },
19
+ recommended: {
20
+ rules: {
21
+ "@checkdigit/no-card-numbers": "error",
22
+ "@checkdigit/file-path-comment": "off",
23
+ "@checkdigit/no-uuid": "error"
24
+ }
25
+ }
26
+ }
27
+ };
28
+ export {
29
+ src_default as default
30
+ };
31
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLE9BQU8scUJBQXFCO0FBQzVCLE9BQU8sbUJBQW1CO0FBQzFCLE9BQU8sWUFBWTtBQUVuQixJQUFPLGNBQVE7QUFBQSxFQUNiLE9BQU87QUFBQSxJQUNMLHFCQUFxQjtBQUFBLElBQ3JCLG1CQUFtQjtBQUFBLElBQ25CLFdBQVc7QUFBQSxFQUNiO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFDUCxLQUFLO0FBQUEsTUFDSCxPQUFPO0FBQUEsUUFDTCwrQkFBK0I7QUFBQSxRQUMvQixpQ0FBaUM7QUFBQSxRQUNqQyx1QkFBdUI7QUFBQSxNQUN6QjtBQUFBLElBQ0Y7QUFBQSxJQUNBLGFBQWE7QUFBQSxNQUNYLE9BQU87QUFBQSxRQUNMLCtCQUErQjtBQUFBLFFBQy9CLGlDQUFpQztBQUFBLFFBQ2pDLHVCQUF1QjtBQUFBLE1BQ3pCO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,125 @@
1
+ // src/no-card-numbers.ts
2
+ var CARD_NUMBER_FOUND = "CARD_NUMBER_FOUND";
3
+ var CARD_NUMBERS_FOUND = "CARD_NUMBERS_FOUND";
4
+ var cardNumberRegex = /\d{15,19}/gmu;
5
+ var allowCardNumbers = [
6
+ "4111111111111111",
7
+ "111111111111111",
8
+ "000000000000000",
9
+ "0000000000000000",
10
+ "00000000000000000",
11
+ "000000000000000000",
12
+ "0000000000000000000"
13
+ ];
14
+ function luhnCheck(cardNumber) {
15
+ return cardNumber.split("").reverse().map((digit) => parseInt(digit, 10)).reduce((previousValue, currentValue, index) => {
16
+ let value = currentValue;
17
+ if (index % 2 === 1) {
18
+ value *= 2;
19
+ if (value > 9) {
20
+ value = value % 10 + 1;
21
+ }
22
+ }
23
+ return previousValue + value;
24
+ }, 0) % 10 === 0;
25
+ }
26
+ function checkForCardNumbers(value, context, node, loc) {
27
+ const matches = value.match(cardNumberRegex);
28
+ if (matches === null) {
29
+ return;
30
+ }
31
+ const cardNumbers = matches.filter(
32
+ (match) => luhnCheck(match) && allowCardNumbers.indexOf(match) === -1 && // any 16-digit number that begins with 0-1 or 7-9 is not a valid card number
33
+ match[0] !== "0" && match[0] !== "1" && match[0] !== "7" && match[0] !== "8" && match[0] !== "9"
34
+ );
35
+ if (cardNumbers.length === 1) {
36
+ if (node !== void 0) {
37
+ context.report({
38
+ messageId: CARD_NUMBER_FOUND,
39
+ data: {
40
+ number: cardNumbers[0]
41
+ },
42
+ node
43
+ });
44
+ } else if (loc !== void 0) {
45
+ context.report({
46
+ messageId: CARD_NUMBER_FOUND,
47
+ data: {
48
+ number: cardNumbers[0]
49
+ },
50
+ loc: {
51
+ start: loc.start,
52
+ end: loc.end
53
+ }
54
+ });
55
+ }
56
+ } else if (cardNumbers.length > 1) {
57
+ if (node !== void 0) {
58
+ context.report({
59
+ messageId: CARD_NUMBERS_FOUND,
60
+ data: {
61
+ numbers: matches.join(", ")
62
+ },
63
+ node
64
+ });
65
+ } else if (loc !== void 0) {
66
+ context.report({
67
+ messageId: CARD_NUMBERS_FOUND,
68
+ data: {
69
+ numbers: matches.join(", ")
70
+ },
71
+ loc: {
72
+ start: loc.start,
73
+ end: loc.end
74
+ }
75
+ });
76
+ }
77
+ }
78
+ }
79
+ var no_card_numbers_default = {
80
+ meta: {
81
+ type: "problem",
82
+ docs: {
83
+ description: "Detects if a luhn passing card number",
84
+ url: "https://github.com/checkdigit/eslint-plugin"
85
+ },
86
+ messages: {
87
+ [CARD_NUMBER_FOUND]: `Valid card number: "{{ number }}"`,
88
+ [CARD_NUMBERS_FOUND]: `Multiple valid card numbers found: "{{ numbers }}"`
89
+ }
90
+ },
91
+ create(context) {
92
+ const sourceCode = context.getSourceCode();
93
+ const comments = sourceCode.getAllComments();
94
+ comments.forEach((comment) => {
95
+ if (comment.loc !== void 0 && comment.loc !== null) {
96
+ checkForCardNumbers(comment.value, context, void 0, comment.loc);
97
+ }
98
+ });
99
+ return {
100
+ Literal(node) {
101
+ if (node.value === void 0) {
102
+ return;
103
+ }
104
+ if (typeof node.value !== "string" && typeof node.value !== "number") {
105
+ return;
106
+ }
107
+ const value = `${node.value}`;
108
+ checkForCardNumbers(value, context, node);
109
+ },
110
+ TemplateElement(node) {
111
+ if (!node.value) {
112
+ return;
113
+ }
114
+ if (typeof node.value.cooked !== "string") {
115
+ return;
116
+ }
117
+ checkForCardNumbers(node.value.cooked, context, node);
118
+ }
119
+ };
120
+ }
121
+ };
122
+ export {
123
+ no_card_numbers_default as default
124
+ };
125
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLWNhcmQtbnVtYmVycy50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFXQSxJQUFNLG9CQUFvQjtBQUMxQixJQUFNLHFCQUFxQjtBQUMzQixJQUFNLGtCQUFrQjtBQUN4QixJQUFNLG1CQUFtQjtBQUFBLEVBQ3ZCO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0Y7QUFFQSxTQUFTLFVBQVUsWUFBb0I7QUFDckMsU0FDRSxXQUNHLE1BQU0sRUFBRSxFQUNSLFFBQVEsRUFDUixJQUFJLENBQUMsVUFBVSxTQUFTLE9BQU8sRUFBRSxDQUFDLEVBQ2xDLE9BQU8sQ0FBQyxlQUFlLGNBQWMsVUFBVTtBQUM5QyxRQUFJLFFBQVE7QUFDWixRQUFJLFFBQVEsTUFBTSxHQUFHO0FBQ25CLGVBQVM7QUFFVCxVQUFJLFFBQVEsR0FBRztBQUNiLGdCQUFTLFFBQVEsS0FBTTtBQUFBLE1BQ3pCO0FBQUEsSUFDRjtBQUNBLFdBQU8sZ0JBQWdCO0FBQUEsRUFDekIsR0FBRyxDQUFDLElBQ0osT0FDRjtBQUVKO0FBRUEsU0FBUyxvQkFBb0IsT0FBZSxTQUEyQixNQUFhLEtBQXNCO0FBQ3hHLFFBQU0sVUFBVSxNQUFNLE1BQU0sZUFBZTtBQUMzQyxNQUFJLFlBQVksTUFBTTtBQUNwQjtBQUFBLEVBQ0Y7QUFDQSxRQUFNLGNBQWMsUUFBUTtBQUFBLElBQzFCLENBQUMsVUFDQyxVQUFVLEtBQUssS0FDZixpQkFBaUIsUUFBUSxLQUFLLE1BQU07QUFBQSxJQUVwQyxNQUFNLENBQUMsTUFBTSxPQUNiLE1BQU0sQ0FBQyxNQUFNLE9BQ2IsTUFBTSxDQUFDLE1BQU0sT0FDYixNQUFNLENBQUMsTUFBTSxPQUNiLE1BQU0sQ0FBQyxNQUFNO0FBQUEsRUFDakI7QUFDQSxNQUFJLFlBQVksV0FBVyxHQUFHO0FBQzVCLFFBQUksU0FBUyxRQUFXO0FBQ3RCLGNBQVEsT0FBTztBQUFBLFFBQ2IsV0FBVztBQUFBLFFBQ1gsTUFBTTtBQUFBLFVBQ0osUUFBUSxZQUFZLENBQUM7QUFBQSxRQUN2QjtBQUFBLFFBQ0E7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNILFdBQVcsUUFBUSxRQUFXO0FBQzVCLGNBQVEsT0FBTztBQUFBLFFBQ2IsV0FBVztBQUFBLFFBQ1gsTUFBTTtBQUFBLFVBQ0osUUFBUSxZQUFZLENBQUM7QUFBQSxRQUN2QjtBQUFBLFFBQ0EsS0FBSztBQUFBLFVBQ0gsT0FBTyxJQUFJO0FBQUEsVUFDWCxLQUFLLElBQUk7QUFBQSxRQUNYO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDSDtBQUFBLEVBQ0YsV0FBVyxZQUFZLFNBQVMsR0FBRztBQUNqQyxRQUFJLFNBQVMsUUFBVztBQUN0QixjQUFRLE9BQU87QUFBQSxRQUNiLFdBQVc7QUFBQSxRQUNYLE1BQU07QUFBQSxVQUNKLFNBQVMsUUFBUSxLQUFLLElBQUk7QUFBQSxRQUM1QjtBQUFBLFFBQ0E7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNILFdBQVcsUUFBUSxRQUFXO0FBQzVCLGNBQVEsT0FBTztBQUFBLFFBQ2IsV0FBVztBQUFBLFFBQ1gsTUFBTTtBQUFBLFVBQ0osU0FBUyxRQUFRLEtBQUssSUFBSTtBQUFBLFFBQzVCO0FBQUEsUUFDQSxLQUFLO0FBQUEsVUFDSCxPQUFPLElBQUk7QUFBQSxVQUNYLEtBQUssSUFBSTtBQUFBLFFBQ1g7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUNGO0FBRUEsSUFBTywwQkFBUTtBQUFBLEVBQ2IsTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLE1BQ2IsS0FBSztBQUFBLElBQ1A7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLENBQUMsaUJBQWlCLEdBQUc7QUFBQSxNQUNyQixDQUFDLGtCQUFrQixHQUFHO0FBQUEsSUFDeEI7QUFBQSxFQUNGO0FBQUEsRUFDQSxPQUFPLFNBQVM7QUFDZCxVQUFNLGFBQWEsUUFBUSxjQUFjO0FBQ3pDLFVBQU0sV0FBVyxXQUFXLGVBQWU7QUFFM0MsYUFBUyxRQUFRLENBQUMsWUFBWTtBQUM1QixVQUFJLFFBQVEsUUFBUSxVQUFhLFFBQVEsUUFBUSxNQUFNO0FBQ3JELDRCQUFvQixRQUFRLE9BQU8sU0FBUyxRQUFXLFFBQVEsR0FBRztBQUFBLE1BQ3BFO0FBQUEsSUFDRixDQUFDO0FBQ0QsV0FBTztBQUFBLE1BQ0wsUUFBUSxNQUFNO0FBQ1osWUFBSSxLQUFLLFVBQVUsUUFBVztBQUM1QjtBQUFBLFFBQ0Y7QUFDQSxZQUFJLE9BQU8sS0FBSyxVQUFVLFlBQVksT0FBTyxLQUFLLFVBQVUsVUFBVTtBQUNwRTtBQUFBLFFBQ0Y7QUFDQSxjQUFNLFFBQVEsR0FBRyxLQUFLLEtBQUs7QUFDM0IsNEJBQW9CLE9BQU8sU0FBUyxJQUFJO0FBQUEsTUFDMUM7QUFBQSxNQUNBLGdCQUFnQixNQUFNO0FBQ3BCLFlBQUksQ0FBQyxLQUFLLE9BQU87QUFDZjtBQUFBLFFBQ0Y7QUFDQSxZQUFJLE9BQU8sS0FBSyxNQUFNLFdBQVcsVUFBVTtBQUN6QztBQUFBLFFBQ0Y7QUFDQSw0QkFBb0IsS0FBSyxNQUFNLFFBQVEsU0FBUyxJQUFJO0FBQUEsTUFDdEQ7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,100 @@
1
+ // src/no-uuid.ts
2
+ var UUID_FOUND = "UUID_FOUND";
3
+ var UUIDS_FOUND = "UUIDS_FOUND";
4
+ var 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;
5
+ function checkForUuid(value, context, node, loc) {
6
+ const matches = value.match(uuidRegex);
7
+ if (matches === null) {
8
+ return;
9
+ }
10
+ if (matches.length === 1) {
11
+ if (node !== void 0) {
12
+ context.report({
13
+ messageId: UUID_FOUND,
14
+ data: {
15
+ uuid: matches[0] ?? ""
16
+ },
17
+ node
18
+ });
19
+ } else if (loc !== void 0) {
20
+ context.report({
21
+ messageId: UUID_FOUND,
22
+ data: {
23
+ uuid: matches[0] ?? ""
24
+ },
25
+ loc: {
26
+ start: loc.start,
27
+ end: loc.end
28
+ }
29
+ });
30
+ }
31
+ } else if (matches.length > 1) {
32
+ if (node !== void 0) {
33
+ context.report({
34
+ messageId: UUIDS_FOUND,
35
+ data: {
36
+ uuids: matches.join(", ")
37
+ },
38
+ node
39
+ });
40
+ } else if (loc !== void 0) {
41
+ context.report({
42
+ messageId: UUIDS_FOUND,
43
+ data: {
44
+ uuids: matches.join(", ")
45
+ },
46
+ loc: {
47
+ start: loc.start,
48
+ end: loc.end
49
+ }
50
+ });
51
+ }
52
+ }
53
+ }
54
+ var no_uuid_default = {
55
+ meta: {
56
+ type: "problem",
57
+ docs: {
58
+ description: "Detects if a string literal contains a UUID",
59
+ url: "https://github.com/checkdigit/eslint-plugin"
60
+ },
61
+ messages: {
62
+ [UUID_FOUND]: `UUID found: "{{ uuid }}"`,
63
+ [UUIDS_FOUND]: `Multiple UUIDs found: "{{ uuids }}"`
64
+ }
65
+ },
66
+ create(context) {
67
+ const sourceCode = context.getSourceCode();
68
+ const comments = sourceCode.getAllComments();
69
+ comments.forEach((comment) => {
70
+ if (comment.loc !== void 0 && comment.loc !== null) {
71
+ checkForUuid(comment.value, context, void 0, comment.loc);
72
+ }
73
+ });
74
+ return {
75
+ Literal(node) {
76
+ if (node.value === void 0) {
77
+ return;
78
+ }
79
+ if (typeof node.value !== "string") {
80
+ return;
81
+ }
82
+ const value = `${node.value}`;
83
+ checkForUuid(value, context, node);
84
+ },
85
+ TemplateElement(node) {
86
+ if (!node.value) {
87
+ return;
88
+ }
89
+ if (typeof node.value.cooked !== "string") {
90
+ return;
91
+ }
92
+ checkForUuid(node.value.cooked, context, node);
93
+ }
94
+ };
95
+ }
96
+ };
97
+ export {
98
+ no_uuid_default as default
99
+ };
100
+ //# sourceMappingURL=data:application/json;base64,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
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const _default: Rule.RuleModule;
3
+ export default _default;
@@ -0,0 +1,24 @@
1
+ declare const _default: {
2
+ rules: {
3
+ 'file-path-comment': import("eslint").Rule.RuleModule;
4
+ 'no-card-numbers': import("eslint").Rule.RuleModule;
5
+ 'no-uuid': import("eslint").Rule.RuleModule;
6
+ };
7
+ configs: {
8
+ all: {
9
+ rules: {
10
+ '@checkdigit/no-card-numbers': string;
11
+ '@checkdigit/file-path-comment': string;
12
+ '@checkdigit/no-uuid': string;
13
+ };
14
+ };
15
+ recommended: {
16
+ rules: {
17
+ '@checkdigit/no-card-numbers': string;
18
+ '@checkdigit/file-path-comment': string;
19
+ '@checkdigit/no-uuid': string;
20
+ };
21
+ };
22
+ };
23
+ };
24
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const _default: Rule.RuleModule;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const _default: Rule.RuleModule;
3
+ export default _default;
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@checkdigit/eslint-plugin","version":"5.0.0-PR.36-f31c","description":"Check Digit eslint plugins","prettier":"@checkdigit/prettier-config","main":"dist/index.js","keywords":["eslint","eslintplugin"],"engines":{"node":">=18"},"repository":{"type":"git","url":"git+https://github.com/checkdigit/eslint-plugin.git"},"author":"Check Digit, LLC","license":"MIT","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"homepage":"https://github.com/checkdigit/eslint-plugin#readme","peerDependencies":{"eslint":">=8"},"devDependencies":{"@checkdigit/jest-config":"^2.3.0","@checkdigit/prettier-config":"4.0.0-PR.23-11e4","@checkdigit/typescript-config":"4.0.0-PR.38-ff3c","@types/eslint":"^8.40.2","@typescript-eslint/eslint-plugin":"^5.60.1","@typescript-eslint/parser":"^5.60.1","eslint-config-prettier":"^8.8.0","eslint-plugin-deprecate":"^0.7.0","eslint-plugin-eslint-plugin":"^5.1.0","eslint-plugin-import":"^2.27.5","eslint-plugin-no-only-tests":"^3.1.0","eslint-plugin-no-secrets":"^0.8.9","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"^0.19.0"},"scripts":{"postversion":"git push && git push --tags","lint:fix":"eslint -f unix --ext .ts src --fix","lint":"eslint -f unix --ext .ts src","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","ci:compile":"tsc --noEmit","ci:test":"jest --coverage=false","ci:coverage":"jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier"},"jest":{"preset":"@checkdigit/jest-config"},"files":["dist","SECURITY.md"]}
1
+ {"name":"@checkdigit/eslint-plugin","version":"5.0.0-PR.36-40a0","description":"Check Digit eslint plugins","prettier":"@checkdigit/prettier-config","exports":{".":{"types":"./dist-types/index.d.ts","require":"./dist-cjs/index.cjs","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"type":"module","sideEffects":false,"keywords":["eslint","eslintplugin"],"engines":{"node":">=18"},"repository":{"type":"git","url":"git+https://github.com/checkdigit/eslint-plugin.git"},"author":"Check Digit, LLC","license":"MIT","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"homepage":"https://github.com/checkdigit/eslint-plugin#readme","peerDependencies":{"eslint":">=8"},"devDependencies":{"@checkdigit/jest-config":"^2.3.0","@checkdigit/prettier-config":"4.0.0-PR.23-11e4","@checkdigit/typescript-config":"4.0.0-PR.38-ff3c","@types/eslint":"^8.40.2","@typescript-eslint/eslint-plugin":"^5.60.1","@typescript-eslint/parser":"^5.60.1","eslint-config-prettier":"^8.8.0","eslint-plugin-deprecate":"^0.7.0","eslint-plugin-eslint-plugin":"^5.1.0","eslint-plugin-import":"^2.27.5","eslint-plugin-no-only-tests":"^3.1.0","eslint-plugin-no-secrets":"^0.8.9","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"^0.19.0"},"scripts":{"prepublishOnly":"npm run build:dist-types && npm run build:dist-cjs && npm run build:dist-esm","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","build:dist-cjs":"rimraf dist-cjs && npx builder --type=commonjs --sourceMap --outDir=dist-cjs","build:dist-esm":"rimraf dist-esm && npx builder --type=module --sourceMap --outDir=dist-mjs","lint:fix":"eslint -f unix --ext .ts src --fix","lint":"eslint -f unix --ext .ts src","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","ci:compile":"tsc --noEmit","ci:test":"jest --coverage=false","ci:coverage":"jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier"},"jest":{"preset":"@checkdigit/jest-config"},"files":["src","dist-types","dist-cjs","dist-mjs","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-cjs/**/*.test.cjs","!dist-cjs/**/*.spec.cjs","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"]}
@@ -0,0 +1,88 @@
1
+ // file-path-comment.ts
2
+
3
+ import type { Rule } from 'eslint';
4
+
5
+ /*
6
+ * Copyright (c) 2021-2022 Check Digit, LLC
7
+ *
8
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
9
+ */
10
+
11
+ export default {
12
+ meta: {
13
+ type: 'suggestion',
14
+ docs: {
15
+ description: 'Validate that first line of file is a path to the file',
16
+ url: 'https://github.com/checkdigit/eslint-plugin',
17
+ },
18
+ fixable: 'code',
19
+ },
20
+ create(context) {
21
+ const firstLine = context.getSourceCode().getLines()[0] as string;
22
+ const expectedPath = context.getFilename().split('src/')[1];
23
+
24
+ if (expectedPath === undefined) {
25
+ return {};
26
+ }
27
+
28
+ if (!firstLine.startsWith('//')) {
29
+ if (firstLine.startsWith('/*')) {
30
+ context.report({
31
+ loc: {
32
+ start: {
33
+ line: 0,
34
+ column: 0,
35
+ },
36
+ end: {
37
+ line: 0,
38
+ column: 1,
39
+ },
40
+ },
41
+ message: 'first line cannot be a block comment',
42
+ fix(fixer: Rule.RuleFixer) {
43
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}\n\n`);
44
+ },
45
+ });
46
+ } else {
47
+ context.report({
48
+ loc: {
49
+ start: {
50
+ line: 0,
51
+ column: 0,
52
+ },
53
+ end: {
54
+ line: 0,
55
+ column: 1,
56
+ },
57
+ },
58
+ message: 'first line is not a comment with the file path',
59
+ fix(fixer: Rule.RuleFixer) {
60
+ return fixer.insertTextBeforeRange([0, 0], `// ${expectedPath}\n\n`);
61
+ },
62
+ });
63
+ }
64
+ } else {
65
+ const actualComment = firstLine.split('// ')[1];
66
+ if (expectedPath !== actualComment) {
67
+ context.report({
68
+ loc: {
69
+ start: {
70
+ line: 0,
71
+ column: 0,
72
+ },
73
+ end: {
74
+ line: 0,
75
+ column: 1,
76
+ },
77
+ },
78
+ message: 'first line is a comment but is not a path to the file',
79
+ fix(fixer: Rule.RuleFixer) {
80
+ return fixer.replaceTextRange([0, firstLine.length], `// ${expectedPath}`);
81
+ },
82
+ });
83
+ }
84
+ }
85
+
86
+ return {};
87
+ },
88
+ } as Rule.RuleModule;
package/src/index.ts ADDED
@@ -0,0 +1,35 @@
1
+ // index.ts
2
+
3
+ /*
4
+ * Copyright (c) 2021-2022 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import filePathComment from './file-path-comment';
10
+ import noCardNumbers from './no-card-numbers';
11
+ import noUuid from './no-uuid';
12
+
13
+ export default {
14
+ rules: {
15
+ 'file-path-comment': filePathComment,
16
+ 'no-card-numbers': noCardNumbers,
17
+ 'no-uuid': noUuid,
18
+ },
19
+ configs: {
20
+ all: {
21
+ rules: {
22
+ '@checkdigit/no-card-numbers': 'error',
23
+ '@checkdigit/file-path-comment': 'error',
24
+ '@checkdigit/no-uuid': 'error',
25
+ },
26
+ },
27
+ recommended: {
28
+ rules: {
29
+ '@checkdigit/no-card-numbers': 'error',
30
+ '@checkdigit/file-path-comment': 'off',
31
+ '@checkdigit/no-uuid': 'error',
32
+ },
33
+ },
34
+ },
35
+ };
@@ -0,0 +1,151 @@
1
+ // no-card-numbers.ts
2
+
3
+ /*
4
+ * Copyright (c) 2021-2022 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import type { Node, SourceLocation } from 'estree';
10
+ import type { Rule } from 'eslint';
11
+
12
+ const CARD_NUMBER_FOUND = 'CARD_NUMBER_FOUND';
13
+ const CARD_NUMBERS_FOUND = 'CARD_NUMBERS_FOUND';
14
+ const cardNumberRegex = /\d{15,19}/gmu;
15
+ const allowCardNumbers = [
16
+ '4111111111111111',
17
+ '111111111111111',
18
+ '000000000000000',
19
+ '0000000000000000',
20
+ '00000000000000000',
21
+ '000000000000000000',
22
+ '0000000000000000000',
23
+ ];
24
+
25
+ function luhnCheck(cardNumber: string) {
26
+ return (
27
+ cardNumber
28
+ .split('')
29
+ .reverse()
30
+ .map((digit) => parseInt(digit, 10))
31
+ .reduce((previousValue, currentValue, index) => {
32
+ let value = currentValue;
33
+ if (index % 2 === 1) {
34
+ value *= 2;
35
+ // eslint-disable-next-line no-magic-numbers
36
+ if (value > 9) {
37
+ value = (value % 10) + 1;
38
+ }
39
+ }
40
+ return previousValue + value;
41
+ }, 0) %
42
+ 10 ===
43
+ 0
44
+ );
45
+ }
46
+
47
+ function checkForCardNumbers(value: string, context: Rule.RuleContext, node?: Node, loc?: SourceLocation) {
48
+ const matches = value.match(cardNumberRegex);
49
+ if (matches === null) {
50
+ return;
51
+ }
52
+ const cardNumbers = matches.filter(
53
+ (match) =>
54
+ luhnCheck(match) &&
55
+ allowCardNumbers.indexOf(match) === -1 &&
56
+ // any 16-digit number that begins with 0-1 or 7-9 is not a valid card number
57
+ match[0] !== '0' &&
58
+ match[0] !== '1' &&
59
+ match[0] !== '7' &&
60
+ match[0] !== '8' &&
61
+ match[0] !== '9'
62
+ );
63
+ if (cardNumbers.length === 1) {
64
+ if (node !== undefined) {
65
+ context.report({
66
+ messageId: CARD_NUMBER_FOUND,
67
+ data: {
68
+ number: cardNumbers[0] as string,
69
+ },
70
+ node,
71
+ });
72
+ } else if (loc !== undefined) {
73
+ context.report({
74
+ messageId: CARD_NUMBER_FOUND,
75
+ data: {
76
+ number: cardNumbers[0] as string,
77
+ },
78
+ loc: {
79
+ start: loc.start,
80
+ end: loc.end,
81
+ },
82
+ });
83
+ }
84
+ } else if (cardNumbers.length > 1) {
85
+ if (node !== undefined) {
86
+ context.report({
87
+ messageId: CARD_NUMBERS_FOUND,
88
+ data: {
89
+ numbers: matches.join(', '),
90
+ },
91
+ node,
92
+ });
93
+ } else if (loc !== undefined) {
94
+ context.report({
95
+ messageId: CARD_NUMBERS_FOUND,
96
+ data: {
97
+ numbers: matches.join(', '),
98
+ },
99
+ loc: {
100
+ start: loc.start,
101
+ end: loc.end,
102
+ },
103
+ });
104
+ }
105
+ }
106
+ }
107
+
108
+ export default {
109
+ meta: {
110
+ type: 'problem',
111
+ docs: {
112
+ description: 'Detects if a luhn passing card number',
113
+ url: 'https://github.com/checkdigit/eslint-plugin',
114
+ },
115
+ messages: {
116
+ [CARD_NUMBER_FOUND]: `Valid card number: "{{ number }}"`,
117
+ [CARD_NUMBERS_FOUND]: `Multiple valid card numbers found: "{{ numbers }}"`,
118
+ },
119
+ },
120
+ create(context) {
121
+ const sourceCode = context.getSourceCode();
122
+ const comments = sourceCode.getAllComments();
123
+
124
+ comments.forEach((comment) => {
125
+ if (comment.loc !== undefined && comment.loc !== null) {
126
+ checkForCardNumbers(comment.value, context, undefined, comment.loc);
127
+ }
128
+ });
129
+ return {
130
+ Literal(node) {
131
+ if (node.value === undefined) {
132
+ return;
133
+ }
134
+ if (typeof node.value !== 'string' && typeof node.value !== 'number') {
135
+ return;
136
+ }
137
+ const value = `${node.value}`;
138
+ checkForCardNumbers(value, context, node);
139
+ },
140
+ TemplateElement(node) {
141
+ if (!node.value) {
142
+ return;
143
+ }
144
+ if (typeof node.value.cooked !== 'string') {
145
+ return;
146
+ }
147
+ checkForCardNumbers(node.value.cooked, context, node);
148
+ },
149
+ };
150
+ },
151
+ } as Rule.RuleModule;
package/src/no-uuid.ts ADDED
@@ -0,0 +1,109 @@
1
+ // no-uuid.ts
2
+
3
+ /*
4
+ * Copyright (c) 2022 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import type { Node, SourceLocation } from 'estree';
10
+ import type { Rule } from 'eslint';
11
+
12
+ const UUID_FOUND = 'UUID_FOUND';
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;
15
+
16
+ function checkForUuid(value: string, context: Rule.RuleContext, node?: Node, loc?: SourceLocation) {
17
+ const matches = value.match(uuidRegex);
18
+ if (matches === null) {
19
+ return;
20
+ }
21
+ if (matches.length === 1) {
22
+ if (node !== undefined) {
23
+ context.report({
24
+ messageId: UUID_FOUND,
25
+ data: {
26
+ uuid: matches[0] ?? '',
27
+ },
28
+ node,
29
+ });
30
+ } else if (loc !== undefined) {
31
+ context.report({
32
+ messageId: UUID_FOUND,
33
+ data: {
34
+ uuid: matches[0] ?? '',
35
+ },
36
+ loc: {
37
+ start: loc.start,
38
+ end: loc.end,
39
+ },
40
+ });
41
+ }
42
+ } else if (matches.length > 1) {
43
+ if (node !== undefined) {
44
+ context.report({
45
+ messageId: UUIDS_FOUND,
46
+ data: {
47
+ uuids: matches.join(', '),
48
+ },
49
+ node,
50
+ });
51
+ } else if (loc !== undefined) {
52
+ context.report({
53
+ messageId: UUIDS_FOUND,
54
+ data: {
55
+ uuids: matches.join(', '),
56
+ },
57
+ loc: {
58
+ start: loc.start,
59
+ end: loc.end,
60
+ },
61
+ });
62
+ }
63
+ }
64
+ }
65
+
66
+ export default {
67
+ meta: {
68
+ type: 'problem',
69
+ docs: {
70
+ description: 'Detects if a string literal contains a UUID',
71
+ url: 'https://github.com/checkdigit/eslint-plugin',
72
+ },
73
+ messages: {
74
+ [UUID_FOUND]: `UUID found: "{{ uuid }}"`,
75
+ [UUIDS_FOUND]: `Multiple UUIDs found: "{{ uuids }}"`,
76
+ },
77
+ },
78
+ create(context) {
79
+ const sourceCode = context.getSourceCode();
80
+ const comments = sourceCode.getAllComments();
81
+
82
+ comments.forEach((comment) => {
83
+ if (comment.loc !== undefined && comment.loc !== null) {
84
+ checkForUuid(comment.value, context, undefined, comment.loc);
85
+ }
86
+ });
87
+ return {
88
+ Literal(node) {
89
+ if (node.value === undefined) {
90
+ return;
91
+ }
92
+ if (typeof node.value !== 'string') {
93
+ return;
94
+ }
95
+ const value = `${node.value}`;
96
+ checkForUuid(value, context, node);
97
+ },
98
+ TemplateElement(node) {
99
+ if (!node.value) {
100
+ return;
101
+ }
102
+ if (typeof node.value.cooked !== 'string') {
103
+ return;
104
+ }
105
+ checkForUuid(node.value.cooked, context, node);
106
+ },
107
+ };
108
+ },
109
+ } as Rule.RuleModule;