@n8n/eslint-plugin-community-nodes 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/README.md +7 -1
  3. package/dist/plugin.d.ts +36 -0
  4. package/dist/plugin.d.ts.map +1 -1
  5. package/dist/plugin.js +12 -0
  6. package/dist/plugin.js.map +1 -1
  7. package/dist/rules/credential-password-field.d.ts.map +1 -1
  8. package/dist/rules/credential-password-field.js +3 -31
  9. package/dist/rules/credential-password-field.js.map +1 -1
  10. package/dist/rules/credential-unnecessary-password.d.ts +2 -0
  11. package/dist/rules/credential-unnecessary-password.d.ts.map +1 -0
  12. package/dist/rules/credential-unnecessary-password.js +54 -0
  13. package/dist/rules/credential-unnecessary-password.js.map +1 -0
  14. package/dist/rules/index.d.ts +6 -0
  15. package/dist/rules/index.d.ts.map +1 -1
  16. package/dist/rules/index.js +12 -0
  17. package/dist/rules/index.js.map +1 -1
  18. package/dist/rules/no-dead-files.d.ts +7 -0
  19. package/dist/rules/no-dead-files.d.ts.map +1 -0
  20. package/dist/rules/no-dead-files.js +57 -0
  21. package/dist/rules/no-dead-files.js.map +1 -0
  22. package/dist/rules/no-hardcoded-secrets.d.ts +2 -0
  23. package/dist/rules/no-hardcoded-secrets.d.ts.map +1 -0
  24. package/dist/rules/no-hardcoded-secrets.js +147 -0
  25. package/dist/rules/no-hardcoded-secrets.js.map +1 -0
  26. package/dist/rules/no-silent-error-swallowing.d.ts +2 -0
  27. package/dist/rules/no-silent-error-swallowing.d.ts.map +1 -0
  28. package/dist/rules/no-silent-error-swallowing.js +112 -0
  29. package/dist/rules/no-silent-error-swallowing.js.map +1 -0
  30. package/dist/rules/require-files-array.d.ts +2 -0
  31. package/dist/rules/require-files-array.d.ts.map +1 -0
  32. package/dist/rules/require-files-array.js +41 -0
  33. package/dist/rules/require-files-array.js.map +1 -0
  34. package/dist/rules/require-homepage.d.ts +2 -0
  35. package/dist/rules/require-homepage.d.ts.map +1 -0
  36. package/dist/rules/require-homepage.js +52 -0
  37. package/dist/rules/require-homepage.js.map +1 -0
  38. package/dist/rules/webhook-lifecycle-complete.d.ts.map +1 -1
  39. package/dist/rules/webhook-lifecycle-complete.js +2 -3
  40. package/dist/rules/webhook-lifecycle-complete.js.map +1 -1
  41. package/dist/typecheck.tsbuildinfo +1 -1
  42. package/dist/utils/constants.d.ts +5 -0
  43. package/dist/utils/constants.d.ts.map +1 -0
  44. package/dist/utils/constants.js +15 -0
  45. package/dist/utils/constants.js.map +1 -0
  46. package/dist/utils/credential-fields.d.ts +20 -0
  47. package/dist/utils/credential-fields.d.ts.map +1 -0
  48. package/dist/utils/credential-fields.js +45 -0
  49. package/dist/utils/credential-fields.js.map +1 -0
  50. package/dist/utils/file-utils.d.ts +6 -0
  51. package/dist/utils/file-utils.d.ts.map +1 -1
  52. package/dist/utils/file-utils.js +16 -0
  53. package/dist/utils/file-utils.js.map +1 -1
  54. package/dist/utils/index.d.ts +2 -0
  55. package/dist/utils/index.d.ts.map +1 -1
  56. package/dist/utils/index.js +2 -0
  57. package/dist/utils/index.js.map +1 -1
  58. package/docs/rules/credential-password-field.md +3 -1
  59. package/docs/rules/credential-unnecessary-password.md +46 -0
  60. package/docs/rules/no-dead-files.md +56 -0
  61. package/docs/rules/no-hardcoded-secrets.md +59 -0
  62. package/docs/rules/no-silent-error-swallowing.md +72 -0
  63. package/docs/rules/require-files-array.md +43 -0
  64. package/docs/rules/require-homepage.md +49 -0
  65. package/package.json +2 -2
  66. package/src/plugin.ts +12 -0
  67. package/src/rules/credential-password-field.ts +4 -40
  68. package/src/rules/credential-unnecessary-password.test.ts +105 -0
  69. package/src/rules/credential-unnecessary-password.ts +72 -0
  70. package/src/rules/index.ts +12 -0
  71. package/src/rules/no-dead-files.test.ts +128 -0
  72. package/src/rules/no-dead-files.ts +71 -0
  73. package/src/rules/no-hardcoded-secrets.test.ts +124 -0
  74. package/src/rules/no-hardcoded-secrets.ts +161 -0
  75. package/src/rules/no-silent-error-swallowing.test.ts +245 -0
  76. package/src/rules/no-silent-error-swallowing.ts +127 -0
  77. package/src/rules/require-files-array.test.ts +57 -0
  78. package/src/rules/require-files-array.ts +50 -0
  79. package/src/rules/require-homepage.test.ts +80 -0
  80. package/src/rules/require-homepage.ts +59 -0
  81. package/src/rules/webhook-lifecycle-complete.ts +4 -5
  82. package/src/utils/constants.ts +21 -0
  83. package/src/utils/credential-fields.ts +57 -0
  84. package/src/utils/file-utils.ts +23 -0
  85. package/src/utils/index.ts +2 -0
