@blumintinc/eslint-plugin-blumint 1.12.6 → 1.14.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 (258) hide show
  1. package/README.md +171 -99
  2. package/lib/index.js +300 -17
  3. package/lib/rules/array-methods-this-context.js +20 -2
  4. package/lib/rules/avoid-utils-directory.js +11 -2
  5. package/lib/rules/class-methods-read-top-to-bottom.js +24 -5
  6. package/lib/rules/consistent-callback-naming.js +1 -1
  7. package/lib/rules/dynamic-https-errors.d.ts +3 -1
  8. package/lib/rules/dynamic-https-errors.js +48 -11
  9. package/lib/rules/enforce-assert-safe-object-key.d.ts +8 -0
  10. package/lib/rules/{enforce-assertSafe-object-key.js → enforce-assert-safe-object-key.js} +52 -96
  11. package/lib/rules/enforce-assert-throws.d.ts +3 -1
  12. package/lib/rules/enforce-assert-throws.js +493 -51
  13. package/lib/rules/enforce-boolean-naming-prefixes.d.ts +3 -1
  14. package/lib/rules/enforce-boolean-naming-prefixes.js +820 -39
  15. package/lib/rules/enforce-callable-types.js +4 -4
  16. package/lib/rules/enforce-callback-memo.js +143 -18
  17. package/lib/rules/enforce-centralized-mock-firestore.js +5 -2
  18. package/lib/rules/enforce-console-error.d.ts +3 -0
  19. package/lib/rules/enforce-console-error.js +278 -0
  20. package/lib/rules/enforce-css-media-queries.js +24 -46
  21. package/lib/rules/enforce-dynamic-file-naming.d.ts +2 -0
  22. package/lib/rules/enforce-dynamic-file-naming.js +53 -28
  23. package/lib/rules/enforce-dynamic-firebase-imports.js +100 -19
  24. package/lib/rules/enforce-dynamic-imports.js +1 -1
  25. package/lib/rules/enforce-early-destructuring.d.ts +2 -0
  26. package/lib/rules/enforce-early-destructuring.js +980 -0
  27. package/lib/rules/enforce-empty-object-check.d.ts +11 -0
  28. package/lib/rules/enforce-empty-object-check.js +502 -0
  29. package/lib/rules/enforce-exported-function-types.js +4 -4
  30. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.d.ts +2 -0
  31. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +262 -0
  32. package/lib/rules/enforce-firestore-doc-ref-generic.js +350 -3
  33. package/lib/rules/enforce-firestore-facade.js +349 -157
  34. package/lib/rules/enforce-firestore-rules-get-access.d.ts +3 -0
  35. package/lib/rules/enforce-firestore-rules-get-access.js +109 -0
  36. package/lib/rules/enforce-firestore-set-merge.js +3 -4
  37. package/lib/rules/enforce-global-constants.d.ts +4 -1
  38. package/lib/rules/enforce-global-constants.js +240 -12
  39. package/lib/rules/enforce-identifiable-firestore-type.js +108 -58
  40. package/lib/rules/enforce-memoize-async.d.ts +2 -1
  41. package/lib/rules/enforce-memoize-async.js +92 -27
  42. package/lib/rules/enforce-memoize-getters.d.ts +3 -0
  43. package/lib/rules/enforce-memoize-getters.js +147 -0
  44. package/lib/rules/enforce-microdiff.js +3 -2
  45. package/lib/rules/enforce-object-literal-as-const.js +4 -4
  46. package/lib/rules/enforce-positive-naming.js +9 -7
  47. package/lib/rules/enforce-props-argument-name.d.ts +2 -7
  48. package/lib/rules/enforce-props-argument-name.js +165 -151
  49. package/lib/rules/enforce-props-naming-consistency.d.ts +2 -0
  50. package/lib/rules/enforce-props-naming-consistency.js +145 -0
  51. package/lib/rules/enforce-querykey-ts.d.ts +9 -0
  52. package/lib/rules/enforce-querykey-ts.js +274 -0
  53. package/lib/rules/enforce-safe-stringify.js +1 -1
  54. package/lib/rules/enforce-serializable-params.js +3 -3
  55. package/lib/rules/enforce-singular-type-names.js +10 -6
  56. package/lib/rules/enforce-stable-hash-spread-props.d.ts +13 -0
  57. package/lib/rules/enforce-stable-hash-spread-props.js +342 -0
  58. package/lib/rules/enforce-storage-context.d.ts +9 -0
  59. package/lib/rules/enforce-storage-context.js +646 -0
  60. package/lib/rules/enforce-timestamp-now.js +23 -7
  61. package/lib/rules/enforce-transform-memoization.d.ts +4 -0
  62. package/lib/rules/enforce-transform-memoization.js +416 -0
  63. package/lib/rules/enforce-typescript-markdown-code-blocks.d.ts +1 -0
  64. package/lib/rules/enforce-typescript-markdown-code-blocks.js +100 -0
  65. package/lib/rules/enforce-unique-cursor-headers.d.ts +16 -0
  66. package/lib/rules/enforce-unique-cursor-headers.js +365 -0
  67. package/lib/rules/enforce-verb-noun-naming.js +90 -14
  68. package/lib/rules/ensure-pointer-events-none.js +28 -2
  69. package/lib/rules/export-if-in-doubt.js +27 -4
  70. package/lib/rules/extract-global-constants.js +92 -53
  71. package/lib/rules/fast-deep-equal-over-microdiff.d.ts +2 -1
  72. package/lib/rules/fast-deep-equal-over-microdiff.js +351 -83
  73. package/lib/rules/firestore-transaction-reads-before-writes.d.ts +1 -0
  74. package/lib/rules/firestore-transaction-reads-before-writes.js +277 -0
  75. package/lib/rules/flatten-push-calls.d.ts +2 -0
  76. package/lib/rules/flatten-push-calls.js +428 -0
  77. package/lib/rules/generic-starts-with-t.js +8 -2
  78. package/lib/rules/global-const-style.js +50 -19
  79. package/lib/rules/jsdoc-above-field.d.ts +11 -0
  80. package/lib/rules/jsdoc-above-field.js +208 -0
  81. package/lib/rules/key-only-outermost-element.js +21 -3
  82. package/lib/rules/logical-top-to-bottom-grouping.d.ts +5 -0
  83. package/lib/rules/logical-top-to-bottom-grouping.js +1258 -0
  84. package/lib/rules/memo-compare-deeply-complex-props.d.ts +3 -0
  85. package/lib/rules/memo-compare-deeply-complex-props.js +788 -0
  86. package/lib/rules/memo-nested-react-components.d.ts +8 -0
  87. package/lib/rules/memo-nested-react-components.js +410 -0
  88. package/lib/rules/memoize-root-level-hocs.d.ts +7 -0
  89. package/lib/rules/memoize-root-level-hocs.js +242 -0
  90. package/lib/rules/no-always-true-false-conditions.d.ts +2 -1
  91. package/lib/rules/no-always-true-false-conditions.js +68 -8
  92. package/lib/rules/no-array-length-in-deps.d.ts +12 -0
  93. package/lib/rules/no-array-length-in-deps.js +314 -0
  94. package/lib/rules/no-async-array-filter.js +5 -2
  95. package/lib/rules/no-async-foreach.js +210 -12
  96. package/lib/rules/no-circular-references.js +18 -17
  97. package/lib/rules/no-class-instance-destructuring.js +55 -12
  98. package/lib/rules/no-complex-cloud-params.js +22 -5
  99. package/lib/rules/no-compositing-layer-props.js +6 -4
  100. package/lib/rules/no-conditional-literals-in-jsx.js +37 -12
  101. package/lib/rules/no-console-error.d.ts +9 -0
  102. package/lib/rules/no-console-error.js +525 -0
  103. package/lib/rules/no-curly-brackets-around-commented-properties.d.ts +2 -0
  104. package/lib/rules/no-curly-brackets-around-commented-properties.js +258 -0
  105. package/lib/rules/no-empty-dependency-use-callbacks.d.ts +11 -0
  106. package/lib/rules/no-empty-dependency-use-callbacks.js +576 -0
  107. package/lib/rules/no-entire-object-hook-deps.d.ts +3 -1
  108. package/lib/rules/no-entire-object-hook-deps.js +320 -68
  109. package/lib/rules/no-excessive-parent-chain.d.ts +5 -0
  110. package/lib/rules/no-excessive-parent-chain.js +273 -0
  111. package/lib/rules/no-explicit-return-type.d.ts +2 -1
  112. package/lib/rules/no-explicit-return-type.js +215 -26
  113. package/lib/rules/no-filter-without-return.js +5 -1
  114. package/lib/rules/no-firestore-jest-mock.d.ts +2 -1
  115. package/lib/rules/no-firestore-jest-mock.js +126 -8
  116. package/lib/rules/no-firestore-object-arrays.js +398 -28
  117. package/lib/rules/no-handler-suffix.d.ts +12 -0
  118. package/lib/rules/no-handler-suffix.js +305 -0
  119. package/lib/rules/no-hungarian.js +14 -14
  120. package/lib/rules/no-inline-component-prop.d.ts +10 -0
  121. package/lib/rules/no-inline-component-prop.js +456 -0
  122. package/lib/rules/no-jsx-in-hooks.js +6 -1
  123. package/lib/rules/no-jsx-whitespace-literal.js +8 -2
  124. package/lib/rules/no-margin-properties.d.ts +7 -1
  125. package/lib/rules/no-margin-properties.js +22 -9
  126. package/lib/rules/no-memoize-on-static.js +9 -1
  127. package/lib/rules/no-misleading-boolean-prefixes.d.ts +7 -0
  128. package/lib/rules/no-misleading-boolean-prefixes.js +331 -0
  129. package/lib/rules/no-misused-switch-case.js +22 -1
  130. package/lib/rules/no-mixed-firestore-transactions.d.ts +3 -1
  131. package/lib/rules/no-mixed-firestore-transactions.js +296 -34
  132. package/lib/rules/no-mock-firebase-admin.js +5 -2
  133. package/lib/rules/no-object-values-on-strings.js +10 -2
  134. package/lib/rules/no-overridable-method-calls-in-constructor.d.ts +1 -0
  135. package/lib/rules/no-overridable-method-calls-in-constructor.js +272 -0
  136. package/lib/rules/no-passthrough-getters.d.ts +4 -0
  137. package/lib/rules/no-passthrough-getters.js +206 -0
  138. package/lib/rules/no-redundant-annotation-assertion.d.ts +2 -0
  139. package/lib/rules/no-redundant-annotation-assertion.js +402 -0
  140. package/lib/rules/no-redundant-param-types.js +16 -6
  141. package/lib/rules/no-redundant-this-params.d.ts +3 -0
  142. package/lib/rules/no-redundant-this-params.js +459 -0
  143. package/lib/rules/no-redundant-usecallback-wrapper.d.ts +8 -0
  144. package/lib/rules/no-redundant-usecallback-wrapper.js +328 -0
  145. package/lib/rules/no-res-error-status-in-onrequest.d.ts +4 -0
  146. package/lib/rules/no-res-error-status-in-onrequest.js +521 -0
  147. package/lib/rules/no-restricted-properties-fix.d.ts +12 -0
  148. package/lib/rules/no-restricted-properties-fix.js +173 -0
  149. package/lib/rules/no-separate-loading-state.d.ts +8 -0
  150. package/lib/rules/no-separate-loading-state.js +133 -0
  151. package/lib/rules/no-stale-state-across-await.d.ts +1 -0
  152. package/lib/rules/no-stale-state-across-await.js +185 -0
  153. package/lib/rules/no-static-constants-in-dynamic-files.d.ts +3 -0
  154. package/lib/rules/no-static-constants-in-dynamic-files.js +149 -0
  155. package/lib/rules/no-try-catch-already-exists-in-transaction.d.ts +1 -0
  156. package/lib/rules/no-try-catch-already-exists-in-transaction.js +342 -0
  157. package/lib/rules/no-type-assertion-returns.js +49 -49
  158. package/lib/rules/no-undefined-null-passthrough.js +217 -40
  159. package/lib/rules/no-unmemoized-memo-without-props.d.ts +8 -0
  160. package/lib/rules/no-unmemoized-memo-without-props.js +426 -0
  161. package/lib/rules/no-unnecessary-destructuring-rename.d.ts +2 -0
  162. package/lib/rules/no-unnecessary-destructuring-rename.js +347 -0
  163. package/lib/rules/no-unnecessary-destructuring.js +14 -4
  164. package/lib/rules/no-unnecessary-verb-suffix.js +2 -3
  165. package/lib/rules/no-unpinned-dependencies.js +36 -5
  166. package/lib/rules/no-unsafe-firestore-spread.js +8 -5
  167. package/lib/rules/no-unused-props.d.ts +5 -2
  168. package/lib/rules/no-unused-props.js +451 -112
  169. package/lib/rules/no-unused-usestate.js +6 -2
  170. package/lib/rules/no-useless-fragment.js +28 -2
  171. package/lib/rules/no-useless-usememo-primitives.d.ts +9 -0
  172. package/lib/rules/no-useless-usememo-primitives.js +393 -0
  173. package/lib/rules/no-usememo-for-pass-by-value.d.ts +13 -0
  174. package/lib/rules/no-usememo-for-pass-by-value.js +757 -0
  175. package/lib/rules/no-uuidv4-base62-as-key.js +18 -13
  176. package/lib/rules/omit-index-html.d.ts +2 -1
  177. package/lib/rules/omit-index-html.js +62 -7
  178. package/lib/rules/optimize-object-boolean-conditions.d.ts +1 -0
  179. package/lib/rules/optimize-object-boolean-conditions.js +236 -0
  180. package/lib/rules/parallelize-async-operations.d.ts +8 -0
  181. package/lib/rules/parallelize-async-operations.js +394 -0
  182. package/lib/rules/prefer-batch-operations.d.ts +1 -3
  183. package/lib/rules/prefer-batch-operations.js +228 -35
  184. package/lib/rules/prefer-block-comments-for-declarations.js +22 -7
  185. package/lib/rules/prefer-clone-deep.js +3 -3
  186. package/lib/rules/prefer-destructuring-no-class.d.ts +2 -1
  187. package/lib/rules/prefer-destructuring-no-class.js +244 -59
  188. package/lib/rules/prefer-docsetter-setall.d.ts +2 -0
  189. package/lib/rules/prefer-docsetter-setall.js +243 -0
  190. package/lib/rules/prefer-document-flattening.d.ts +4 -0
  191. package/lib/rules/prefer-document-flattening.js +239 -0
  192. package/lib/rules/prefer-field-paths-in-transforms.d.ts +7 -0
  193. package/lib/rules/prefer-field-paths-in-transforms.js +251 -0
  194. package/lib/rules/prefer-fragment-component.js +4 -4
  195. package/lib/rules/prefer-fragment-shorthand.js +2 -1
  196. package/lib/rules/prefer-getter-over-parameterless-method.d.ts +13 -0
  197. package/lib/rules/prefer-getter-over-parameterless-method.js +648 -0
  198. package/lib/rules/prefer-global-router-state-key.d.ts +7 -3
  199. package/lib/rules/prefer-global-router-state-key.js +305 -31
  200. package/lib/rules/prefer-memoized-props.d.ts +3 -0
  201. package/lib/rules/prefer-memoized-props.js +445 -0
  202. package/lib/rules/prefer-next-dynamic.d.ts +9 -0
  203. package/lib/rules/prefer-next-dynamic.js +357 -0
  204. package/lib/rules/prefer-nullish-coalescing-boolean-props.d.ts +1 -0
  205. package/lib/rules/prefer-nullish-coalescing-boolean-props.js +435 -0
  206. package/lib/rules/prefer-nullish-coalescing-override.d.ts +7 -0
  207. package/lib/rules/prefer-nullish-coalescing-override.js +188 -0
  208. package/lib/rules/prefer-params-over-parent-id.d.ts +5 -0
  209. package/lib/rules/prefer-params-over-parent-id.js +277 -0
  210. package/lib/rules/prefer-settings-object.js +23 -15
  211. package/lib/rules/prefer-type-alias-over-typeof-constant.d.ts +3 -0
  212. package/lib/rules/prefer-type-alias-over-typeof-constant.js +259 -0
  213. package/lib/rules/prefer-type-over-interface.js +7 -2
  214. package/lib/rules/prefer-url-tostring-over-tojson.d.ts +2 -0
  215. package/lib/rules/prefer-url-tostring-over-tojson.js +169 -0
  216. package/lib/rules/prefer-use-deep-compare-memo.d.ts +4 -0
  217. package/lib/rules/prefer-use-deep-compare-memo.js +431 -0
  218. package/lib/rules/prefer-usecallback-over-usememo-for-functions.js +25 -2
  219. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +24 -5
  220. package/lib/rules/prefer-utility-function-over-private-static.js +34 -2
  221. package/lib/rules/prevent-children-clobber.d.ts +2 -0
  222. package/lib/rules/prevent-children-clobber.js +536 -0
  223. package/lib/rules/react-memoize-literals.d.ts +4 -0
  224. package/lib/rules/react-memoize-literals.js +495 -0
  225. package/lib/rules/react-usememo-should-be-component.d.ts +2 -1
  226. package/lib/rules/react-usememo-should-be-component.js +144 -78
  227. package/lib/rules/require-dynamic-firebase-imports.js +2 -1
  228. package/lib/rules/require-hooks-default-params.js +17 -16
  229. package/lib/rules/require-https-error-cause.d.ts +4 -0
  230. package/lib/rules/require-https-error-cause.js +136 -0
  231. package/lib/rules/require-https-error.js +43 -21
  232. package/lib/rules/require-image-optimized.js +2 -2
  233. package/lib/rules/require-memo.js +12 -2
  234. package/lib/rules/require-memoize-jsx-returners.d.ts +3 -0
  235. package/lib/rules/require-memoize-jsx-returners.js +485 -0
  236. package/lib/rules/require-usememo-object-literals.js +9 -4
  237. package/lib/rules/semantic-function-prefixes.js +38 -18
  238. package/lib/rules/sync-onwrite-name-func.js +5 -1
  239. package/lib/rules/test-file-location-enforcement.d.ts +1 -0
  240. package/lib/rules/test-file-location-enforcement.js +57 -0
  241. package/lib/rules/use-custom-link.js +6 -1
  242. package/lib/rules/use-custom-router.js +6 -1
  243. package/lib/rules/use-latest-callback.d.ts +3 -0
  244. package/lib/rules/use-latest-callback.js +271 -0
  245. package/lib/rules/vertically-group-related-functions.d.ts +16 -0
  246. package/lib/rules/vertically-group-related-functions.js +480 -0
  247. package/lib/utils/ASTHelpers.d.ts +13 -1
  248. package/lib/utils/ASTHelpers.js +34 -0
  249. package/lib/utils/createRule.js +1 -1
  250. package/lib/utils/getMethodName.d.ts +27 -0
  251. package/lib/utils/getMethodName.js +35 -0
  252. package/lib/utils/graph/ClassGraphSorterReadability.js +1 -1
  253. package/lib/utils/ruleTester.d.ts +1 -0
  254. package/lib/utils/ruleTester.js +4 -1
  255. package/lib/utils/tsTypeClassifier.d.ts +30 -0
  256. package/lib/utils/tsTypeClassifier.js +149 -0
  257. package/package.json +23 -14
  258. package/lib/rules/enforce-assertSafe-object-key.d.ts +0 -2
