@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
@@ -0,0 +1,357 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preferNextDynamic = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ const DEFAULT_USE_DYNAMIC_SOURCES = [
7
+ 'useDynamic',
8
+ './useDynamic',
9
+ '../hooks/useDynamic',
10
+ '../../hooks/useDynamic',
11
+ ];
12
+ function matchesAllowedSource(source, allowedSources) {
13
+ return allowedSources.some((pattern) => source === pattern || source.endsWith(`/${pattern}`));
14
+ }
15
+ function hasNodeStructure(value) {
16
+ return (!!value &&
17
+ typeof value === 'object' &&
18
+ 'type' in value &&
19
+ typeof value.type === 'string');
20
+ }
21
+ /**
22
+ * Walks the AST and invokes the visitor on each node.
23
+ * Uses WeakSet to prevent infinite cycles.
24
+ *
25
+ * @param visitor - Callback invoked on each node. Return `false` to stop
26
+ * traversal; return `undefined` (or nothing) to continue walking.
27
+ * @returns `false` if traversal stopped early; `true` when traversal completes.
28
+ */
29
+ function walkAst(node, visitor, visited = new WeakSet()) {
30
+ if (visited.has(node))
31
+ return true;
32
+ visited.add(node);
33
+ const shouldContinue = visitor(node);
34
+ if (shouldContinue === false)
35
+ return false;
36
+ const anyNode = node;
37
+ for (const key of Object.keys(anyNode)) {
38
+ if (key === 'parent')
39
+ continue;
40
+ const child = anyNode[key];
41
+ if (Array.isArray(child)) {
42
+ for (const c of child) {
43
+ if (hasNodeStructure(c)) {
44
+ if (!walkAst(c, visitor, visited))
45
+ return false;
46
+ }
47
+ }
48
+ }
49
+ else if (hasNodeStructure(child)) {
50
+ if (!walkAst(child, visitor, visited))
51
+ return false;
52
+ }
53
+ }
54
+ return true;
55
+ }
56
+ function isUseDynamicCall(node) {
57
+ const { callee, arguments: args } = node;
58
+ if (callee.type === utils_1.AST_NODE_TYPES.Identifier &&
59
+ callee.name === 'useDynamic' &&
60
+ args.length === 1 &&
61
+ args[0].type === utils_1.AST_NODE_TYPES.ImportExpression) {
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+ function findProgramNode(node) {
67
+ let current = node;
68
+ while (current && current.type !== utils_1.AST_NODE_TYPES.Program) {
69
+ current = current.parent;
70
+ }
71
+ return current || null;
72
+ }
73
+ function getImportDeclarations(program) {
74
+ return program.body.filter((n) => n.type === utils_1.AST_NODE_TYPES.ImportDeclaration);
75
+ }
76
+ function findUseDynamicImport(program, allowedSources) {
77
+ const imports = getImportDeclarations(program);
78
+ for (const imp of imports) {
79
+ if (typeof imp.source.value !== 'string')
80
+ continue;
81
+ const source = imp.source.value;
82
+ if (!matchesAllowedSource(source, allowedSources))
83
+ continue;
84
+ const importedUseDynamic = imp.specifiers.find((s) => (s.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
85
+ s.imported.type === utils_1.AST_NODE_TYPES.Identifier &&
86
+ s.imported.name === 'useDynamic') ||
87
+ s.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier ||
88
+ (s.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
89
+ s.local.name === 'useDynamic'));
90
+ if (importedUseDynamic && importedUseDynamic.local.name === 'useDynamic') {
91
+ return {
92
+ importNode: imp,
93
+ specifier: importedUseDynamic,
94
+ localName: importedUseDynamic.local.name,
95
+ };
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ function getNextDynamicLocalName(program) {
101
+ for (const imp of getImportDeclarations(program)) {
102
+ if (imp.source.value === 'next/dynamic') {
103
+ const def = imp.specifiers.find((s) => s.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier);
104
+ if (def)
105
+ return def.local.name;
106
+ }
107
+ }
108
+ return null;
109
+ }
110
+ function buildDynamicReplacement(call, variableKind, variableIdText, namedExportKey, sourceCode, dynamicIdent) {
111
+ const expr = buildDynamicExpression(call, namedExportKey, sourceCode, dynamicIdent);
112
+ return `${variableKind} ${variableIdText} = ${expr};`;
113
+ }
114
+ function buildDynamicExpression(call, namedExportKey, sourceCode, dynamicIdent) {
115
+ // call.arguments[0] is ImportExpression
116
+ const importExpr = call.arguments[0];
117
+ const importArgText = sourceCode.getText(importExpr.source);
118
+ const returnExpr = namedExportKey ? `mod.${namedExportKey}` : 'mod.default';
119
+ const dynamicText = `${dynamicIdent}(
120
+ async () => {
121
+ const mod = await import(${importArgText});
122
+ return ${returnExpr};
123
+ },
124
+ { ssr: false }
125
+ )`;
126
+ return dynamicText;
127
+ }
128
+ function inferVariableInfo(node) {
129
+ // Support: const Foo = useDynamic(import('...'));
130
+ // or: const { Picker } = useDynamic(import('...'));
131
+ const decl = node;
132
+ if (!decl.init || decl.init.type !== utils_1.AST_NODE_TYPES.CallExpression) {
133
+ return null;
134
+ }
135
+ if (!isUseDynamicCall(decl.init))
136
+ return null;
137
+ let kind = 'const';
138
+ const parent = decl.parent;
139
+ if (parent &&
140
+ parent.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
141
+ (parent.kind === 'const' || parent.kind === 'let' || parent.kind === 'var')) {
142
+ kind = parent.kind;
143
+ }
144
+ if (decl.id.type === utils_1.AST_NODE_TYPES.Identifier) {
145
+ return { kind, idText: decl.id.name, namedExportKey: null };
146
+ }
147
+ if (decl.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
148
+ // Only handle a single-property destructure like { Picker }
149
+ if (decl.id.properties.length !== 1) {
150
+ return null;
151
+ }
152
+ const prop = decl.id.properties[0];
153
+ if (prop && prop.type === utils_1.AST_NODE_TYPES.Property) {
154
+ const key = prop.key.type === utils_1.AST_NODE_TYPES.Identifier ? prop.key.name : null;
155
+ const valueName = prop.value.type === utils_1.AST_NODE_TYPES.Identifier ? prop.value.name : null;
156
+ if (key && valueName) {
157
+ return { kind, idText: valueName, namedExportKey: key };
158
+ }
159
+ }
160
+ }
161
+ return null;
162
+ }
163
+ exports.preferNextDynamic = (0, createRule_1.createRule)({
164
+ name: 'prefer-next-dynamic',
165
+ meta: {
166
+ type: 'problem',
167
+ docs: {
168
+ description: 'Prefer Next.js dynamic() over custom useDynamic() for component imports',
169
+ recommended: 'error',
170
+ requiresTypeChecking: false,
171
+ },
172
+ fixable: 'code',
173
+ schema: [
174
+ {
175
+ type: 'object',
176
+ properties: {
177
+ useDynamicSources: {
178
+ type: 'array',
179
+ items: { type: 'string' },
180
+ minItems: 1,
181
+ },
182
+ },
183
+ additionalProperties: false,
184
+ },
185
+ ],
186
+ messages: {
187
+ preferNextDynamic: 'Component "{{componentName}}" is created with useDynamic(import(...)), which bypasses Next.js dynamic() handling for client-only components and leaves SSR control to a custom wrapper. Wrap the import in dynamic(() => import(...), { ssr: false }) so Next.js manages code-splitting and disables server rendering safely.',
188
+ addNextDynamicImport: "The auto-fix will replace useDynamic(import(...)) with dynamic(() => import(...), { ssr: false }), which references Next.js's dynamic function. Without importing dynamic from 'next/dynamic', the fixed code will throw a ReferenceError at runtime when the module loads. Add `import dynamic from 'next/dynamic'` at the top of the file to make the dynamic identifier available.",
189
+ removeUseDynamicImport: 'Remove the unused useDynamic import after migrating to dynamic(); leaving the custom hook imported invites accidental reuse and keeps dead code in the bundle.',
190
+ },
191
+ },
192
+ defaultOptions: [{}],
193
+ create(context) {
194
+ const [options = {}] = context.options;
195
+ const allowedUseDynamicSources = options.useDynamicSources && options.useDynamicSources.length > 0
196
+ ? options.useDynamicSources
197
+ : DEFAULT_USE_DYNAMIC_SOURCES;
198
+ const sourceCode = context.sourceCode;
199
+ return {
200
+ VariableDeclarator(node) {
201
+ const info = inferVariableInfo(node);
202
+ if (!info)
203
+ return;
204
+ // For edge case 1 (Non-Component Imports): we conservatively only transform when the LHS is used in JSX.
205
+ // Heuristic: if identifier appears in any JSXOpeningElement as name, consider a component.
206
+ const program = findProgramNode(node);
207
+ if (!program)
208
+ return;
209
+ const useDynamicImportInfo = findUseDynamicImport(program, allowedUseDynamicSources);
210
+ if (!useDynamicImportInfo)
211
+ return;
212
+ const identifierName = info.idText;
213
+ // walkAst returns false when visitor returns false (early exit on match)
214
+ const usedInJsx = program.body.some((b) => walkAst(b, (n) => {
215
+ if (n.type === utils_1.AST_NODE_TYPES.JSXOpeningElement) {
216
+ const name = n.name;
217
+ if (name.type === utils_1.AST_NODE_TYPES.JSXIdentifier) {
218
+ if (name.name === identifierName) {
219
+ return false;
220
+ }
221
+ }
222
+ }
223
+ return undefined;
224
+ }) === false);
225
+ if (!usedInJsx) {
226
+ // Skip to avoid flagging non-component dynamic imports
227
+ return;
228
+ }
229
+ // Now we are confident enough to report and fix
230
+ const init = node.init;
231
+ const parentDecl = node.parent;
232
+ context.report({
233
+ node: init,
234
+ messageId: 'preferNextDynamic',
235
+ data: { componentName: identifierName },
236
+ fix(fixer) {
237
+ const fixes = [];
238
+ // ensure dynamic import is present
239
+ const programNode = program;
240
+ let dynamicLocal = getNextDynamicLocalName(programNode);
241
+ const hasDynamic = !!dynamicLocal;
242
+ if (!hasDynamic) {
243
+ // Insert after directive prologue (e.g., "use client")
244
+ const insertionIndex = programNode.body.findIndex((stmt) => {
245
+ return !(stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement &&
246
+ stmt.expression.type === utils_1.AST_NODE_TYPES.Literal &&
247
+ typeof stmt.expression.value === 'string');
248
+ });
249
+ const target = insertionIndex === -1
250
+ ? programNode.body[0]
251
+ : programNode.body[insertionIndex];
252
+ const indentation = '';
253
+ fixes.push(fixer.insertTextBefore(target, `${indentation}import dynamic from 'next/dynamic';\n`));
254
+ dynamicLocal = 'dynamic';
255
+ }
256
+ // Replace the variable declarator text with dynamic(...) usage
257
+ if (parentDecl.declarations.length === 1) {
258
+ const variableText = buildDynamicReplacement(init, parentDecl.kind, info.idText, info.namedExportKey, sourceCode, dynamicLocal || 'dynamic');
259
+ fixes.push(fixer.replaceText(parentDecl, variableText));
260
+ }
261
+ else {
262
+ // Multiple declarators:
263
+ if (node.id.type === utils_1.AST_NODE_TYPES.Identifier) {
264
+ // Replace only the initializer expression
265
+ const dynamicExpr = buildDynamicExpression(init, info.namedExportKey, sourceCode, dynamicLocal || 'dynamic');
266
+ fixes.push(fixer.replaceText(init, dynamicExpr));
267
+ }
268
+ else if (node.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
269
+ // Replace the whole declarator with "<localName> = dynamic(...)"
270
+ const dynamicExpr = buildDynamicExpression(init, info.namedExportKey, sourceCode, dynamicLocal || 'dynamic');
271
+ const replacement = `${info.idText} = ${dynamicExpr}`;
272
+ fixes.push(fixer.replaceText(node, replacement));
273
+ }
274
+ }
275
+ // Remove unused useDynamic import if present and no longer referenced
276
+ const latestUseDynamicImport = findUseDynamicImport(programNode, allowedUseDynamicSources);
277
+ if (latestUseDynamicImport) {
278
+ // Abort removal if there are other useDynamic(import(...)) calls in the file
279
+ const otherUseDynamicCalls = programNode.body.some((b) => walkAst(b, (n) => {
280
+ if (n.type === utils_1.AST_NODE_TYPES.CallExpression &&
281
+ isUseDynamicCall(n) &&
282
+ n !== init) {
283
+ return false;
284
+ }
285
+ return undefined;
286
+ }) === false);
287
+ if (otherUseDynamicCalls) {
288
+ return fixes; // keep the import; other occurrences still rely on it
289
+ }
290
+ // If import had only useDynamic, remove entire declaration; else remove just its specifier
291
+ const specifiers = latestUseDynamicImport.importNode.specifiers;
292
+ const useDynamicSpecifier = specifiers.find((s) => (s.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
293
+ s.imported.type === utils_1.AST_NODE_TYPES.Identifier &&
294
+ s.imported.name === 'useDynamic') ||
295
+ (s.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier &&
296
+ s.local.name === 'useDynamic') ||
297
+ (s.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
298
+ s.local.name === 'useDynamic'));
299
+ if (useDynamicSpecifier) {
300
+ if (specifiers.length === 1) {
301
+ // Remove entire import
302
+ fixes.push(fixer.remove(latestUseDynamicImport.importNode));
303
+ // If dynamic was already present (we didn't insert), collapse the extra newline left by removal
304
+ if (hasDynamic) {
305
+ const after = latestUseDynamicImport.importNode.range[1];
306
+ if (after < sourceCode.text.length) {
307
+ const ch = sourceCode.text[after];
308
+ if (ch === '\n' || ch === '\r') {
309
+ fixes.push(fixer.removeRange([after, after + 1]));
310
+ }
311
+ }
312
+ }
313
+ }
314
+ else {
315
+ // If only named specifiers exist, reconstruct a clean import text
316
+ const onlyNamed = specifiers.every((s) => s.type === utils_1.AST_NODE_TYPES.ImportSpecifier);
317
+ if (onlyNamed) {
318
+ const remaining = specifiers.filter((s) => s !== useDynamicSpecifier);
319
+ const specText = remaining
320
+ .map((s) => s.imported.name === s.local.name
321
+ ? s.local.name
322
+ : `${s.imported.name} as ${s.local.name}`)
323
+ .join(', ');
324
+ const newText = `import { ${specText} } from '${latestUseDynamicImport.importNode.source.value}';`;
325
+ fixes.push(fixer.replaceText(latestUseDynamicImport.importNode, newText));
326
+ }
327
+ else {
328
+ // Otherwise, remove the specifier with proper comma handling
329
+ const tokenAfter = sourceCode.getTokenAfter(useDynamicSpecifier);
330
+ const tokenBefore = sourceCode.getTokenBefore(useDynamicSpecifier);
331
+ if (tokenAfter && tokenAfter.value === ',') {
332
+ fixes.push(fixer.removeRange([
333
+ useDynamicSpecifier.range[0],
334
+ tokenAfter.range[1],
335
+ ]));
336
+ }
337
+ else if (tokenBefore && tokenBefore.value === ',') {
338
+ fixes.push(fixer.removeRange([
339
+ tokenBefore.range[0],
340
+ useDynamicSpecifier.range[1],
341
+ ]));
342
+ }
343
+ else {
344
+ fixes.push(fixer.remove(useDynamicSpecifier));
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
350
+ return fixes;
351
+ },
352
+ });
353
+ },
354
+ };
355
+ },
356
+ });
357
+ //# sourceMappingURL=prefer-next-dynamic.js.map
@@ -0,0 +1 @@
1
+ export declare const preferNullishCoalescingBooleanProps: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"preferNullishCoalescing", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;