@atlaskit/eslint-plugin-platform 2.7.2 → 2.9.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/CHANGELOG.md +16 -0
  2. package/dist/cjs/index.js +19 -3
  3. package/dist/cjs/rules/ensure-use-sync-external-store-server-snapshot/index.js +41 -0
  4. package/dist/cjs/rules/feature-gating/valid-gate-name/index.js +60 -0
  5. package/dist/cjs/rules/import/no-barrel-entry-imports/index.js +1279 -0
  6. package/dist/cjs/rules/import/no-barrel-entry-jest-mock/index.js +1659 -0
  7. package/dist/cjs/rules/import/no-conversation-assistant-barrel-imports/index.js +43 -0
  8. package/dist/cjs/rules/import/no-jest-mock-barrel-files/index.js +1402 -0
  9. package/dist/cjs/rules/import/no-relative-barrel-file-imports/index.js +781 -0
  10. package/dist/cjs/rules/import/shared/barrel-parsing.js +511 -0
  11. package/dist/cjs/rules/import/shared/file-system.js +186 -0
  12. package/dist/cjs/rules/import/shared/jest-utils.js +244 -0
  13. package/dist/cjs/rules/import/shared/package-registry.js +263 -0
  14. package/dist/cjs/rules/import/shared/package-resolution.js +318 -0
  15. package/dist/cjs/rules/import/shared/perf.js +89 -0
  16. package/dist/cjs/rules/import/shared/types.js +67 -0
  17. package/dist/cjs/rules/visit-example-type-import-required/index.js +409 -0
  18. package/dist/es2019/index.js +19 -3
  19. package/dist/es2019/rules/ensure-use-sync-external-store-server-snapshot/index.js +43 -0
  20. package/dist/es2019/rules/feature-gating/valid-gate-name/index.js +52 -0
  21. package/dist/es2019/rules/import/no-barrel-entry-imports/index.js +1158 -0
  22. package/dist/es2019/rules/import/no-barrel-entry-jest-mock/index.js +1341 -0
  23. package/dist/es2019/rules/import/no-conversation-assistant-barrel-imports/index.js +37 -0
  24. package/dist/es2019/rules/import/no-jest-mock-barrel-files/index.js +1180 -0
  25. package/dist/es2019/rules/import/no-relative-barrel-file-imports/index.js +742 -0
  26. package/dist/es2019/rules/import/shared/barrel-parsing.js +433 -0
  27. package/dist/es2019/rules/import/shared/file-system.js +174 -0
  28. package/dist/es2019/rules/import/shared/jest-utils.js +203 -0
  29. package/dist/es2019/rules/import/shared/package-registry.js +240 -0
  30. package/dist/es2019/rules/import/shared/package-resolution.js +253 -0
  31. package/dist/es2019/rules/import/shared/perf.js +83 -0
  32. package/dist/es2019/rules/import/shared/types.js +57 -0
  33. package/dist/es2019/rules/visit-example-type-import-required/index.js +375 -0
  34. package/dist/esm/index.js +19 -3
  35. package/dist/esm/rules/ensure-use-sync-external-store-server-snapshot/index.js +35 -0
  36. package/dist/esm/rules/feature-gating/valid-gate-name/index.js +53 -0
  37. package/dist/esm/rules/import/no-barrel-entry-imports/index.js +1272 -0
  38. package/dist/esm/rules/import/no-barrel-entry-jest-mock/index.js +1650 -0
  39. package/dist/esm/rules/import/no-conversation-assistant-barrel-imports/index.js +37 -0
  40. package/dist/esm/rules/import/no-jest-mock-barrel-files/index.js +1392 -0
  41. package/dist/esm/rules/import/no-relative-barrel-file-imports/index.js +774 -0
  42. package/dist/esm/rules/import/shared/barrel-parsing.js +500 -0
  43. package/dist/esm/rules/import/shared/file-system.js +176 -0
  44. package/dist/esm/rules/import/shared/jest-utils.js +231 -0
  45. package/dist/esm/rules/import/shared/package-registry.js +256 -0
  46. package/dist/esm/rules/import/shared/package-resolution.js +306 -0
  47. package/dist/esm/rules/import/shared/perf.js +80 -0
  48. package/dist/esm/rules/import/shared/types.js +61 -0
  49. package/dist/esm/rules/visit-example-type-import-required/index.js +402 -0
  50. package/dist/types/index.d.ts +28 -2
  51. package/dist/types/rules/ensure-use-sync-external-store-server-snapshot/index.d.ts +3 -0
  52. package/dist/types/rules/feature-gating/valid-gate-name/index.d.ts +3 -0
  53. package/dist/types/rules/import/no-barrel-entry-imports/index.d.ts +9 -0
  54. package/dist/types/rules/import/no-barrel-entry-jest-mock/index.d.ts +9 -0
  55. package/dist/types/rules/import/no-conversation-assistant-barrel-imports/index.d.ts +3 -0
  56. package/dist/types/rules/import/no-jest-mock-barrel-files/index.d.ts +22 -0
  57. package/dist/types/rules/import/no-relative-barrel-file-imports/index.d.ts +5 -0
  58. package/dist/types/rules/import/shared/barrel-parsing.d.ts +30 -0
  59. package/dist/types/rules/import/shared/file-system.d.ts +38 -0
  60. package/dist/types/rules/import/shared/jest-utils.d.ts +55 -0
  61. package/dist/types/rules/import/shared/package-registry.d.ts +26 -0
  62. package/dist/types/rules/import/shared/package-resolution.d.ts +58 -0
  63. package/dist/types/rules/import/shared/perf.d.ts +13 -0
  64. package/dist/types/rules/import/shared/types.d.ts +131 -0
  65. package/dist/types/rules/visit-example-type-import-required/index.d.ts +4 -0
  66. package/dist/types-ts4.5/index.d.ts +28 -2
  67. package/dist/types-ts4.5/rules/import/no-barrel-entry-imports/index.d.ts +9 -0
  68. package/dist/types-ts4.5/rules/import/no-barrel-entry-jest-mock/index.d.ts +9 -0
  69. package/dist/types-ts4.5/rules/import/no-conversation-assistant-barrel-imports/index.d.ts +3 -0
  70. package/dist/types-ts4.5/rules/import/no-jest-mock-barrel-files/index.d.ts +22 -0
  71. package/dist/types-ts4.5/rules/import/no-relative-barrel-file-imports/index.d.ts +5 -0
  72. package/dist/types-ts4.5/rules/import/shared/barrel-parsing.d.ts +30 -0
  73. package/dist/types-ts4.5/rules/import/shared/file-system.d.ts +38 -0
  74. package/dist/types-ts4.5/rules/import/shared/jest-utils.d.ts +55 -0
  75. package/dist/types-ts4.5/rules/import/shared/package-registry.d.ts +26 -0
  76. package/dist/types-ts4.5/rules/import/shared/package-resolution.d.ts +58 -0
  77. package/dist/types-ts4.5/rules/import/shared/perf.d.ts +13 -0
  78. package/dist/types-ts4.5/rules/import/shared/types.d.ts +131 -0
  79. package/dist/types-ts4.5/rules/visit-example-type-import-required/index.d.ts +4 -0
  80. package/package.json +6 -2
  81. package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +0 -158
  82. package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +0 -146
  83. package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +0 -151
  84. /package/dist/types-ts4.5/rules/{ensure-native-and-af-exports-synced → ensure-use-sync-external-store-server-snapshot}/index.d.ts +0 -0
  85. /package/dist/{types/rules/ensure-native-and-af-exports-synced → types-ts4.5/rules/feature-gating/valid-gate-name}/index.d.ts +0 -0