@@ -3,6 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.reactUseMemoShouldBeComponent = void 0;
4
4
  const utils_1 = require("@typescript-eslint/utils");
5
5
  const createRule_1 = require("../utils/createRule");
6
+ const ARRAY_RETURNING_METHODS = new Set([
7
+ 'map',
8
+ 'flatMap',
9
+ 'filter',
10
+ 'concat',
11
+ 'slice',
12
+ ]);
6
13
  /**
7
14
  * Checks if a node is a JSX element or fragment
8
15
  */
@@ -24,6 +31,99 @@ const isJsxElement = (node) => {
24
31
  return (node.type === utils_1.AST_NODE_TYPES.JSXElement ||
25
32
  node.type === utils_1.AST_NODE_TYPES.JSXFragment);
26
33
  };
34
+ /**
35
+ * True if the resolved variable is referenced inside a JSX prop (attribute or spread).
36
+ */
37
+ const isUsedAsComponentProp = (context, variableName, node) => {
38
+ // Find containing function for proper scope acquisition
39
+ let current = node;
40
+ let fn;
41
+ while (current?.parent) {
42
+ current = current.parent;
43
+ if (current.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
44
+ current.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
45
+ current.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
46
+ fn = current;
47
+ break;
48
+ }
49
+ }
50
+ const sourceCode = context.sourceCode;
51
+ const scopeManager = sourceCode.scopeManager;
52
+ const scope = scopeManager &&
53
+ ((fn && scopeManager.acquire(fn)) || scopeManager.acquire(node));
54
+ if (!scopeManager || !scope) {
55
+ return true;
56
+ }
57
+ const variable = scope.variables.find((v) => v.name === variableName) ??
58
+ scope.upper?.variables.find((v) => v.name === variableName) ??
59
+ null;
60
+ if (!variable) {
61
+ return true;
62
+ }
63
+ for (const ref of variable.references) {
64
+ let p = ref.identifier.parent ?? null;
65
+ while (p) {
66
+ if (p.type === utils_1.AST_NODE_TYPES.JSXAttribute ||
67
+ p.type === utils_1.AST_NODE_TYPES.JSXSpreadAttribute) {
68
+ return true;
69
+ }
70
+ p = p.parent;
71
+ }
72
+ }
73
+ return false;
74
+ };
75
+ const isUsedAsJsxChild = (context, variableName, node) => {
76
+ // Traverse the nearest function (or program) to see if the identifier appears
77
+ // as a JSX child expression.
78
+ const sourceCode = context.sourceCode;
79
+ let container = sourceCode.ast;
80
+ let current = node;
81
+ while (current?.parent) {
82
+ current = current.parent;
83
+ if (current.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
84
+ current.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
85
+ current.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
86
+ container = current;
87
+ break;
88
+ }
89
+ }
90
+ let found = false;
91
+ const visited = new Set();
92
+ const visit = (n) => {
93
+ if (found || visited.has(n))
94
+ return;
95
+ visited.add(n);
96
+ if (n.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
97
+ n.expression.type === utils_1.AST_NODE_TYPES.Identifier &&
98
+ n.expression.name === variableName &&
99
+ n.parent &&
100
+ (n.parent.type === utils_1.AST_NODE_TYPES.JSXElement ||
101
+ n.parent.type === utils_1.AST_NODE_TYPES.JSXFragment) &&
102
+ n.parent.children.includes(n)) {
103
+ found = true;
104
+ return;
105
+ }
106
+ for (const key of Object.keys(n)) {
107
+ if (key === 'parent')
108
+ continue;
109
+ const value = n[key];
110
+ if (!value)
111
+ continue;
112
+ if (Array.isArray(value)) {
113
+ for (const child of value) {
114
+ if (child && typeof child.type === 'string') {
115
+ visit(child);
116
+ }
117
+ }
118
+ }
119
+ else if (value && typeof value.type === 'string') {
120
+ visit(value);
121
+ }
122
+ }
123
+ };
124
+ visit(container);
125
+ return found;
126
+ };
27
127
  /**
28
128
  * Checks if a variable is used multiple times in a component
29
129
  */