@@ -0,0 +1,57 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import * as path from 'node:path';
3
+ import { createRule, findFilesInPackageDirs } from '../utils/index.js';
4
+ // Package subdirectories that ship in the published artifact and should stay clean.
5
+ const SCAN_DIRS = ['nodes', 'credentials'];
6
+ const DEAD_FILE_MATCHERS = [
7
+ (fileName) => fileName.endsWith('.backup'),
8
+ (fileName) => fileName.endsWith('.bak'),
9
+ // Windows "mark of the web" ADS files, extracted as literal filenames on
10
+ // filesystems without alternate data streams (e.g. `Foo.node.ts:Zone.Identifier`).
11
+ (fileName) => fileName.endsWith('Zone.Identifier'),
12
+ (fileName) => fileName === 'test.js',
13
+ (fileName) => fileName === 'test.ts',
14
+ ];
15
+ /**
16
+ * Returns true if the given filename looks like a leftover backup, editor, or
17
+ * test-artifact file that should not ship with a community node.
18
+ */
19
+ export function isDeadFileName(fileName) {
20
+ return DEAD_FILE_MATCHERS.some((matches) => matches(fileName));
21
+ }
22
+ export const NoDeadFilesRule = createRule({
23
+ name: 'no-dead-files',
24
+ meta: {
25
+ type: 'problem',
26
+ docs: {
27
+ description: 'Disallow leftover backup, editor, and test-artifact files in the `nodes/` and `credentials/` directories of a community node package',
28
+ },
29
+ messages: {
30
+ deadFileFound: 'Remove the leftover file "{{ file }}". Backup, editor, and test-artifact files should not be published with a community node.',
31
+ },
32
+ schema: [],
33
+ },
34
+ defaultOptions: [],
35
+ create(context) {
36
+ if (!context.filename.endsWith('package.json')) {
37
+ return {};
38
+ }
39
+ return {
40
+ ObjectExpression(node) {
41
+ // Only inspect the root object of the package.json file, so the scan runs once.
42
+ if (node.parent?.type !== AST_NODE_TYPES.ExpressionStatement) {
43
+ return;
44
+ }
45
+ const packageDir = path.dirname(context.filename);
46
+ for (const deadFile of findFilesInPackageDirs(context.filename, SCAN_DIRS, isDeadFileName)) {
47
+ context.report({
48
+ node,
49
+ messageId: 'deadFileFound',
50
+ data: { file: path.relative(packageDir, deadFile) },
51
+ });
52
+ }
53
+ },
54
+ };
55
+ },
56
+ });
57
+ //# sourceMappingURL=no-dead-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-dead-files.js","sourceRoot":"","sources":["../../src/rules/no-dead-files.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,oFAAoF;AACpF,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AAE3C,MAAM,kBAAkB,GAAyC;IAChE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC1C,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;IACvC,yEAAyE;IACzE,mFAAmF;IACnF,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAClD,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,SAAS;IACpC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,SAAS;CACpC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC9C,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;IACzC,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EACV,sIAAsI;SACvI;QACD,QAAQ,EAAE;YACT,aAAa,EACZ,+HAA+H;SAChI;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAA+B;gBAC/C,gFAAgF;gBAChF,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,mBAAmB,EAAE,CAAC;oBAC9D,OAAO;gBACR,CAAC;gBAED,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAElD,KAAK,MAAM,QAAQ,IAAI,sBAAsB,CAC5C,OAAO,CAAC,QAAQ,EAChB,SAAS,EACT,cAAc,CACd,EAAE,CAAC;oBACH,OAAO,CAAC,MAAM,CAAC;wBACd,IAAI;wBACJ,SAAS,EAAE,eAAe;wBAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE;qBACnD,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const NoHardcodedSecretsRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"hardcodedSecret", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
+ //# sourceMappingURL=no-hardcoded-secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-hardcoded-secrets.d.ts","sourceRoot":"","sources":["../../src/rules/no-hardcoded-secrets.ts"],"names":[],"mappings":"AAkGA,eAAO,MAAM,sBAAsB,oJA8DjC,CAAC"}
@@ -0,0 +1,147 @@
1
+ import { TSESTree } from '@typescript-eslint/utils';
2
+ import { createRule, getStringLiteralValue, isSensitiveName } from '../utils/index.js';
3
+ const { AST_NODE_TYPES } = TSESTree;
4
+ /**
5
+ * Extra name fragments (beyond the shared sensitive set in `credential-fields`)
6
+ * that suggest a JS identifier holds a credential. Bare `key`/`auth` are broad,
7
+ * but the value heuristic below narrows the match, and they catch separator
8
+ * forms such as `api_key` that the compound fragments miss.
9
+ */
10
+ const EXTRA_SECRET_NAME_FRAGMENTS = ['key', 'passwd', 'auth'];
11
+ /**
12
+ * Fragments that mark a value as an obvious placeholder rather than a real
13
+ * secret. These are skipped to keep the (intentionally heuristic) rule quieter.
14
+ */
15
+ const PLACEHOLDER_FRAGMENTS = [
16
+ 'example',
17
+ 'placeholder',
18
+ 'changeme',
19
+ 'your',
20
+ 'dummy',
21
+ 'xxxx',
22
+ '<',
23
+ '{{',
24
+ ];
25
+ const MIN_SECRET_LENGTH = 16;
26
+ function nameLooksLikeSecret(name) {
27
+ // `exclusions: []` disables the URL/ID/pub name exclusions on purpose: the
28
+ // value heuristic below is the real gate, so a suspicious value on e.g.
29
+ // `publicKeyUrl` should still be flagged rather than silently skipped. Erring
30
+ // toward a false positive is safer than missing a secret.
31
+ return isSensitiveName(name, { extra: EXTRA_SECRET_NAME_FRAGMENTS, exclusions: [] });
32
+ }
33
+ function looksLikePlaceholder(value) {
34
+ const lower = value.toLowerCase();
35
+ return PLACEHOLDER_FRAGMENTS.some((fragment) => lower.includes(fragment));
36
+ }
37
+ /**
38
+ * Heuristic: does this string value look like a real credential? Real secrets
39
+ * are long, contiguous tokens with the shape of a hex digest or a base64/token
40
+ * string. The digit+letter/punctuation requirement keeps ordinary long
41
+ * camelCase words from being treated as secrets.
42
+ */
43
+ function looksLikeSecretValue(value) {
44
+ // Require at least MIN_SECRET_LENGTH characters; anything shorter is almost
45
+ // always a non-secret word or identifier rather than a generated credential.
46
+ if (value.length < MIN_SECRET_LENGTH)
47
+ return false;
48
+ if (/\s/.test(value))
49
+ return false;
50
+ if (looksLikePlaceholder(value))
51
+ return false;
52
+ // A long, purely hexadecimal string (e.g. an MD5/SHA/hex API key).
53
+ if (/^[0-9a-f]+$/i.test(value))
54
+ return true;
55
+ // A base64 / base64url / token-shaped string.
56
+ if (/^[A-Za-z0-9+/=_.-]+$/.test(value)) {
57
+ const hasDigit = /[0-9]/.test(value);
58
+ const hasLetter = /[a-z]/i.test(value);
59
+ // Only `+ / =` count as a standalone signal: they are hallmarks of base64
60
+ // but rarely appear in ordinary code strings. `. - _` are excluded here
61
+ // because dotted/hyphenated/snake_case constants (scopes, paths, ids) use
62
+ // them heavily and would otherwise be misflagged.
63
+ const hasStrongBase64Punctuation = /[+/=]/.test(value);
64
+ return (hasDigit && hasLetter) || hasStrongBase64Punctuation;
65
+ }
66
+ return false;
67
+ }
68
+ function getStaticStringValue(node) {
69
+ if (!node)
70
+ return null;
71
+ const literal = getStringLiteralValue(node);
72
+ if (literal !== null)
73
+ return literal;
74
+ if (node.type === AST_NODE_TYPES.TemplateLiteral &&
75
+ node.expressions.length === 0 &&
76
+ node.quasis.length === 1) {
77
+ return node.quasis[0]?.value.cooked ?? null;
78
+ }
79
+ return null;
80
+ }
81
+ function getKeyName(key) {
82
+ if (key.type === AST_NODE_TYPES.Identifier)
83
+ return key.name;
84
+ if (key.type === AST_NODE_TYPES.Literal && typeof key.value === 'string')
85
+ return key.value;
86
+ return null;
87
+ }
88
+ export const NoHardcodedSecretsRule = createRule({
89
+ name: 'no-hardcoded-secrets',
90
+ meta: {
91
+ type: 'problem',
92
+ docs: {
93
+ description: 'Disallow hardcoded secrets (API keys, tokens, passwords) embedded as string literals in source.',
94
+ },
95
+ messages: {
96
+ hardcodedSecret: 'Possible hardcoded secret assigned to `{{ name }}`. Store secrets in credentials or environment variables instead of embedding them in source. If this is not a real secret, rename the variable or move the value out of source to silence this rule.',
97
+ },
98
+ schema: [],
99
+ },
100
+ defaultOptions: [],
101
+ create(context) {
102
+ const check = (name, valueNode) => {
103
+ if (!name || !valueNode || !nameLooksLikeSecret(name))
104
+ return;
105
+ const value = getStaticStringValue(valueNode);
106
+ if (value === null || !looksLikeSecretValue(value))
107
+ return;
108
+ context.report({
109
+ node: valueNode,
110
+ messageId: 'hardcodedSecret',
111
+ data: { name },
112
+ });
113
+ };
114
+ return {
115
+ // const apiKey = '...'
116
+ VariableDeclarator(node) {
117
+ if (node.id.type !== AST_NODE_TYPES.Identifier)
118
+ return;
119
+ check(node.id.name, node.init);
120
+ },
121
+ // class field: private token = '...'
122
+ PropertyDefinition(node) {
123
+ if (node.computed)
124
+ return;
125
+ check(getKeyName(node.key), node.value);
126
+ },
127
+ // object literal: { apiKey: '...' } or { 'api_key': '...' }
128
+ Property(node) {
129
+ if (node.computed)
130
+ return;
131
+ check(getKeyName(node.key), node.value);
132
+ },
133
+ // this.secret = '...' / config.token = '...' / secret = '...'
134
+ AssignmentExpression(node) {
135
+ if (node.left.type === AST_NODE_TYPES.Identifier) {
136
+ check(node.left.name, node.right);
137
+ }
138
+ else if (node.left.type === AST_NODE_TYPES.MemberExpression &&
139
+ !node.left.computed &&
140
+ node.left.property.type === AST_NODE_TYPES.Identifier) {
141
+ check(node.left.property.name, node.right);
142
+ }
143
+ },
144
+ };
145
+ },
146
+ });
147
+ //# sourceMappingURL=no-hardcoded-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-hardcoded-secrets.js","sourceRoot":"","sources":["../../src/rules/no-hardcoded-secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEvF,MAAM,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,qBAAqB,GAAG;IAC7B,SAAS;IACT,aAAa;IACb,UAAU;IACV,MAAM;IACN,OAAO;IACP,MAAM;IACN,GAAG;IACH,IAAI;CACJ,CAAC;AAEF,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,SAAS,mBAAmB,CAAC,IAAY;IACxC,2EAA2E;IAC3E,wEAAwE;IACxE,8EAA8E;IAC9E,0DAA0D;IAC1D,OAAO,eAAe,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,2BAA2B,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,KAAa;IAC1C,4EAA4E;IAC5E,6EAA6E;IAC7E,IAAI,KAAK,CAAC,MAAM,GAAG,iBAAiB;QAAE,OAAO,KAAK,CAAC;IACnD,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,oBAAoB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9C,mEAAmE;IACnE,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,8CAA8C;IAC9C,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,0EAA0E;QAC1E,wEAAwE;QACxE,0EAA0E;QAC1E,kDAAkD;QAClD,MAAM,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,0BAA0B,CAAC;IAC9D,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAsC;IACnE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IAErC,IACC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QAC5C,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EACvB,CAAC;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,GAAkB;IACrC,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC5D,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC;IAC3F,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAC;IAChD,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EACV,iGAAiG;SAClG;QACD,QAAQ,EAAE;YACT,eAAe,EACd,wPAAwP;SACzP;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,MAAM,KAAK,GAAG,CAAC,IAAmB,EAAE,SAA2C,EAAE,EAAE;YAClF,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;gBAAE,OAAO;YAE9D,MAAM,KAAK,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;gBAAE,OAAO;YAE3D,OAAO,CAAC,MAAM,CAAC;gBACd,IAAI,EAAE,SAAS;gBACf,SAAS,EAAE,iBAAiB;gBAC5B,IAAI,EAAE,EAAE,IAAI,EAAE;aACd,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF,OAAO;YACN,uBAAuB;YACvB,kBAAkB,CAAC,IAAI;gBACtB,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;oBAAE,OAAO;gBACvD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;YAED,qCAAqC;YACrC,kBAAkB,CAAC,IAAI;gBACtB,IAAI,IAAI,CAAC,QAAQ;oBAAE,OAAO;gBAC1B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YAED,4DAA4D;YAC5D,QAAQ,CAAC,IAAI;gBACZ,IAAI,IAAI,CAAC,QAAQ;oBAAE,OAAO;gBAC1B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YAED,8DAA8D;YAC9D,oBAAoB,CAAC,IAAI;gBACxB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE,CAAC;oBAClD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnC,CAAC;qBAAM,IACN,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;oBAClD,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;oBACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EACpD,CAAC;oBACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC5C,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const NoSilentErrorSwallowingRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"emptyCatch" | "silentReturn", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
+ //# sourceMappingURL=no-silent-error-swallowing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-silent-error-swallowing.d.ts","sourceRoot":"","sources":["../../src/rules/no-silent-error-swallowing.ts"],"names":[],"mappings":"AA6CA,eAAO,MAAM,2BAA2B,gKAiFtC,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import { createRule, findClassProperty, isNodeTypeClass, WEBHOOK_LIFECYCLE_METHODS, } from '../utils/index.js';
3
+ const LIFECYCLE_METHODS = WEBHOOK_LIFECYCLE_METHODS;
4
+ /** Returns the static name of a non-computed object property key, or null. */
5
+ function getPropertyName(property) {
6
+ if (property.computed)
7
+ return null;
8
+ if (property.key.type === AST_NODE_TYPES.Identifier)
9
+ return property.key.name;
10
+ if (property.key.type === AST_NODE_TYPES.Literal)
11
+ return String(property.key.value);
12
+ return null;
13
+ }
14
+ function isFunctionNode(node) {
15
+ return (node.type === AST_NODE_TYPES.FunctionDeclaration ||
16
+ node.type === AST_NODE_TYPES.FunctionExpression ||
17
+ node.type === AST_NODE_TYPES.ArrowFunctionExpression);
18
+ }
19
+ /** Walks up to the function that lexically encloses `node`, or null at module scope. */
20
+ function getEnclosingFunction(node) {
21
+ let current = node.parent;
22
+ while (current) {
23
+ if (isFunctionNode(current))
24
+ return current;
25
+ current = current.parent;
26
+ }
27
+ return null;
28
+ }
29
+ /** A bare `return;` or `return true/false;` with no other work in the block. */
30
+ function isSilentReturn(statement) {
31
+ if (statement.type !== AST_NODE_TYPES.ReturnStatement)
32
+ return false;
33
+ const argument = statement.argument;
34
+ if (argument === null)
35
+ return true;
36
+ return argument.type === AST_NODE_TYPES.Literal && typeof argument.value === 'boolean';
37
+ }
38
+ export const NoSilentErrorSwallowingRule = createRule({
39
+ name: 'no-silent-error-swallowing',
40
+ meta: {
41
+ type: 'problem',
42
+ docs: {
43
+ description: 'Disallow webhook lifecycle methods (checkExists, create, delete) from silently swallowing errors in catch blocks',
44
+ },
45
+ messages: {
46
+ emptyCatch: 'Empty catch block in webhook lifecycle method `{{method}}` silently swallows the error. Log the error or rethrow it so failures surface instead of being hidden.',
47
+ silentReturn: 'Catch block in webhook lifecycle method `{{method}}` swallows the error and only returns without logging. Log the error (or rethrow) so failures surface instead of being hidden.',
48
+ },
49
+ schema: [],
50
+ },
51
+ defaultOptions: [],
52
+ create(context) {
53
+ // Maps each lifecycle method's function node to its method name. Populated
54
+ // when the enclosing class is visited (before its `catch` clauses), so a
55
+ // `catch` is only flagged when its *nearest* enclosing function is a
56
+ // lifecycle method — catches inside nested callbacks are left alone.
57
+ const lifecycleMethodByFn = new WeakMap();
58
+ return {
59
+ ClassDeclaration(node) {
60
+ if (!isNodeTypeClass(node))
61
+ return;
62
+ const webhookMethodsProperty = findClassProperty(node, 'webhookMethods');
63
+ if (webhookMethodsProperty?.value?.type !== AST_NODE_TYPES.ObjectExpression)
64
+ return;
65
+ for (const groupProperty of webhookMethodsProperty.value.properties) {
66
+ if (groupProperty.type !== AST_NODE_TYPES.Property)
67
+ continue;
68
+ if (groupProperty.value.type !== AST_NODE_TYPES.ObjectExpression)
69
+ continue;
70
+ for (const methodProperty of groupProperty.value.properties) {
71
+ if (methodProperty.type !== AST_NODE_TYPES.Property)
72
+ continue;
73
+ const methodName = getPropertyName(methodProperty);
74
+ if (methodName === null || !LIFECYCLE_METHODS.includes(methodName))
75
+ continue;
76
+ const fn = methodProperty.value;
77
+ if (fn.type === AST_NODE_TYPES.FunctionExpression ||
78
+ fn.type === AST_NODE_TYPES.ArrowFunctionExpression) {
79
+ lifecycleMethodByFn.set(fn, methodName);
80
+ }
81
+ }
82
+ }
83
+ },
84
+ CatchClause(node) {
85
+ const enclosingFn = getEnclosingFunction(node);
86
+ if (enclosingFn === null)
87
+ return;
88
+ const methodName = lifecycleMethodByFn.get(enclosingFn);
89
+ if (methodName === undefined)
90
+ return;
91
+ const statements = node.body.body;
92
+ if (statements.length === 0) {
93
+ context.report({
94
+ node: node.body,
95
+ messageId: 'emptyCatch',
96
+ data: { method: methodName },
97
+ });
98
+ return;
99
+ }
100
+ const onlyStatement = statements.length === 1 ? statements[0] : undefined;
101
+ if (onlyStatement && isSilentReturn(onlyStatement)) {
102
+ context.report({
103
+ node: onlyStatement,
104
+ messageId: 'silentReturn',
105
+ data: { method: methodName },
106
+ });
107
+ }
108
+ },
109
+ };
110
+ },
111
+ });
112
+ //# sourceMappingURL=no-silent-error-swallowing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-silent-error-swallowing.js","sourceRoot":"","sources":["../../src/rules/no-silent-error-swallowing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const RequireFilesArrayRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"filesEmpty" | "filesMissing", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
+ //# sourceMappingURL=require-files-array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-files-array.d.ts","sourceRoot":"","sources":["../../src/rules/require-files-array.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,qBAAqB,gKA4ChC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import { createRule, findJsonProperty, getTopLevelObjectInJson } from '../utils/index.js';
3
+ export const RequireFilesArrayRule = createRule({
4
+ name: 'require-files-array',
5
+ meta: {
6
+ type: 'problem',
7
+ docs: {
8
+ description: 'Require a non-empty "files" array in package.json',
9
+ },
10
+ messages: {
11
+ filesMissing: 'package.json must have a "files" field with a non-empty array of files to publish.',
12
+ filesEmpty: 'The "files" field must be a non-empty array.',
13
+ },
14
+ schema: [],
15
+ },
16
+ defaultOptions: [],
17
+ create(context) {
18
+ if (!context.filename.endsWith('package.json')) {
19
+ return {};
20
+ }
21
+ return {
22
+ ObjectExpression(node) {
23
+ const root = getTopLevelObjectInJson(node);
24
+ if (!root) {
25
+ return;
26
+ }
27
+ const filesProp = findJsonProperty(root, 'files');
28
+ if (!filesProp) {
29
+ context.report({ node: root, messageId: 'filesMissing' });
30
+ return;
31
+ }
32
+ const filesValue = filesProp.value;
33
+ if (filesValue.type !== AST_NODE_TYPES.ArrayExpression ||
34
+ filesValue.elements.length === 0) {
35
+ context.report({ node: filesProp, messageId: 'filesEmpty' });
36
+ }
37
+ },
38
+ };
39
+ },
40
+ });
41
+ //# sourceMappingURL=require-files-array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-files-array.js","sourceRoot":"","sources":["../../src/rules/require-files-array.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE1F,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC;IAC/C,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EAAE,mDAAmD;SAChE;QACD,QAAQ,EAAE;YACT,YAAY,EACX,oFAAoF;YACrF,UAAU,EAAE,8CAA8C;SAC1D;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAA+B;gBAC/C,MAAM,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;oBACX,OAAO;gBACR,CAAC;gBAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAClD,IAAI,CAAC,SAAS,EAAE,CAAC;oBAChB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;oBAC1D,OAAO;gBACR,CAAC;gBAED,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC;gBAEnC,IACC,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;oBAClD,UAAU,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAC/B,CAAC;oBACF,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;gBAC9D,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const RequireHomepageRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"homepageInvalid" | "homepageMissing", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
+ //# sourceMappingURL=require-homepage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-homepage.d.ts","sourceRoot":"","sources":["../../src/rules/require-homepage.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,mBAAmB,wKA4C9B,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import { createRule, findJsonProperty, getTopLevelObjectInJson } from '../utils/index.js';
3
+ function isValidUrl(value) {
4
+ try {
5
+ new URL(value);
6
+ return true;
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ export const RequireHomepageRule = createRule({
13
+ name: 'require-homepage',
14
+ meta: {
15
+ type: 'suggestion',
16
+ docs: {
17
+ description: 'Require a "homepage" field with a valid URL in package.json',
18
+ },
19
+ messages: {
20
+ homepageMissing: 'package.json must have a "homepage" field.',
21
+ homepageInvalid: 'The "homepage" field must be a valid URL (e.g. "https://example.com").',
22
+ },
23
+ schema: [],
24
+ },
25
+ defaultOptions: [],
26
+ create(context) {
27
+ if (!context.filename.endsWith('package.json')) {
28
+ return {};
29
+ }
30
+ return {
31
+ ObjectExpression(node) {
32
+ const root = getTopLevelObjectInJson(node);
33
+ if (!root) {
34
+ return;
35
+ }
36
+ const homepageProp = findJsonProperty(root, 'homepage');
37
+ if (!homepageProp) {
38
+ context.report({ node: root, messageId: 'homepageMissing' });
39
+ return;
40
+ }
41
+ const homepageValue = homepageProp.value;
42
+ const isValidHomepage = homepageValue.type === AST_NODE_TYPES.Literal &&
43
+ typeof homepageValue.value === 'string' &&
44
+ isValidUrl(homepageValue.value);
45
+ if (!isValidHomepage) {
46
+ context.report({ node: homepageProp, messageId: 'homepageInvalid' });
47
+ }
48
+ },
49
+ };
50
+ },
51
+ });
52
+ //# sourceMappingURL=require-homepage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-homepage.js","sourceRoot":"","sources":["../../src/rules/require-homepage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE1F,SAAS,UAAU,CAAC,KAAa;IAChC,IAAI,CAAC;QACJ,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QACf,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;IAC7C,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE;QACL,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACL,WAAW,EAAE,6DAA6D;SAC1E;QACD,QAAQ,EAAE;YACT,eAAe,EAAE,4CAA4C;YAC7D,eAAe,EAAE,wEAAwE;SACzF;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAA+B;gBAC/C,MAAM,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;oBACX,OAAO;gBACR,CAAC;gBAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBACxD,IAAI,CAAC,YAAY,EAAE,CAAC;oBACnB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;oBAC7D,OAAO;gBACR,CAAC;gBAED,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC;gBACzC,MAAM,eAAe,GACpB,aAAa,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;oBAC7C,OAAO,aAAa,CAAC,KAAK,KAAK,QAAQ;oBACvC,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAEjC,IAAI,CAAC,eAAe,EAAE,CAAC;oBACtB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBACtE,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-lifecycle-complete.d.ts","sourceRoot":"","sources":["../../src/rules/webhook-lifecycle-complete.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,4BAA4B,6MAkFvC,CAAC"}
1
+ {"version":3,"file":"webhook-lifecycle-complete.d.ts","sourceRoot":"","sources":["../../src/rules/webhook-lifecycle-complete.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,4BAA4B,6MAkFvC,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
- import { createRule, findClassProperty, findObjectProperty, isNodeTypeClass, } from '../utils/index.js';
3
- const REQUIRED_METHODS = ['checkExists', 'create', 'delete'];
2
+ import { createRule, findClassProperty, findObjectProperty, isNodeTypeClass, WEBHOOK_LIFECYCLE_METHODS, } from '../utils/index.js';
4
3
  /**
5
4
  * Returns true if the description declares webhook endpoints, indicating the
6
5
  * node is a webhook-based trigger that needs a complete lifecycle.
@@ -28,7 +27,7 @@ function isMethodProperty(property, name) {
28
27
  property.value.type === AST_NODE_TYPES.ArrowFunctionExpression);
29
28
  }
30
29
  function findMissingMethods(group) {
31
- return REQUIRED_METHODS.filter((method) => !group.properties.some((property) => isMethodProperty(property, method)));
30
+ return WEBHOOK_LIFECYCLE_METHODS.filter((method) => !group.properties.some((property) => isMethodProperty(property, method)));
32
31
  }
33
32
  export const WebhookLifecycleCompleteRule = createRule({
34
33
  name: 'webhook-lifecycle-complete',
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-lifecycle-complete.js","sourceRoot":"","sources":["../../src/rules/webhook-lifecycle-complete.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhook-lifecycle-complete.js","sourceRoot":"","sources":["../../src/rules/webhook-lifecycle-complete.ts"],"names":[],"mappings":"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"}