@@ -0,0 +1,1279 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createRule = createRule;
8
+ exports.default = void 0;
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
12
+ var _path = require("path");
13
+ var _barrelParsing = require("../shared/barrel-parsing");
14
+ var _fileSystem = require("../shared/file-system");
15
+ var _packageRegistry = require("../shared/package-registry");
16
+ var _packageResolution = require("../shared/package-resolution");
17
+ var _types = require("../shared/types");
18
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
19
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
20
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
21
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
22
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
23
+ /**
24
+ * Options for the no-barrel-entry-imports rule.
25
+ */
26
+
27
+ /**
28
+ * Represents a Jest automock call: jest.mock('path') with no additional arguments
29
+ */
30
+
31
+ /**
32
+ * Metadata for the ESLint rule
33
+ */
34
+ var ruleMeta = {
35
+ type: 'problem',
36
+ docs: {
37
+ description: 'Disallow importing from barrel files in entry points.',
38
+ category: 'Best Practices',
39
+ recommended: false
40
+ },
41
+ fixable: 'code',
42
+ schema: [{
43
+ type: 'object',
44
+ properties: {
45
+ applyToImportsFrom: {
46
+ type: 'array',
47
+ items: {
48
+ type: 'string'
49
+ },
50
+ description: 'The folder paths (relative to workspace root) containing packages whose imports will be checked and autofixed.'
51
+ }
52
+ },
53
+ additionalProperties: false
54
+ }],
55
+ messages: {
56
+ barrelEntryImport: "Importing from barrel file '{{path}}' is not allowed. Import directly from the source file using a more specific package.json export instead."
57
+ }
58
+ };
59
+
60
+ /**
61
+ * Get the imported name from an ImportSpecifier, handling both Identifier and Literal
62
+ */
63
+ function getImportedName(spec) {
64
+ var imported = spec.imported;
65
+ return imported.type === 'Identifier' ? imported.name : String(imported.value);
66
+ }
67
+
68
+ /**
69
+ * Build an import statement for a set of specifiers
70
+ */
71
+ function buildImportStatement(_ref) {
72
+ var specs = _ref.specs,
73
+ path = _ref.path,
74
+ quoteChar = _ref.quoteChar,
75
+ _ref$isTypeImport = _ref.isTypeImport,
76
+ isTypeImport = _ref$isTypeImport === void 0 ? false : _ref$isTypeImport;
77
+ var importNames = specs.map(function (spec) {
78
+ if (spec.type === 'ImportDefaultSpecifier') {
79
+ return spec.local.name;
80
+ } else if (spec.type === 'ImportSpecifier') {
81
+ var imported = getImportedName(spec);
82
+ var local = spec.local.name;
83
+ var isInlineType = spec.importKind === 'type' && !isTypeImport;
84
+ var prefix = isInlineType ? 'type ' : '';
85
+ return imported === local ? "".concat(prefix).concat(imported) : "".concat(prefix).concat(imported, " as ").concat(local);
86
+ }
87
+ return '';
88
+ }).filter(function (name) {
89
+ return name.length > 0;
90
+ });
91
+ if (importNames.length === 0) {
92
+ return '';
93
+ }
94
+ var typeKeyword = isTypeImport ? 'type ' : '';
95
+ var hasDefault = specs.some(function (spec) {
96
+ return spec.type === 'ImportDefaultSpecifier';
97
+ });
98
+ var hasNamed = specs.some(function (spec) {
99
+ return spec.type === 'ImportSpecifier';
100
+ });
101
+ if (hasDefault && hasNamed) {
102
+ var _specs$find;
103
+ var defaultName = (_specs$find = specs.find(function (spec) {
104
+ return spec.type === 'ImportDefaultSpecifier';
105
+ })) === null || _specs$find === void 0 ? void 0 : _specs$find.local.name;
106
+ var namedImports = specs.filter(function (spec) {
107
+ return spec.type === 'ImportSpecifier';
108
+ }).map(function (spec) {
109
+ var imported = getImportedName(spec);
110
+ var local = spec.local.name;
111
+ var isInlineType = spec.importKind === 'type' && !isTypeImport;
112
+ var prefix = isInlineType ? 'type ' : '';
113
+ return imported === local ? "".concat(prefix).concat(imported) : "".concat(prefix).concat(imported, " as ").concat(local);
114
+ }).join(', ');
115
+ return "import ".concat(typeKeyword).concat(defaultName, ", { ").concat(namedImports, " } from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
116
+ } else if (hasDefault) {
117
+ var _specs$find2;
118
+ var _defaultName = (_specs$find2 = specs.find(function (spec) {
119
+ return spec.type === 'ImportDefaultSpecifier';
120
+ })) === null || _specs$find2 === void 0 ? void 0 : _specs$find2.local.name;
121
+ return "import ".concat(typeKeyword).concat(_defaultName, " from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
122
+ } else {
123
+ return "import ".concat(typeKeyword, "{ ").concat(importNames.join(', '), " } from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Represents a specifier with its resolved target export path information.
129
+ */
130
+
131
+ /**
132
+ * Context resolved for an import that may be a barrel import.
133
+ */
134
+
135
+ /**
136
+ * Result of classifying specifiers by their target export paths.
137
+ */
138
+
139
+ /**
140
+ * Resolves import context for barrel file analysis from a module specifier string.
141
+ * Returns null if the import should not be processed (relative import, not in target folder, etc.)
142
+ */
143
+ function resolveImportContextFromModulePath(_ref2) {
144
+ var importPath = _ref2.importPath,
145
+ workspaceRoot = _ref2.workspaceRoot,
146
+ fs = _ref2.fs,
147
+ applyToImportsFrom = _ref2.applyToImportsFrom;
148
+ // Skip relative imports - this rule is for cross-package imports
149
+ if ((0, _fileSystem.isRelativeImport)(importPath)) {
150
+ return null;
151
+ }
152
+
153
+ // Extract the base package name (without subpath)
154
+ // e.g., "@atlassian/conversation-assistant-instrumentation" from
155
+ // "@atlassian/conversation-assistant-instrumentation" or
156
+ // "@atlassian/conversation-assistant-instrumentation/controllers/analytics"
157
+ var packageNameMatch = importPath.match(/^(@[^/]+\/[^/]+)/);
158
+ if (!packageNameMatch) {
159
+ return null;
160
+ }
161
+ var packageName = packageNameMatch[1];
162
+ var subPath = importPath.slice(packageName.length); // e.g., "" or "/controllers/analytics"
163
+
164
+ // Find the package (resolution is not constrained by applyToImportsFrom)
165
+ var packageDir = (0, _packageRegistry.findPackageInRegistry)({
166
+ packageName: packageName,
167
+ workspaceRoot: workspaceRoot,
168
+ fs: fs
169
+ });
170
+ if (!packageDir) {
171
+ return null;
172
+ }
173
+
174
+ // Only check imports from packages in our applyToImportsFrom folders
175
+ if (!(0, _packageRegistry.isPackageInApplyToImportsFrom)({
176
+ packageDir: packageDir,
177
+ workspaceRoot: workspaceRoot,
178
+ applyToImportsFrom: applyToImportsFrom
179
+ })) {
180
+ return null;
181
+ }
182
+
183
+ // Get the exports map for this package
184
+ var exportsMap = (0, _packageResolution.parsePackageExports)({
185
+ packageDir: packageDir,
186
+ fs: fs
187
+ });
188
+ if (exportsMap.size === 0) {
189
+ return null;
190
+ }
191
+
192
+ // Determine which export path we're importing from
193
+ // For bare package imports, it's ".", for subpath imports it's "./" + subPath
194
+ var currentExportPath = subPath ? '.' + subPath : '.';
195
+
196
+ // Get the resolved path for the current export (the entry point file for this import)
197
+ var entryFilePath = exportsMap.get(currentExportPath);
198
+ if (!entryFilePath) {
199
+ return null;
200
+ }
201
+
202
+ // Parse the entry file to find where each export originates
203
+ // Pass workspaceRoot to enable cross-package re-export resolution
204
+ var exportMap = (0, _barrelParsing.parseBarrelExports)({
205
+ barrelFilePath: entryFilePath,
206
+ fs: fs,
207
+ workspaceRoot: workspaceRoot
208
+ });
209
+ if (exportMap.size === 0) {
210
+ return null;
211
+ }
212
+ return {
213
+ importPath: importPath,
214
+ packageName: packageName,
215
+ currentExportPath: currentExportPath,
216
+ exportsMap: exportsMap,
217
+ exportMap: exportMap
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Resolves import context for barrel file analysis.
223
+ * Returns null if the import should not be processed (relative import, not in target folder, etc.)
224
+ */
225
+ function resolveImportContext(_ref3) {
226
+ var node = _ref3.node,
227
+ workspaceRoot = _ref3.workspaceRoot,
228
+ fs = _ref3.fs,
229
+ applyToImportsFrom = _ref3.applyToImportsFrom;
230
+ if (!node.source || typeof node.source.value !== 'string') {
231
+ return null;
232
+ }
233
+ return resolveImportContextFromModulePath({
234
+ importPath: node.source.value,
235
+ workspaceRoot: workspaceRoot,
236
+ fs: fs,
237
+ applyToImportsFrom: applyToImportsFrom
238
+ });
239
+ }
240
+
241
+ /**
242
+ * Classifies import specifiers by their target export paths.
243
+ * Groups specifiers that can be remapped to more specific exports.
244
+ * For cross-package re-exports, suggests importing from the source package's most specific subpath.
245
+ */
246
+ function classifySpecifiers(_ref4) {
247
+ var node = _ref4.node,
248
+ importContext = _ref4.importContext,
249
+ workspaceRoot = _ref4.workspaceRoot,
250
+ fs = _ref4.fs;
251
+ var currentExportPath = importContext.currentExportPath,
252
+ exportsMap = importContext.exportsMap,
253
+ exportMap = importContext.exportMap;
254
+ var specifiers = node.specifiers;
255
+ var specifiersByTarget = new Map();
256
+ var unmappedSpecifiers = [];
257
+ var hasNamespaceImport = false;
258
+
259
+ // Cache for source package exports maps to avoid redundant parsing
260
+ var sourcePackageExportsMaps = new Map();
261
+ var _iterator = _createForOfIteratorHelper(specifiers),
262
+ _step;
263
+ try {
264
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
265
+ var spec = _step.value;
266
+ if (spec.type === 'ImportNamespaceSpecifier') {
267
+ hasNamespaceImport = true;
268
+ continue;
269
+ }
270
+ var nameInSource = void 0;
271
+ var kind = 'value';
272
+ if (spec.type === 'ImportDefaultSpecifier') {
273
+ nameInSource = 'default';
274
+ } else if (spec.type === 'ImportSpecifier') {
275
+ nameInSource = getImportedName(spec);
276
+ var parentImportKind = node.importKind;
277
+ kind = parentImportKind === 'type' || spec.importKind === 'type' ? 'type' : 'value';
278
+ } else {
279
+ continue;
280
+ }
281
+ var exportInfo = exportMap.get(nameInSource);
282
+ if (exportInfo) {
283
+ var _exportInfo$crossPack, _exportInfo$originalN2, _matchResult$exportPa2;
284
+ var effectiveKind = kind === 'type' || exportInfo.isTypeOnly ? 'type' : 'value';
285
+
286
+ // Check if this is a cross-package re-export
287
+ var sourcePackageName = (_exportInfo$crossPack = exportInfo.crossPackageSource) === null || _exportInfo$crossPack === void 0 ? void 0 : _exportInfo$crossPack.packageName;
288
+ if (sourcePackageName) {
289
+ // For cross-package re-exports, find the most specific subpath in the source package
290
+ // Note: Package resolution is not constrained by applyToImportsFrom - any package can be resolved
291
+ var sourcePackageExportsMap = sourcePackageExportsMaps.get(sourcePackageName);
292
+ if (!sourcePackageExportsMap) {
293
+ var sourcePackageDir = (0, _packageRegistry.findPackageInRegistry)({
294
+ packageName: sourcePackageName,
295
+ workspaceRoot: workspaceRoot,
296
+ fs: fs
297
+ });
298
+ if (sourcePackageDir) {
299
+ sourcePackageExportsMap = (0, _packageResolution.parsePackageExports)({
300
+ packageDir: sourcePackageDir,
301
+ fs: fs
302
+ });
303
+ sourcePackageExportsMaps.set(sourcePackageName, sourcePackageExportsMap);
304
+ }
305
+ }
306
+
307
+ // Find the best export path in the source package
308
+ var _targetExportPath = null;
309
+ var resolvedOriginalName = exportInfo.originalName;
310
+ if (sourcePackageExportsMap) {
311
+ var _exportInfo$originalN, _matchResult$exportPa;
312
+ var _sourceExportName = (_exportInfo$originalN = exportInfo.originalName) !== null && _exportInfo$originalN !== void 0 ? _exportInfo$originalN : nameInSource;
313
+ var _matchResult = (0, _packageResolution.findExportForSourceFile)({
314
+ sourceFilePath: exportInfo.path,
315
+ exportsMap: sourcePackageExportsMap,
316
+ fs: fs,
317
+ sourceExportName: _sourceExportName
318
+ });
319
+ _targetExportPath = (_matchResult$exportPa = _matchResult === null || _matchResult === void 0 ? void 0 : _matchResult.exportPath) !== null && _matchResult$exportPa !== void 0 ? _matchResult$exportPa : null;
320
+ if ((_matchResult === null || _matchResult === void 0 ? void 0 : _matchResult.entryPointExportName) !== undefined) {
321
+ resolvedOriginalName = _matchResult.entryPointExportName === nameInSource ? undefined : _matchResult.entryPointExportName;
322
+ }
323
+ }
324
+
325
+ // Build the full import path: @package/subpath or just @package if no subpath found
326
+ var targetKey = _targetExportPath ? sourcePackageName + _targetExportPath.slice(1) // Remove leading '.' from subpath
327
+ : sourcePackageName;
328
+ if (!specifiersByTarget.has(targetKey)) {
329
+ specifiersByTarget.set(targetKey, []);
330
+ }
331
+ specifiersByTarget.get(targetKey).push({
332
+ spec: _objectSpread(_objectSpread({}, spec), {}, {
333
+ importKind: effectiveKind
334
+ }),
335
+ originalName: resolvedOriginalName,
336
+ targetExportPath: targetKey,
337
+ kind: effectiveKind,
338
+ sourcePackageName: sourcePackageName
339
+ });
340
+ continue;
341
+ }
342
+
343
+ // Find if there's a package.json export that points to this source file
344
+ var sourceExportName = (_exportInfo$originalN2 = exportInfo.originalName) !== null && _exportInfo$originalN2 !== void 0 ? _exportInfo$originalN2 : nameInSource;
345
+ var matchResult = (0, _packageResolution.findExportForSourceFile)({
346
+ sourceFilePath: exportInfo.path,
347
+ exportsMap: exportsMap,
348
+ fs: fs,
349
+ sourceExportName: sourceExportName
350
+ });
351
+ var targetExportPath = (_matchResult$exportPa2 = matchResult === null || matchResult === void 0 ? void 0 : matchResult.exportPath) !== null && _matchResult$exportPa2 !== void 0 ? _matchResult$exportPa2 : null;
352
+ var resolvedOriginalName2 = exportInfo.originalName;
353
+ if ((matchResult === null || matchResult === void 0 ? void 0 : matchResult.entryPointExportName) !== undefined) {
354
+ resolvedOriginalName2 = matchResult.entryPointExportName === nameInSource ? undefined : matchResult.entryPointExportName;
355
+ }
356
+
357
+ // Get the file that the current export path resolves to
358
+ var currentExportResolvedFile = exportsMap.get(currentExportPath);
359
+
360
+ // Skip if:
361
+ // 1. No target export path found
362
+ // 2. Target is same as current (no change needed)
363
+ // 3. Current export path already resolves to the same file as the source
364
+ // (handles multiple exports pointing to same file - avoid no-op changes)
365
+ var currentExportAlreadyPointsToSourceFile = currentExportResolvedFile !== undefined && currentExportResolvedFile === exportInfo.path;
366
+ if (targetExportPath && targetExportPath !== currentExportPath && !currentExportAlreadyPointsToSourceFile) {
367
+ if (!specifiersByTarget.has(targetExportPath)) {
368
+ specifiersByTarget.set(targetExportPath, []);
369
+ }
370
+ specifiersByTarget.get(targetExportPath).push({
371
+ spec: _objectSpread(_objectSpread({}, spec), {}, {
372
+ importKind: effectiveKind
373
+ }),
374
+ originalName: resolvedOriginalName2,
375
+ targetExportPath: targetExportPath,
376
+ kind: effectiveKind
377
+ });
378
+ } else {
379
+ // No more specific export available
380
+ unmappedSpecifiers.push({
381
+ spec: spec,
382
+ targetExportPath: null,
383
+ kind: kind
384
+ });
385
+ }
386
+ } else {
387
+ unmappedSpecifiers.push({
388
+ spec: spec,
389
+ targetExportPath: null,
390
+ kind: kind
391
+ });
392
+ }
393
+ }
394
+ } catch (err) {
395
+ _iterator.e(err);
396
+ } finally {
397
+ _iterator.f();
398
+ }
399
+ return {
400
+ specifiersByTarget: specifiersByTarget,
401
+ unmappedSpecifiers: unmappedSpecifiers,
402
+ hasNamespaceImport: hasNamespaceImport
403
+ };
404
+ }
405
+
406
+ /**
407
+ * Transforms a specifier to use the original export name (handling aliasing).
408
+ * Converts named imports of default exports to ImportDefaultSpecifier.
409
+ */
410
+ function transformSpecifierForExport(_ref5) {
411
+ var spec = _ref5.spec,
412
+ originalName = _ref5.originalName,
413
+ kind = _ref5.kind;
414
+ if (!originalName) {
415
+ return spec;
416
+ }
417
+ if (originalName === 'default') {
418
+ // Should be ImportDefaultSpecifier
419
+ if (spec.type === 'ImportDefaultSpecifier') {
420
+ return spec;
421
+ }
422
+ // Convert ImportSpecifier to ImportDefaultSpecifier
423
+ return {
424
+ type: 'ImportDefaultSpecifier',
425
+ local: spec.local,
426
+ range: spec.range,
427
+ loc: spec.loc,
428
+ parent: spec.parent
429
+ };
430
+ } else {
431
+ // Create synthetic ImportSpecifier with correct importKind
432
+ return {
433
+ type: 'ImportSpecifier',
434
+ local: spec.local,
435
+ imported: {
436
+ type: 'Identifier',
437
+ name: originalName,
438
+ range: [0, 0],
439
+ loc: {
440
+ start: {
441
+ line: 0,
442
+ column: 0
443
+ },
444
+ end: {
445
+ line: 0,
446
+ column: 0
447
+ }
448
+ }
449
+ },
450
+ importKind: kind,
451
+ range: spec.range,
452
+ loc: spec.loc,
453
+ parent: spec.parent
454
+ };
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Merges new specifiers with an existing import declaration.
460
+ * Returns the new import statement string.
461
+ */
462
+ function buildMergedImportStatement(_ref6) {
463
+ var existingImport = _ref6.existingImport,
464
+ newSpecs = _ref6.newSpecs,
465
+ newImportPath = _ref6.newImportPath,
466
+ nodeImportKind = _ref6.nodeImportKind,
467
+ quoteChar = _ref6.quoteChar;
468
+ var existingSpecs = existingImport.specifiers.map(function (s) {
469
+ if (existingImport.importKind === 'type') {
470
+ return _objectSpread(_objectSpread({}, s), {}, {
471
+ importKind: 'type'
472
+ });
473
+ }
474
+ return s;
475
+ });
476
+ var augmentedNewSpecs = newSpecs.map(function (s) {
477
+ if (nodeImportKind === 'type') {
478
+ return _objectSpread(_objectSpread({}, s), {}, {
479
+ importKind: 'type'
480
+ });
481
+ }
482
+ return s;
483
+ });
484
+ var mergedSpecs = [].concat((0, _toConsumableArray2.default)(existingSpecs), (0, _toConsumableArray2.default)(augmentedNewSpecs));
485
+
486
+ // Determine if we should use 'import type'
487
+ var allType = mergedSpecs.every(function (s) {
488
+ return s.importKind === 'type';
489
+ });
490
+ return buildImportStatement({
491
+ specs: mergedSpecs,
492
+ path: newImportPath,
493
+ quoteChar: quoteChar,
494
+ isTypeImport: allType
495
+ });
496
+ }
497
+
498
+ /**
499
+ * Check if an ExpressionStatement is a Jest automock: jest.mock('path') with exactly one string argument.
500
+ * Returns the JestAutomock info if it is, null otherwise.
501
+ */
502
+ function getJestAutomock(node) {
503
+ if (node.type !== 'ExpressionStatement') {
504
+ return null;
505
+ }
506
+ var statement = node;
507
+ var expr = statement.expression;
508
+ if (expr.type !== 'CallExpression') {
509
+ return null;
510
+ }
511
+
512
+ // Check for jest.mock(...)
513
+ var callee = expr.callee;
514
+ if (callee.type !== 'MemberExpression' || callee.object.type !== 'Identifier' || callee.object.name !== 'jest' || callee.property.type !== 'Identifier' || callee.property.name !== 'mock') {
515
+ return null;
516
+ }
517
+
518
+ // Must have exactly one argument (automock = no factory function)
519
+ if (expr.arguments.length !== 1) {
520
+ return null;
521
+ }
522
+ var arg = expr.arguments[0];
523
+ if (arg.type !== 'Literal' || typeof arg.value !== 'string') {
524
+ return null;
525
+ }
526
+
527
+ // Get the quote character from the raw value
528
+ var raw = arg.raw || "'".concat(arg.value, "'");
529
+ var quoteChar = raw[0];
530
+ return {
531
+ statementNode: statement,
532
+ path: arg.value,
533
+ quoteChar: quoteChar
534
+ };
535
+ }
536
+
537
+ /**
538
+ * Find all Jest automocks in the AST that match the given import path.
539
+ */
540
+ function findMatchingAutomocks(_ref7) {
541
+ var sourceCode = _ref7.sourceCode,
542
+ importPath = _ref7.importPath;
543
+ var automocks = [];
544
+ var ast = sourceCode.ast;
545
+ var _iterator2 = _createForOfIteratorHelper(ast.body),
546
+ _step2;
547
+ try {
548
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
549
+ var statement = _step2.value;
550
+ var automock = getJestAutomock(statement);
551
+ if (automock && automock.path === importPath) {
552
+ automocks.push(automock);
553
+ }
554
+ }
555
+ } catch (err) {
556
+ _iterator2.e(err);
557
+ } finally {
558
+ _iterator2.f();
559
+ }
560
+ return automocks;
561
+ }
562
+
563
+ /**
564
+ * Build a jest.mock() statement string
565
+ */
566
+ function buildAutomockStatement(_ref8) {
567
+ var path = _ref8.path,
568
+ quoteChar = _ref8.quoteChar;
569
+ return "jest.mock(".concat(quoteChar).concat(path).concat(quoteChar, ");");
570
+ }
571
+
572
+ /**
573
+ * Creates a fix to remove a node with proper whitespace handling.
574
+ * Removes surrounding newlines to avoid leaving blank lines.
575
+ */
576
+ function createNodeRemovalFix(_ref9) {
577
+ var fixer = _ref9.fixer,
578
+ node = _ref9.node,
579
+ sourceCode = _ref9.sourceCode;
580
+ var nodeStart = node.range[0];
581
+ var nodeEnd = node.range[1];
582
+
583
+ // Check for leading newline (prefer removing the line separator before the node)
584
+ var textBeforeNode = sourceCode.text.slice(0, nodeStart);
585
+ var leadingNewlineMatch = textBeforeNode.match(/(\r?\n)$/);
586
+ if (leadingNewlineMatch) {
587
+ // Remove the leading newline plus the node
588
+ return fixer.removeRange([nodeStart - leadingNewlineMatch[1].length, nodeEnd]);
589
+ }
590
+
591
+ // No leading newline - check for trailing newline
592
+ var textAfterNode = sourceCode.text.slice(nodeEnd);
593
+ var trailingNewlineMatch = textAfterNode.match(/^(\r?\n)/);
594
+ if (trailingNewlineMatch) {
595
+ return fixer.removeRange([nodeStart, nodeEnd + trailingNewlineMatch[1].length]);
596
+ }
597
+ return fixer.remove(node);
598
+ }
599
+
600
+ /**
601
+ * Creates the auto-fix for barrel import violations.
602
+ * Generates new import statements and handles merging with existing imports.
603
+ * Also updates Jest automocks (jest.mock calls with only a path) when present.
604
+ */
605
+ function createBarrelImportFix(_ref0) {
606
+ var fixer = _ref0.fixer,
607
+ node = _ref0.node,
608
+ context = _ref0.context,
609
+ importContext = _ref0.importContext,
610
+ specifiersByTarget = _ref0.specifiersByTarget,
611
+ unmappedSpecifiers = _ref0.unmappedSpecifiers;
612
+ var importPath = importContext.importPath,
613
+ packageName = importContext.packageName;
614
+ var sourceCode = context.sourceCode;
615
+ var quote = sourceCode.getText(node.source)[0]; // Get quote character
616
+
617
+ var fixes = [];
618
+ var newStatements = [];
619
+
620
+ // Find any Jest automocks that match this import path
621
+ var automocks = findMatchingAutomocks({
622
+ sourceCode: sourceCode,
623
+ importPath: importPath
624
+ });
625
+
626
+ // Track which new import paths need automocks (only value imports, not type-only)
627
+ var automockPaths = [];
628
+
629
+ // Track if we have any value imports at all (to determine if automocks should be updated)
630
+ var hasAnyValueImports = false;
631
+
632
+ // Get all existing imports to check for merging
633
+ var allImports = sourceCode.ast.body.filter(function (n) {
634
+ return n.type === 'ImportDeclaration' && n !== node;
635
+ });
636
+
637
+ // Generate new import statements for each target export path
638
+ var _iterator3 = _createForOfIteratorHelper(specifiersByTarget),
639
+ _step3;
640
+ try {
641
+ var _loop2 = function _loop2() {
642
+ var _step3$value = (0, _slicedToArray2.default)(_step3.value, 2),
643
+ targetExportPath = _step3$value[0],
644
+ specsWithTarget = _step3$value[1];
645
+ // Check if this is a cross-package re-export (sourcePackageName is set)
646
+ var isCrossPackage = specsWithTarget.some(function (s) {
647
+ return s.sourcePackageName;
648
+ });
649
+ var newImportPath = isCrossPackage ? targetExportPath // For cross-package, targetExportPath is already the full import path (e.g., @package/subpath)
650
+ : packageName + targetExportPath.slice(1); // Remove leading '.' for same-package imports
651
+
652
+ // Transform specifiers if needed (handle aliasing)
653
+ var specs = specsWithTarget.map(function (_ref10) {
654
+ var spec = _ref10.spec,
655
+ originalName = _ref10.originalName,
656
+ kind = _ref10.kind;
657
+ return transformSpecifierForExport({
658
+ spec: spec,
659
+ originalName: originalName,
660
+ kind: kind
661
+ });
662
+ });
663
+
664
+ // Check if any specifier in this group is a value import (not type-only)
665
+ // Only add automock paths for value imports (types don't need mocking at runtime)
666
+ if (automocks.length > 0) {
667
+ var hasValueImport = specsWithTarget.some(function (_ref11) {
668
+ var kind = _ref11.kind,
669
+ spec = _ref11.spec;
670
+ return kind === 'value' && (spec.type !== 'ImportSpecifier' || spec.importKind !== 'type');
671
+ });
672
+ if (hasValueImport) {
673
+ hasAnyValueImports = true;
674
+ automockPaths.push(newImportPath);
675
+ }
676
+ }
677
+
678
+ // Check for existing import from the same path
679
+ var existingImport = allImports.find(function (n) {
680
+ return n.source.value === newImportPath;
681
+ });
682
+
683
+ // Skip merging if existing is namespace import
684
+ var isNamespace = existingImport === null || existingImport === void 0 ? void 0 : existingImport.specifiers.some(function (s) {
685
+ return s.type === 'ImportNamespaceSpecifier';
686
+ });
687
+ if (existingImport && !isNamespace) {
688
+ // Merge with existing import
689
+ var newImportStatement = buildMergedImportStatement({
690
+ existingImport: existingImport,
691
+ newSpecs: specs,
692
+ newImportPath: newImportPath,
693
+ nodeImportKind: node.importKind,
694
+ quoteChar: quote
695
+ });
696
+ if (newImportStatement.length > 0) {
697
+ fixes.push(fixer.replaceText(existingImport, newImportStatement));
698
+ }
699
+ } else {
700
+ // Create new import
701
+ var _isTypeImport = node.importKind === 'type';
702
+ var importStatement = buildImportStatement({
703
+ specs: specs,
704
+ path: newImportPath,
705
+ quoteChar: quote,
706
+ isTypeImport: _isTypeImport
707
+ });
708
+ if (importStatement.length > 0) {
709
+ newStatements.push(importStatement);
710
+ }
711
+ }
712
+ };
713
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
714
+ _loop2();
715
+ }
716
+
717
+ // Handle unmapped specifiers - they stay in the original import
718
+ } catch (err) {
719
+ _iterator3.e(err);
720
+ } finally {
721
+ _iterator3.f();
722
+ }
723
+ if (unmappedSpecifiers.length > 0) {
724
+ var unmappedSpecs = unmappedSpecifiers.map(function (u) {
725
+ return u.spec;
726
+ });
727
+ var isTypeImport = node.importKind === 'type';
728
+ var remainingImport = buildImportStatement({
729
+ specs: unmappedSpecs,
730
+ path: importPath,
731
+ quoteChar: quote,
732
+ isTypeImport: isTypeImport
733
+ });
734
+ if (remainingImport.length > 0) {
735
+ newStatements.push(remainingImport);
736
+ }
737
+
738
+ // If there are unmapped value specifiers and automocks, keep the original automock path too
739
+ if (automocks.length > 0) {
740
+ var hasUnmappedValueImport = unmappedSpecifiers.some(function (_ref1) {
741
+ var kind = _ref1.kind,
742
+ spec = _ref1.spec;
743
+ return kind === 'value' && (spec.type !== 'ImportSpecifier' || spec.importKind !== 'type');
744
+ });
745
+ if (hasUnmappedValueImport) {
746
+ hasAnyValueImports = true;
747
+ automockPaths.push(importPath);
748
+ }
749
+ }
750
+ }
751
+ if (newStatements.length > 0) {
752
+ fixes.push(fixer.replaceText(node, newStatements.join('\n')));
753
+ } else {
754
+ // If all were merged, remove the node including surrounding whitespace/newlines
755
+ fixes.push(createNodeRemovalFix({
756
+ fixer: fixer,
757
+ node: node,
758
+ sourceCode: sourceCode
759
+ }));
760
+ }
761
+
762
+ // Handle automock updates
763
+ // Only modify automocks if there are value imports being fixed
764
+ // Type-only imports don't need runtime mocking, so we preserve existing automocks
765
+ if (automocks.length > 0 && hasAnyValueImports && automockPaths.length > 0) {
766
+ var _iterator4 = _createForOfIteratorHelper(automocks),
767
+ _step4;
768
+ try {
769
+ var _loop = function _loop() {
770
+ var automock = _step4.value;
771
+ // Build new automock statements for all new paths
772
+ var newAutomockStatements = automockPaths.map(function (path) {
773
+ return buildAutomockStatement({
774
+ path: path,
775
+ quoteChar: automock.quoteChar
776
+ });
777
+ });
778
+
779
+ // Replace the original automock statement with the new automock(s)
780
+ fixes.push(fixer.replaceTextRange(automock.statementNode.range, newAutomockStatements.join('\n')));
781
+ };
782
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
783
+ _loop();
784
+ }
785
+ } catch (err) {
786
+ _iterator4.e(err);
787
+ } finally {
788
+ _iterator4.f();
789
+ }
790
+ }
791
+ return fixes;
792
+ }
793
+ function isPlainRequireCall(node) {
794
+ if (node.callee.type !== 'Identifier' || node.callee.name !== 'require') {
795
+ return false;
796
+ }
797
+ if (node.arguments.length !== 1) {
798
+ return false;
799
+ }
800
+ var arg = node.arguments[0];
801
+ return arg.type === 'Literal' && typeof arg.value === 'string';
802
+ }
803
+ function unwrapToRequireCall(expr) {
804
+ var e = expr;
805
+ for (;;) {
806
+ var wrapped = e;
807
+ if (wrapped.type !== 'ParenthesizedExpression' || !wrapped.expression) {
808
+ break;
809
+ }
810
+ e = wrapped.expression;
811
+ }
812
+ if (e.type !== 'CallExpression' || !isPlainRequireCall(e)) {
813
+ return null;
814
+ }
815
+ return e;
816
+ }
817
+ function buildSyntheticImportFromRequireAccess(exportPropertyName, modulePath) {
818
+ var specifiers = exportPropertyName === 'default' ? [{
819
+ type: 'ImportDefaultSpecifier',
820
+ local: {
821
+ type: 'Identifier',
822
+ name: '_r'
823
+ }
824
+ }] : [{
825
+ type: 'ImportSpecifier',
826
+ imported: {
827
+ type: 'Identifier',
828
+ name: exportPropertyName
829
+ },
830
+ local: {
831
+ type: 'Identifier',
832
+ name: exportPropertyName
833
+ }
834
+ }];
835
+ return {
836
+ type: 'ImportDeclaration',
837
+ source: {
838
+ type: 'Literal',
839
+ value: modulePath,
840
+ raw: "'".concat(modulePath, "'")
841
+ },
842
+ specifiers: specifiers,
843
+ importKind: 'value'
844
+ };
845
+ }
846
+ function fullNewImportPathForTarget(targetKey, specsWithTarget, packageName) {
847
+ var isCrossPackage = specsWithTarget.some(function (s) {
848
+ return s.sourcePackageName;
849
+ });
850
+ return isCrossPackage ? targetKey : packageName + targetKey.slice(1);
851
+ }
852
+ function getRhsPropertyAfterTransform(spec) {
853
+ if (spec.type === 'ImportDefaultSpecifier') {
854
+ return 'default';
855
+ }
856
+ return getImportedName(spec);
857
+ }
858
+ function appendAutomockFixesForPathMigration(_ref12) {
859
+ var fixer = _ref12.fixer,
860
+ sourceCode = _ref12.sourceCode,
861
+ oldBarrelPath = _ref12.oldBarrelPath,
862
+ newPaths = _ref12.newPaths;
863
+ var automocks = findMatchingAutomocks({
864
+ sourceCode: sourceCode,
865
+ importPath: oldBarrelPath
866
+ });
867
+ if (automocks.length === 0 || newPaths.length === 0) {
868
+ return [];
869
+ }
870
+ var fixes = [];
871
+ var _iterator5 = _createForOfIteratorHelper(automocks),
872
+ _step5;
873
+ try {
874
+ var _loop3 = function _loop3() {
875
+ var automock = _step5.value;
876
+ var newAutomockStatements = newPaths.map(function (path) {
877
+ return buildAutomockStatement({
878
+ path: path,
879
+ quoteChar: automock.quoteChar
880
+ });
881
+ });
882
+ fixes.push(fixer.replaceTextRange(automock.statementNode.range, newAutomockStatements.join('\n')));
883
+ };
884
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
885
+ _loop3();
886
+ }
887
+ } catch (err) {
888
+ _iterator5.e(err);
889
+ } finally {
890
+ _iterator5.f();
891
+ }
892
+ return fixes;
893
+ }
894
+
895
+ /**
896
+ * `require('barrel').default` or `require('barrel').namedExport`
897
+ */
898
+ function handleRequireMemberExpression(_ref13) {
899
+ var node = _ref13.node,
900
+ context = _ref13.context,
901
+ workspaceRoot = _ref13.workspaceRoot,
902
+ fs = _ref13.fs,
903
+ applyToImportsFrom = _ref13.applyToImportsFrom;
904
+ if (node.computed || node.property.type !== 'Identifier') {
905
+ return;
906
+ }
907
+ var reqCall = unwrapToRequireCall(node.object);
908
+ if (!reqCall) {
909
+ return;
910
+ }
911
+ var modulePath = reqCall.arguments[0].value;
912
+ var importContext = resolveImportContextFromModulePath({
913
+ importPath: modulePath,
914
+ workspaceRoot: workspaceRoot,
915
+ fs: fs,
916
+ applyToImportsFrom: applyToImportsFrom
917
+ });
918
+ if (!importContext) {
919
+ return;
920
+ }
921
+ var exportPropertyName = node.property.name;
922
+ var synthetic = buildSyntheticImportFromRequireAccess(exportPropertyName, modulePath);
923
+ var _classifySpecifiers = classifySpecifiers({
924
+ node: synthetic,
925
+ importContext: importContext,
926
+ workspaceRoot: workspaceRoot,
927
+ fs: fs
928
+ }),
929
+ specifiersByTarget = _classifySpecifiers.specifiersByTarget,
930
+ hasNamespaceImport = _classifySpecifiers.hasNamespaceImport;
931
+ if (hasNamespaceImport || specifiersByTarget.size === 0) {
932
+ return;
933
+ }
934
+ var entries = (0, _toConsumableArray2.default)(specifiersByTarget.entries());
935
+ if (entries.length !== 1) {
936
+ return;
937
+ }
938
+ var _ref14 = entries[0],
939
+ _ref15 = (0, _slicedToArray2.default)(_ref14, 2),
940
+ targetKey = _ref15[0],
941
+ specsWithTarget = _ref15[1];
942
+ if (specsWithTarget.length !== 1) {
943
+ return;
944
+ }
945
+ var st = specsWithTarget[0];
946
+ var newImportPath = fullNewImportPathForTarget(targetKey, specsWithTarget, importContext.packageName);
947
+ var transformed = transformSpecifierForExport({
948
+ spec: st.spec,
949
+ originalName: st.originalName,
950
+ kind: st.kind
951
+ });
952
+ var newRhs = getRhsPropertyAfterTransform(transformed);
953
+ var sourceCode = context.getSourceCode();
954
+ var quote = sourceCode.getText(reqCall.arguments[0])[0];
955
+ context.report({
956
+ node: node,
957
+ messageId: 'barrelEntryImport',
958
+ data: {
959
+ path: importContext.importPath
960
+ },
961
+ fix: function fix(fixer) {
962
+ var fixes = [];
963
+ fixes.push(fixer.replaceText(node, "require(".concat(quote).concat(newImportPath).concat(quote, ").").concat(newRhs)));
964
+ if (st.kind === 'value') {
965
+ fixes.push.apply(fixes, (0, _toConsumableArray2.default)(appendAutomockFixesForPathMigration({
966
+ fixer: fixer,
967
+ sourceCode: sourceCode,
968
+ oldBarrelPath: modulePath,
969
+ newPaths: [newImportPath]
970
+ })));
971
+ }
972
+ return fixes;
973
+ }
974
+ });
975
+ }
976
+
977
+ /**
978
+ * `const { a, b } = require('barrel')`
979
+ */
980
+ function handleRequireDestructuringDeclarator(_ref16) {
981
+ var node = _ref16.node,
982
+ context = _ref16.context,
983
+ workspaceRoot = _ref16.workspaceRoot,
984
+ fs = _ref16.fs,
985
+ applyToImportsFrom = _ref16.applyToImportsFrom;
986
+ if (node.id.type !== 'ObjectPattern' || !node.init || node.init.type !== 'CallExpression') {
987
+ return;
988
+ }
989
+ var initCall = node.init;
990
+ if (!isPlainRequireCall(initCall)) {
991
+ return;
992
+ }
993
+ var modulePath = initCall.arguments[0].value;
994
+ var importContext = resolveImportContextFromModulePath({
995
+ importPath: modulePath,
996
+ workspaceRoot: workspaceRoot,
997
+ fs: fs,
998
+ applyToImportsFrom: applyToImportsFrom
999
+ });
1000
+ if (!importContext) {
1001
+ return;
1002
+ }
1003
+ var specifiers = [];
1004
+ var _iterator6 = _createForOfIteratorHelper(node.id.properties),
1005
+ _step6;
1006
+ try {
1007
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1008
+ var prop = _step6.value;
1009
+ if (prop.type !== 'Property' || prop.computed) {
1010
+ continue;
1011
+ }
1012
+ if (prop.key.type !== 'Identifier' || prop.value.type !== 'Identifier') {
1013
+ continue;
1014
+ }
1015
+ var importedName = prop.key.name;
1016
+ var localName = prop.value.name;
1017
+ specifiers.push({
1018
+ type: 'ImportSpecifier',
1019
+ imported: {
1020
+ type: 'Identifier',
1021
+ name: importedName
1022
+ },
1023
+ local: {
1024
+ type: 'Identifier',
1025
+ name: localName
1026
+ }
1027
+ });
1028
+ }
1029
+ } catch (err) {
1030
+ _iterator6.e(err);
1031
+ } finally {
1032
+ _iterator6.f();
1033
+ }
1034
+ if (specifiers.length === 0) {
1035
+ return;
1036
+ }
1037
+ var synthetic = {
1038
+ type: 'ImportDeclaration',
1039
+ source: {
1040
+ type: 'Literal',
1041
+ value: modulePath,
1042
+ raw: "'".concat(modulePath, "'")
1043
+ },
1044
+ specifiers: specifiers,
1045
+ importKind: 'value'
1046
+ };
1047
+ var _classifySpecifiers2 = classifySpecifiers({
1048
+ node: synthetic,
1049
+ importContext: importContext,
1050
+ workspaceRoot: workspaceRoot,
1051
+ fs: fs
1052
+ }),
1053
+ specifiersByTarget = _classifySpecifiers2.specifiersByTarget,
1054
+ unmappedSpecifiers = _classifySpecifiers2.unmappedSpecifiers,
1055
+ hasNamespaceImport = _classifySpecifiers2.hasNamespaceImport;
1056
+ if (hasNamespaceImport || specifiersByTarget.size === 0 || unmappedSpecifiers.length > 0) {
1057
+ return;
1058
+ }
1059
+ var parentDecl = node.parent;
1060
+ if (parentDecl.type !== 'VariableDeclaration') {
1061
+ return;
1062
+ }
1063
+ if (specifiersByTarget.size > 1 && parentDecl.declarations.length !== 1) {
1064
+ return;
1065
+ }
1066
+ var sourceCode = context.getSourceCode();
1067
+ var quote = sourceCode.getText(initCall.arguments[0])[0];
1068
+ var pkg = importContext.packageName;
1069
+ var buildFixes = function buildFixes(fixer) {
1070
+ var fixes = [];
1071
+ var hasValue = false;
1072
+ var automockPaths = [];
1073
+ if (specifiersByTarget.size === 1) {
1074
+ var _ref17 = (0, _toConsumableArray2.default)(specifiersByTarget.entries())[0],
1075
+ _ref18 = (0, _slicedToArray2.default)(_ref17, 2),
1076
+ targetKey = _ref18[0],
1077
+ specsWithTarget = _ref18[1];
1078
+ var newImportPath = fullNewImportPathForTarget(targetKey, specsWithTarget, pkg);
1079
+ if (specsWithTarget.some(function (s) {
1080
+ return s.kind === 'value';
1081
+ })) {
1082
+ hasValue = true;
1083
+ automockPaths.push(newImportPath);
1084
+ }
1085
+ fixes.push(fixer.replaceText(initCall.arguments[0], "".concat(quote).concat(newImportPath).concat(quote)));
1086
+ } else {
1087
+ var lines = [];
1088
+ var _iterator7 = _createForOfIteratorHelper(specifiersByTarget),
1089
+ _step7;
1090
+ try {
1091
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1092
+ var _step7$value = (0, _slicedToArray2.default)(_step7.value, 2),
1093
+ _targetKey = _step7$value[0],
1094
+ _specsWithTarget = _step7$value[1];
1095
+ var _newImportPath = fullNewImportPathForTarget(_targetKey, _specsWithTarget, pkg);
1096
+ if (_specsWithTarget.some(function (s) {
1097
+ return s.kind === 'value';
1098
+ })) {
1099
+ hasValue = true;
1100
+ automockPaths.push(_newImportPath);
1101
+ }
1102
+ var _iterator8 = _createForOfIteratorHelper(_specsWithTarget),
1103
+ _step8;
1104
+ try {
1105
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1106
+ var st = _step8.value;
1107
+ var transformed = transformSpecifierForExport({
1108
+ spec: st.spec,
1109
+ originalName: st.originalName,
1110
+ kind: st.kind
1111
+ });
1112
+ var rhs = getRhsPropertyAfterTransform(transformed);
1113
+ var local = st.spec.local.name;
1114
+ lines.push("".concat(local, " = require(").concat(quote).concat(_newImportPath).concat(quote, ").").concat(rhs));
1115
+ }
1116
+ } catch (err) {
1117
+ _iterator8.e(err);
1118
+ } finally {
1119
+ _iterator8.f();
1120
+ }
1121
+ }
1122
+ } catch (err) {
1123
+ _iterator7.e(err);
1124
+ } finally {
1125
+ _iterator7.f();
1126
+ }
1127
+ var declText = lines.map(function (l) {
1128
+ return "".concat(parentDecl.kind, " ").concat(l, ";");
1129
+ }).join('\n');
1130
+ fixes.push(fixer.replaceText(parentDecl, declText));
1131
+ }
1132
+ if (hasValue) {
1133
+ fixes.push.apply(fixes, (0, _toConsumableArray2.default)(appendAutomockFixesForPathMigration({
1134
+ fixer: fixer,
1135
+ sourceCode: sourceCode,
1136
+ oldBarrelPath: modulePath,
1137
+ newPaths: (0, _toConsumableArray2.default)(new Set(automockPaths))
1138
+ })));
1139
+ }
1140
+ return fixes;
1141
+ };
1142
+ context.report({
1143
+ node: initCall,
1144
+ messageId: 'barrelEntryImport',
1145
+ data: {
1146
+ path: importContext.importPath
1147
+ },
1148
+ fix: buildFixes
1149
+ });
1150
+ }
1151
+
1152
+ /**
1153
+ * Handles an ImportDeclaration node to check for barrel file imports.
1154
+ * Reports and auto-fixes imports that could use more specific export paths.
1155
+ */
1156
+ function handleImportDeclaration(_ref19) {
1157
+ var node = _ref19.node,
1158
+ context = _ref19.context,
1159
+ workspaceRoot = _ref19.workspaceRoot,
1160
+ fs = _ref19.fs,
1161
+ applyToImportsFrom = _ref19.applyToImportsFrom;
1162
+ // Resolve import context (validates and extracts package/export info)
1163
+ // applyToImportsFrom is used here to filter which packages the rule applies to
1164
+ var importContext = resolveImportContext({
1165
+ node: node,
1166
+ workspaceRoot: workspaceRoot,
1167
+ fs: fs,
1168
+ applyToImportsFrom: applyToImportsFrom
1169
+ });
1170
+ if (!importContext) {
1171
+ return;
1172
+ }
1173
+
1174
+ // Check each imported specifier to see if we can find a more specific export
1175
+ if (node.specifiers.length === 0) {
1176
+ return;
1177
+ }
1178
+
1179
+ // Classify specifiers by their target export paths
1180
+ var _classifySpecifiers3 = classifySpecifiers({
1181
+ node: node,
1182
+ importContext: importContext,
1183
+ workspaceRoot: workspaceRoot,
1184
+ fs: fs
1185
+ }),
1186
+ specifiersByTarget = _classifySpecifiers3.specifiersByTarget,
1187
+ unmappedSpecifiers = _classifySpecifiers3.unmappedSpecifiers,
1188
+ hasNamespaceImport = _classifySpecifiers3.hasNamespaceImport;
1189
+
1190
+ // If namespace import, report without auto-fix if there are specific exports available
1191
+ if (hasNamespaceImport) {
1192
+ if (specifiersByTarget.size > 0) {
1193
+ context.report({
1194
+ node: node,
1195
+ messageId: 'barrelEntryImport',
1196
+ data: {
1197
+ path: importContext.importPath
1198
+ }
1199
+ });
1200
+ }
1201
+ return;
1202
+ }
1203
+
1204
+ // If no specifiers can be remapped to more specific imports, don't report
1205
+ if (specifiersByTarget.size === 0) {
1206
+ return;
1207
+ }
1208
+
1209
+ // Report with auto-fix
1210
+ context.report({
1211
+ node: node,
1212
+ messageId: 'barrelEntryImport',
1213
+ data: {
1214
+ path: importContext.importPath
1215
+ },
1216
+ fix: function fix(fixer) {
1217
+ return createBarrelImportFix({
1218
+ fixer: fixer,
1219
+ node: node,
1220
+ context: context,
1221
+ importContext: importContext,
1222
+ specifiersByTarget: specifiersByTarget,
1223
+ unmappedSpecifiers: unmappedSpecifiers
1224
+ });
1225
+ }
1226
+ });
1227
+ }
1228
+
1229
+ /**
1230
+ * Factory function to create the ESLint rule with a given file system.
1231
+ * This enables testing with mock file systems.
1232
+ */
1233
+ function createRule(fs) {
1234
+ return {
1235
+ meta: ruleMeta,
1236
+ create: function create(context) {
1237
+ var _options$applyToImpor;
1238
+ var options = context.options[0] || {};
1239
+ var applyToImportsFrom = (_options$applyToImpor = options.applyToImportsFrom) !== null && _options$applyToImpor !== void 0 ? _options$applyToImpor : _fileSystem.DEFAULT_TARGET_FOLDERS;
1240
+ var workspaceRoot = (0, _fileSystem.findWorkspaceRoot)({
1241
+ startPath: (0, _path.dirname)(context.filename),
1242
+ fs: fs,
1243
+ applyToImportsFrom: applyToImportsFrom
1244
+ });
1245
+ return {
1246
+ ImportDeclaration: function ImportDeclaration(rawNode) {
1247
+ var node = rawNode;
1248
+ handleImportDeclaration({
1249
+ node: node,
1250
+ context: context,
1251
+ workspaceRoot: workspaceRoot,
1252
+ fs: fs,
1253
+ applyToImportsFrom: applyToImportsFrom
1254
+ });
1255
+ },
1256
+ MemberExpression: function MemberExpression(rawNode) {
1257
+ handleRequireMemberExpression({
1258
+ node: rawNode,
1259
+ context: context,
1260
+ workspaceRoot: workspaceRoot,
1261
+ fs: fs,
1262
+ applyToImportsFrom: applyToImportsFrom
1263
+ });
1264
+ },
1265
+ VariableDeclarator: function VariableDeclarator(rawNode) {
1266
+ handleRequireDestructuringDeclarator({
1267
+ node: rawNode,
1268
+ context: context,
1269
+ workspaceRoot: workspaceRoot,
1270
+ fs: fs,
1271
+ applyToImportsFrom: applyToImportsFrom
1272
+ });
1273
+ }
1274
+ };
1275
+ }
1276
+ };
1277
+ }
1278
+ var rule = createRule(_types.realFileSystem);
1279
+ var _default = exports.default = rule;