@@ -149,28 +249,13 @@ const containsJsxInFunction = (node) => {
149
249
  if (body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
150
250
  return containsJsxInBlockStatement(body);
151
251
  }
152
- // Check for array methods returning JSX
252
+ // Check for array methods returning arrays (do not flag arrays of JSX)
153
253
  if (body.type === utils_1.AST_NODE_TYPES.CallExpression) {
154
254
  if (body.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
155
255
  body.callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
156
- // Check array methods like map, filter, find, etc.
157
- const arrayMethods = [
158
- 'map',
159
- 'filter',
160
- 'find',
161
- 'findIndex',
162
- 'some',
163
- 'every',
164
- 'reduce',
165
- ];
166
- if (arrayMethods.includes(body.callee.property.name) &&
167
- body.arguments.length > 0) {
168
- const callback = body.arguments[0];
169
- if ((callback.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
170
- callback.type === utils_1.AST_NODE_TYPES.FunctionExpression) &&
171
- containsJsxInFunction(callback)) {
172
- return true;
173
- }
256
+ if (ARRAY_RETURNING_METHODS.has(body.callee.property.name)) {
257
+ // Returning an array (even if its elements are JSX) should not be flagged
258
+ return false;
174
259
  }
175
260
  }
176
261
  // Check for IIFE
@@ -239,70 +324,27 @@ const containsJsxInExpression = (node) => {
239
324
  }
240
325
  return containsJsxInObject(node);
241
326
  case utils_1.AST_NODE_TYPES.CallExpression:
242
- // Special case for array methods that return data structures with JSX
327
+ // Do not flag arrays of JSX: common array-producing patterns
243
328
  if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
244
- node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
245
- node.callee.property.name === 'map' &&
246
- node.arguments.length > 0) {
247
- const callback = node.arguments[0];
248
- if (callback.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
249
- callback.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
250
- // Check if the callback returns an object with both JSX and non-JSX properties
251
- if (callback.body.type !== utils_1.AST_NODE_TYPES.BlockStatement &&
252
- callback.body.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
253
- let hasNonJsxProperties = false;
254
- let hasJsxProperties = false;
255
- for (const property of callback.body.properties) {
256
- if (property.type === utils_1.AST_NODE_TYPES.Property && property.value) {
257
- if (isJsxElement(property.value)) {
258
- hasJsxProperties = true;
259
- }
260
- else if (property.value.type !== utils_1.AST_NODE_TYPES.ObjectExpression) {
261
- hasNonJsxProperties = true;
262
- }
263
- }
264
- }
265
- // If the object has both JSX and non-JSX properties, it's likely a data object
266
- if (hasNonJsxProperties && hasJsxProperties) {
267
- return false;
268
- }
269
- }
270
- // For other cases, check if the function returns JSX directly
271
- return containsJsxInFunction(callback);
329
+ node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
330
+ if (ARRAY_RETURNING_METHODS.has(node.callee.property.name)) {
331
+ return false;
272
332
  }
273
333
  }
334
+ // Array.from(...) returns an array as well
335
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
336
+ node.callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
337
+ node.callee.object.name === 'Array' &&
338
+ node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
339
+ node.callee.property.name === 'from') {
340
+ return false;
341
+ }
274
342
  // Check if it's an IIFE
275
343
  if (node.callee.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
276
344
  node.callee.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
277
345
  return containsJsxInFunction(node.callee);
278
346
  }
279
- // Check array methods
280
- if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
281
- node.callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
282
- const arrayMethods = [
283
- 'filter',
284
- 'find',
285
- 'findIndex',
286
- 'some',
287
- 'every',
288
- 'reduce',
289
- ];
290
- if (arrayMethods.includes(node.callee.property.name) &&
291
- node.arguments.length > 0) {
292
- const callback = node.arguments[0];
293
- if (callback.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
294
- callback.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
295
- return containsJsxInFunction(callback);
296
- }
297
- }
298
- }
299
- // Check arguments for JSX
300
- for (const arg of node.arguments) {
301
- if (arg.type !== utils_1.AST_NODE_TYPES.SpreadElement &&
302
- containsJsxInExpression(arg)) {
303
- return true;
304
- }
305
- }
347
+ // Do not flag based on JSX in arguments of non-IIFE calls
306
348
  return false;
307
349
  case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
308
350
  case utils_1.AST_NODE_TYPES.FunctionExpression:
@@ -371,8 +413,15 @@ const containsJsxInBlockStatement = (node) => {
371
413
  // Check variable declarations for JSX
372
414
  if (statement.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
373
415
  for (const declarator of statement.declarations) {
374
- if (declarator.init && containsJsxInExpression(declarator.init)) {
375
- return true;
416
+ if (declarator.init) {
417
+ // Ignore nested function expressions (helpers/callbacks) even if they return JSX
418
+ if (declarator.init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
419
+ declarator.init.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
420
+ continue;
421
+ }
422
+ if (containsJsxInExpression(declarator.init)) {
423
+ return true;
424
+ }
376
425
  }
377
426
  }
378
427
  }
@@ -441,7 +490,7 @@ exports.reactUseMemoShouldBeComponent = (0, createRule_1.createRule)({
441
490
  },
442
491
  schema: [],
443
492
  messages: {
444
- useMemoShouldBeComponent: 'useMemo returning JSX should be extracted into a separate component. Use React.memo() for component memoization instead.',
493
+ useMemoShouldBeComponent: 'useMemo result "{{memoName}}" returns JSX, which hides a component inside a memoized value. JSX needs component identity so React can manage props, state, and dev tooling; wrapping it in useMemo bypasses that boundary and makes reuse/debugging harder. Extract this JSX into its own component and memoize it with React.memo if stability is required.',
445
494
  },
446
495
  },
447
496
  defaultOptions: [],
@@ -454,15 +503,32 @@ exports.reactUseMemoShouldBeComponent = (0, createRule_1.createRule)({
454
503
  node.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
455
504
  node.parent.id.type === utils_1.AST_NODE_TYPES.Identifier) {
456
505
  const variableName = node.parent.id.name;
506
+ // Only report when the memoized value is used as a JSX child
507
+ if (!isUsedAsJsxChild(context, variableName, node)) {
508
+ return;
509
+ }
457
510
  // Check if the variable is used multiple times in the component
458
511
  if (isUsedMultipleTimes(variableName, node)) {
459
512
  // If the variable is used multiple times, allow it
460
513
  return;
461
514
  }
515
+ // Check if the variable is used as a prop value in a JSX element
516
+ if (isUsedAsComponentProp(context, variableName, node)) {
517
+ // If the variable is used as a prop value, allow it
518
+ return;
519
+ }
462
520
  }
521
+ const memoName = node.parent &&
522
+ node.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
523
+ node.parent.id.type === utils_1.AST_NODE_TYPES.Identifier
524
+ ? node.parent.id.name
525
+ : 'useMemo return value';
463
526
  context.report({
464
527
  node,
465
528
  messageId: 'useMemoShouldBeComponent',
529
+ data: {
530
+ memoName,
531
+ },
466
532
  });
467
533
  }
468
534
  },
@@ -14,7 +14,7 @@ exports.default = (0, createRule_1.createRule)({
14
14
  fixable: 'code',
15
15
  schema: [],
16
16
  messages: {
17
- requireDynamicImport: 'Firebase dependencies must be imported dynamically to reduce bundle size',
17
+ requireDynamicImport: 'Static Firebase import from "{{importSource}}" keeps the Firebase SDK in the initial bundle and blocks route-level code splitting. Use an `await import(\'{{importSource}}\')` dynamic import so Firebase loads only on the code path that needs it; type-only imports remain allowed.',
18
18
  },
19
19
  },
20
20
  defaultOptions: [],
@@ -72,6 +72,7 @@ exports.default = (0, createRule_1.createRule)({
72
72
  context.report({
73
73
  node,
74
74
  messageId: 'requireDynamicImport',
75
+ data: { importSource },
75
76
  fix(fixer) {
76
77
  const dynamicImport = createDynamicImport(node);
77
78
  return fixer.replaceText(node, dynamicImport);
@@ -14,7 +14,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
14
14
  fixable: 'code',
15
15
  schema: [],
16
16
  messages: {
17
- requireDefaultParams: 'React hooks with all optional parameters should default to an empty object',
17
+ requireDefaultParams: 'Hook "{{hookName}}" accepts an options object where every property is optional, but the parameter is not defaulted. When callers omit the argument the hook receives undefined, so destructuring or property access throws even though the fields are optional. Default the parameter to an empty object (e.g., "({ option } = {})") so the hook stays safe to call with no arguments.',
18
18
  },
19
19
  },
20
20
  defaultOptions: [],
@@ -81,8 +81,10 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
81
81
  'ArrowFunctionExpression, FunctionDeclaration'(node) {
82
82
  // Check if it's a hook function
83
83
  let isHook = false;
84
+ let hookName;
84
85
  if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
85
- isHook = node.id ? isHookName(node.id.name) : false;
86
+ hookName = node.id?.name;
87
+ isHook = hookName ? isHookName(hookName) : false;
86
88
  }
87
89
  else {
88
90
  const parent = node.parent;
@@ -90,12 +92,14 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
90
92
  parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
91
93
  parent.id &&
92
94
  parent.id.type === utils_1.AST_NODE_TYPES.Identifier) {
95
+ hookName = parent.id.name;
93
96
  isHook = isHookName(parent.id.name);
94
97
  }
95
98
  }
96
99
  if (!isHook) {
97
100
  return;
98
101
  }
102
+ const messageData = { hookName: hookName ?? 'this hook' };
99
103
  // Check if it has exactly one parameter
100
104
  if (node.params.length !== 1) {
101
105
  return;
@@ -121,10 +125,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
121
125
  context.report({
122
126
  node: param,
123
127
  messageId: 'requireDefaultParams',
128
+ data: messageData,
124
129
  fix(fixer) {
125
- const paramText = context
126
- .getSourceCode()
127
- .getText(param);
130
+ const paramText = context.sourceCode.getText(param);
128
131
  return fixer.replaceText(param, `${paramText} = {}`);
129
132
  },
130
133
  });
@@ -140,10 +143,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
140
143
  context.report({
141
144
  node: param,
142
145
  messageId: 'requireDefaultParams',
146
+ data: messageData,
143
147
  fix(fixer) {
144
- const paramText = context
145
- .getSourceCode()
146
- .getText(param);
148
+ const paramText = context.sourceCode.getText(param);
147
149
  return fixer.replaceText(param, `${paramText} = {}`);
148
150
  },
149
151
  });
@@ -152,7 +154,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
152
154
  }
153
155
  else {
154
156
  // If we can't find the type definition, check if it's defined in the same file
155
- const program = context.getSourceCode().ast;
157
+ const program = context.sourceCode.ast;
156
158
  const typeDefinitions = program.body.filter((node) => {
157
159
  if (node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration ||
158
160
  node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
@@ -172,10 +174,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
172
174
  context.report({
173
175
  node: param,
174
176
  messageId: 'requireDefaultParams',
177
+ data: messageData,
175
178
  fix(fixer) {
176
- const paramText = context
177
- .getSourceCode()
178
- .getText(param);
179
+ const paramText = context.sourceCode.getText(param);
179
180
  return fixer.replaceText(param, `${paramText} = {}`);
180
181
  },
181
182
  });
@@ -191,10 +192,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
191
192
  context.report({
192
193
  node: param,
193
194
  messageId: 'requireDefaultParams',
195
+ data: messageData,
194
196
  fix(fixer) {
195
- const paramText = context
196
- .getSourceCode()
197
- .getText(param);
197
+ const paramText = context.sourceCode.getText(param);
198
198
  return fixer.replaceText(param, `${paramText} = {}`);
199
199
  },
200
200
  });
@@ -214,8 +214,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
214
214
  context.report({
215
215
  node: param,
216
216
  messageId: 'requireDefaultParams',
217
+ data: messageData,
217
218
  fix(fixer) {
218
- const paramText = context.getSourceCode().getText(param);
219
+ const paramText = context.sourceCode.getText(param);
219
220
  return fixer.replaceText(param, `${paramText} = {}`);
220
221
  },
221
222
  });
@@ -0,0 +1,4 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ type MessageIds = 'missingCause' | 'causeNotCatchBinding' | 'missingCatchBinding';
3
+ export declare const requireHttpsErrorCause: TSESLint.RuleModule<MessageIds, [], TSESLint.RuleListener>;
4
+ export {};
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireHttpsErrorCause = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ const isHttpsErrorCallee = (callee) => {
7
+ if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
8
+ return callee.name === 'HttpsError';
9
+ }
10
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
11
+ return (callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
12
+ callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
13
+ callee.property.name === 'HttpsError');
14
+ }
15
+ return false;
16
+ };
17
+ const findVariableInScopeChain = (scope, name) => {
18
+ let currentScope = scope;
19
+ while (currentScope) {
20
+ const variable = currentScope.variables.find((item) => item.name === name);
21
+ if (variable) {
22
+ return variable;
23
+ }
24
+ currentScope = currentScope.upper;
25
+ }
26
+ return null;
27
+ };
28
+ exports.requireHttpsErrorCause = (0, createRule_1.createRule)({
29
+ name: 'require-https-error-cause',
30
+ meta: {
31
+ type: 'problem',
32
+ docs: {
33
+ description: 'Ensure HttpsError calls inside catch blocks pass the caught error as the fourth "cause" argument to preserve stack traces for monitoring.',
34
+ recommended: 'error',
35
+ },
36
+ schema: [],
37
+ messages: {
38
+ missingCause: 'HttpsError inside a catch block must pass the caught error as the fourth "cause" argument. Without the original error, the stack is lost and monitoring fingerprints degrade. Add {{catchName}} as the cause argument after the optional details parameter.',
39
+ causeNotCatchBinding: 'The fourth HttpsError argument should be the catch binding {{catchName}} so the original error stack is preserved for monitoring. Pass the catch variable instead of {{actual}}.',
40
+ missingCatchBinding: 'HttpsError inside a catch block needs a named catch binding so the original error can be forwarded as the fourth "cause" argument. Bind the error value (e.g., `catch (error)`) and pass that variable as the cause to keep the upstream stack trace.',
41
+ },
42
+ },
43
+ defaultOptions: [],
44
+ create(context) {
45
+ const sourceCode = context.getSourceCode();
46
+ const catchStack = [];
47
+ // ESLint 9 moves getScope onto sourceCode; ESLint 8 exposes context.getScope().
48
+ // This shim keeps the rule compatible until the codebase drops ESLint 8 support.
49
+ const getScopeForNode = (node) => {
50
+ const sourceCodeWithScope = sourceCode;
51
+ if (typeof sourceCodeWithScope.getScope === 'function') {
52
+ return sourceCodeWithScope.getScope(node);
53
+ }
54
+ return context.getScope();
55
+ };
56
+ const reportMissingCause = (node, catchName) => {
57
+ context.report({
58
+ node,
59
+ messageId: 'missingCause',
60
+ data: {
61
+ catchName,
62
+ },
63
+ });
64
+ };
65
+ const reportWrongCause = (node, catchName, actual) => {
66
+ context.report({
67
+ node,
68
+ messageId: 'causeNotCatchBinding',
69
+ data: {
70
+ catchName,
71
+ actual,
72
+ },
73
+ });
74
+ };
75
+ const isCatchBindingReference = (identifier, frame) => {
76
+ if (!frame.paramName || identifier.name !== frame.paramName) {
77
+ return false;
78
+ }
79
+ const variable = findVariableInScopeChain(getScopeForNode(identifier), identifier.name);
80
+ return (variable?.defs.some((definition) => definition.type === 'CatchClause' && definition.node === frame.node) ?? false);
81
+ };
82
+ const validateHttpsError = (node) => {
83
+ if (!catchStack.length) {
84
+ return;
85
+ }
86
+ if (!isHttpsErrorCallee(node.callee)) {
87
+ return;
88
+ }
89
+ const activeCatch = catchStack[catchStack.length - 1];
90
+ if (!activeCatch.paramName) {
91
+ context.report({
92
+ node,
93
+ messageId: 'missingCatchBinding',
94
+ });
95
+ return;
96
+ }
97
+ const catchName = activeCatch.paramName;
98
+ if (node.arguments.length < 4) {
99
+ reportMissingCause(node, catchName);
100
+ return;
101
+ }
102
+ const causeArg = node.arguments[3];
103
+ if (!causeArg || causeArg.type !== utils_1.AST_NODE_TYPES.Identifier) {
104
+ reportWrongCause(causeArg ?? node, catchName, causeArg
105
+ ? sourceCode.getText(causeArg)
106
+ : 'the missing cause argument');
107
+ return;
108
+ }
109
+ if (!isCatchBindingReference(causeArg, activeCatch)) {
110
+ reportWrongCause(causeArg, catchName, sourceCode.getText(causeArg));
111
+ }
112
+ };
113
+ return {
114
+ CatchClause(node) {
115
+ if (node.param?.type === utils_1.AST_NODE_TYPES.Identifier) {
116
+ catchStack.push({ paramName: node.param.name, node });
117
+ return;
118
+ }
119
+ // Destructured catch params (e.g., `catch ({ message })`) do not bind the
120
+ // full error object, so they cannot be forwarded as the HttpsError cause.
121
+ // Users should bind the error value (e.g., `catch (error)`) before rethrowing.
122
+ catchStack.push({ paramName: null, node });
123
+ },
124
+ 'CatchClause:exit'() {
125
+ catchStack.pop();
126
+ },
127
+ NewExpression(node) {
128
+ validateHttpsError(node);
129
+ },
130
+ CallExpression(node) {
131
+ validateHttpsError(node);
132
+ },
133
+ };
134
+ },
135
+ });
136
+ //# sourceMappingURL=require-https-error-cause.js.map
@@ -11,8 +11,8 @@ module.exports = (0, createRule_1.createRule)({
11
11
  },
12
12
  schema: [],
13
13
  messages: {
14
- useHttpsError: 'Use HttpsError instead of throw new Error in functions/src directory',
15
- useProprietaryHttpsError: 'Use our proprietary HttpsError instead of firebase-admin HttpsError',
14
+ useHttpsError: 'Throwing "{{constructorName}}" in Cloud Functions returns a generic 500 and drops the structured status code clients rely on. Throw the proprietary HttpsError instead so responses include the correct status, sanitized message, and logging context.',
15
+ useProprietaryHttpsError: '{{reference}} comes from {{source}} and bypasses our proprietary HttpsError wrapper, so responses skip standardized status codes, logging, and client-safe payloads. Import and throw HttpsError from @our-company/errors to keep errors consistent.',
16
16
  },
17
17
  },
18
18
  defaultOptions: [],
@@ -22,12 +22,20 @@ module.exports = (0, createRule_1.createRule)({
22
22
  if (!filename.includes('functions/src')) {
23
23
  return {};
24
24
  }
25
- let httpsIdentifier = null;
26
- let httpsErrorIdentifier = null;
25
+ const httpsIdentifiers = new Map();
26
+ const httpsErrorIdentifiers = new Map();
27
+ const reportProprietary = (node, data) => context.report({
28
+ node,
29
+ messageId: 'useProprietaryHttpsError',
30
+ data,
31
+ });
27
32
  return {
28
33
  ImportDeclaration(node) {
29
34
  if (node.source.value === 'firebase-admin' ||
30
35
  node.source.value === 'firebase-admin/lib/https-error') {
36
+ const sourceModule = String(node.source.value);
37
+ // Report imports immediately so the forbidden dependency is blocked even
38
+ // when unused; throw sites below also report to cover runtime usage.
31
39
  // Check for direct HttpsError import
32
40
  const httpsErrorSpecifier = node.specifiers.find((spec) => spec.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
33
41
  spec.imported.name === 'HttpsError');
@@ -35,17 +43,19 @@ module.exports = (0, createRule_1.createRule)({
35
43
  const httpsSpecifier = node.specifiers.find((spec) => spec.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
36
44
  spec.imported.name === 'https');
37
45
  if (httpsErrorSpecifier && 'local' in httpsErrorSpecifier) {
38
- httpsErrorIdentifier = httpsErrorSpecifier.local.name;
39
- context.report({
40
- node,
41
- messageId: 'useProprietaryHttpsError',
46
+ const localName = httpsErrorSpecifier.local.name;
47
+ httpsErrorIdentifiers.set(localName, sourceModule);
48
+ reportProprietary(node, {
49
+ reference: localName,
50
+ source: sourceModule,
42
51
  });
43
52
  }
44
53
  if (httpsSpecifier && 'local' in httpsSpecifier) {
45
- httpsIdentifier = httpsSpecifier.local.name;
46
- context.report({
47
- node,
48
- messageId: 'useProprietaryHttpsError',
54
+ const localName = httpsSpecifier.local.name;
55
+ httpsIdentifiers.set(localName, sourceModule);
56
+ reportProprietary(node, {
57
+ reference: `${localName}.HttpsError`,
58
+ source: sourceModule,
49
59
  });
50
60
  }
51
61
  }
@@ -65,22 +75,34 @@ module.exports = (0, createRule_1.createRule)({
65
75
  context.report({
66
76
  node,
67
77
  messageId: 'useHttpsError',
78
+ data: {
79
+ constructorName: callee.name,
80
+ },
68
81
  });
69
82
  return;
70
83
  }
71
84
  // Check for firebase-admin HttpsError usage
72
- const isFirebaseHttpsError = callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
85
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
73
86
  callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
74
- callee.object.name === httpsIdentifier &&
75
87
  callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
76
- callee.property.name === 'HttpsError';
77
- const isDirectHttpsError = callee.type === utils_1.AST_NODE_TYPES.Identifier &&
78
- callee.name === httpsErrorIdentifier;
79
- if (isFirebaseHttpsError || isDirectHttpsError) {
80
- context.report({
81
- node,
82
- messageId: 'useProprietaryHttpsError',
88
+ callee.property.name === 'HttpsError') {
89
+ const objectName = callee.object.name;
90
+ const source = httpsIdentifiers.get(objectName);
91
+ if (!source) {
92
+ return;
93
+ }
94
+ reportProprietary(node, {
95
+ reference: `${objectName}.HttpsError`,
96
+ source,
83
97
  });
98
+ return;
99
+ }
100
+ if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
101
+ const source = httpsErrorIdentifiers.get(callee.name);
102
+ if (!source) {
103
+ return;
104
+ }
105
+ reportProprietary(node, { reference: callee.name, source });
84
106
  }
85
107
  },
86
108
  };