@atlaskit/eslint-plugin-platform 2.8.0 → 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 (39) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/index.js +6 -1
  3. package/dist/cjs/rules/ensure-use-sync-external-store-server-snapshot/index.js +41 -0
  4. package/dist/cjs/rules/import/no-barrel-entry-imports/index.js +475 -67
  5. package/dist/cjs/rules/import/no-barrel-entry-jest-mock/index.js +387 -112
  6. package/dist/cjs/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  7. package/dist/cjs/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  8. package/dist/cjs/rules/import/shared/jest-utils.js +62 -9
  9. package/dist/cjs/rules/import/shared/package-resolution.js +156 -23
  10. package/dist/cjs/rules/visit-example-type-import-required/index.js +409 -0
  11. package/dist/es2019/index.js +6 -1
  12. package/dist/es2019/rules/ensure-use-sync-external-store-server-snapshot/index.js +43 -0
  13. package/dist/es2019/rules/import/no-barrel-entry-imports/index.js +372 -15
  14. package/dist/es2019/rules/import/no-barrel-entry-jest-mock/index.js +245 -17
  15. package/dist/es2019/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  16. package/dist/es2019/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  17. package/dist/es2019/rules/import/shared/jest-utils.js +44 -0
  18. package/dist/es2019/rules/import/shared/package-resolution.js +97 -5
  19. package/dist/es2019/rules/visit-example-type-import-required/index.js +375 -0
  20. package/dist/esm/index.js +6 -1
  21. package/dist/esm/rules/ensure-use-sync-external-store-server-snapshot/index.js +35 -0
  22. package/dist/esm/rules/import/no-barrel-entry-imports/index.js +475 -67
  23. package/dist/esm/rules/import/no-barrel-entry-jest-mock/index.js +388 -113
  24. package/dist/esm/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  25. package/dist/esm/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  26. package/dist/esm/rules/import/shared/jest-utils.js +61 -9
  27. package/dist/esm/rules/import/shared/package-resolution.js +156 -25
  28. package/dist/esm/rules/visit-example-type-import-required/index.js +402 -0
  29. package/dist/types/index.d.ts +12 -0
  30. package/dist/types/rules/ensure-use-sync-external-store-server-snapshot/index.d.ts +3 -0
  31. package/dist/types/rules/import/shared/jest-utils.d.ts +8 -0
  32. package/dist/types/rules/import/shared/package-resolution.d.ts +22 -2
  33. package/dist/types/rules/visit-example-type-import-required/index.d.ts +4 -0
  34. package/dist/types-ts4.5/index.d.ts +12 -0
  35. package/dist/types-ts4.5/rules/ensure-use-sync-external-store-server-snapshot/index.d.ts +3 -0
  36. package/dist/types-ts4.5/rules/import/shared/jest-utils.d.ts +8 -0
  37. package/dist/types-ts4.5/rules/import/shared/package-resolution.d.ts +22 -2
  38. package/dist/types-ts4.5/rules/visit-example-type-import-required/index.d.ts +4 -0
  39. package/package.json +3 -1
@@ -137,19 +137,14 @@ function buildImportStatement(_ref) {
137
137
  */
138
138
 
139
139
  /**
140
- * Resolves import context for barrel file analysis.
140
+ * Resolves import context for barrel file analysis from a module specifier string.
141
141
  * Returns null if the import should not be processed (relative import, not in target folder, etc.)
142
142
  */
143
- function resolveImportContext(_ref2) {
144
- var node = _ref2.node,
143
+ function resolveImportContextFromModulePath(_ref2) {
144
+ var importPath = _ref2.importPath,
145
145
  workspaceRoot = _ref2.workspaceRoot,
146
146
  fs = _ref2.fs,
147
147
  applyToImportsFrom = _ref2.applyToImportsFrom;
148
- if (!node.source || typeof node.source.value !== 'string') {
149
- return null;
150
- }
151
- var importPath = node.source.value;
152
-
153
148
  // Skip relative imports - this rule is for cross-package imports
154
149
  if ((0, _fileSystem.isRelativeImport)(importPath)) {
155
150
  return null;
@@ -223,16 +218,36 @@ function resolveImportContext(_ref2) {
223
218
  };
224
219
  }
225
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
+
226
241
  /**
227
242
  * Classifies import specifiers by their target export paths.
228
243
  * Groups specifiers that can be remapped to more specific exports.
229
244
  * For cross-package re-exports, suggests importing from the source package's most specific subpath.
230
245
  */
231
- function classifySpecifiers(_ref3) {
232
- var node = _ref3.node,
233
- importContext = _ref3.importContext,
234
- workspaceRoot = _ref3.workspaceRoot,
235
- fs = _ref3.fs;
246
+ function classifySpecifiers(_ref4) {
247
+ var node = _ref4.node,
248
+ importContext = _ref4.importContext,
249
+ workspaceRoot = _ref4.workspaceRoot,
250
+ fs = _ref4.fs;
236
251
  var currentExportPath = importContext.currentExportPath,
237
252
  exportsMap = importContext.exportsMap,
238
253
  exportMap = importContext.exportMap;
@@ -265,7 +280,7 @@ function classifySpecifiers(_ref3) {
265
280
  }
266
281
  var exportInfo = exportMap.get(nameInSource);
267
282
  if (exportInfo) {
268
- var _exportInfo$crossPack;
283
+ var _exportInfo$crossPack, _exportInfo$originalN2, _matchResult$exportPa2;
269
284
  var effectiveKind = kind === 'type' || exportInfo.isTypeOnly ? 'type' : 'value';
270
285
 
271
286
  // Check if this is a cross-package re-export
@@ -291,11 +306,20 @@ function classifySpecifiers(_ref3) {
291
306
 
292
307
  // Find the best export path in the source package
293
308
  var _targetExportPath = null;
309
+ var resolvedOriginalName = exportInfo.originalName;
294
310
  if (sourcePackageExportsMap) {
295
- _targetExportPath = (0, _packageResolution.findExportForSourceFile)({
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)({
296
314
  sourceFilePath: exportInfo.path,
297
- exportsMap: sourcePackageExportsMap
315
+ exportsMap: sourcePackageExportsMap,
316
+ fs: fs,
317
+ sourceExportName: _sourceExportName
298
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
+ }
299
323
  }
300
324
 
301
325
  // Build the full import path: @package/subpath or just @package if no subpath found
@@ -308,7 +332,7 @@ function classifySpecifiers(_ref3) {
308
332
  spec: _objectSpread(_objectSpread({}, spec), {}, {
309
333
  importKind: effectiveKind
310
334
  }),
311
- originalName: exportInfo.originalName,
335
+ originalName: resolvedOriginalName,
312
336
  targetExportPath: targetKey,
313
337
  kind: effectiveKind,
314
338
  sourcePackageName: sourcePackageName
@@ -317,10 +341,18 @@ function classifySpecifiers(_ref3) {
317
341
  }
318
342
 
319
343
  // Find if there's a package.json export that points to this source file
320
- var targetExportPath = (0, _packageResolution.findExportForSourceFile)({
344
+ var sourceExportName = (_exportInfo$originalN2 = exportInfo.originalName) !== null && _exportInfo$originalN2 !== void 0 ? _exportInfo$originalN2 : nameInSource;
345
+ var matchResult = (0, _packageResolution.findExportForSourceFile)({
321
346
  sourceFilePath: exportInfo.path,
322
- exportsMap: exportsMap
347
+ exportsMap: exportsMap,
348
+ fs: fs,
349
+ sourceExportName: sourceExportName
323
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
+ }
324
356
 
325
357
  // Get the file that the current export path resolves to
326
358
  var currentExportResolvedFile = exportsMap.get(currentExportPath);
@@ -339,7 +371,7 @@ function classifySpecifiers(_ref3) {
339
371
  spec: _objectSpread(_objectSpread({}, spec), {}, {
340
372
  importKind: effectiveKind
341
373
  }),
342
- originalName: exportInfo.originalName,
374
+ originalName: resolvedOriginalName2,
343
375
  targetExportPath: targetExportPath,
344
376
  kind: effectiveKind
345
377
  });
@@ -375,10 +407,10 @@ function classifySpecifiers(_ref3) {
375
407
  * Transforms a specifier to use the original export name (handling aliasing).
376
408
  * Converts named imports of default exports to ImportDefaultSpecifier.
377
409
  */
378
- function transformSpecifierForExport(_ref4) {
379
- var spec = _ref4.spec,
380
- originalName = _ref4.originalName,
381
- kind = _ref4.kind;
410
+ function transformSpecifierForExport(_ref5) {
411
+ var spec = _ref5.spec,
412
+ originalName = _ref5.originalName,
413
+ kind = _ref5.kind;
382
414
  if (!originalName) {
383
415
  return spec;
384
416
  }
@@ -427,12 +459,12 @@ function transformSpecifierForExport(_ref4) {
427
459
  * Merges new specifiers with an existing import declaration.
428
460
  * Returns the new import statement string.
429
461
  */
430
- function buildMergedImportStatement(_ref5) {
431
- var existingImport = _ref5.existingImport,
432
- newSpecs = _ref5.newSpecs,
433
- newImportPath = _ref5.newImportPath,
434
- nodeImportKind = _ref5.nodeImportKind,
435
- quoteChar = _ref5.quoteChar;
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;
436
468
  var existingSpecs = existingImport.specifiers.map(function (s) {
437
469
  if (existingImport.importKind === 'type') {
438
470
  return _objectSpread(_objectSpread({}, s), {}, {
@@ -505,9 +537,9 @@ function getJestAutomock(node) {
505
537
  /**
506
538
  * Find all Jest automocks in the AST that match the given import path.
507
539
  */
508
- function findMatchingAutomocks(_ref6) {
509
- var sourceCode = _ref6.sourceCode,
510
- importPath = _ref6.importPath;
540
+ function findMatchingAutomocks(_ref7) {
541
+ var sourceCode = _ref7.sourceCode,
542
+ importPath = _ref7.importPath;
511
543
  var automocks = [];
512
544
  var ast = sourceCode.ast;
513
545
  var _iterator2 = _createForOfIteratorHelper(ast.body),
@@ -531,9 +563,9 @@ function findMatchingAutomocks(_ref6) {
531
563
  /**
532
564
  * Build a jest.mock() statement string
533
565
  */
534
- function buildAutomockStatement(_ref7) {
535
- var path = _ref7.path,
536
- quoteChar = _ref7.quoteChar;
566
+ function buildAutomockStatement(_ref8) {
567
+ var path = _ref8.path,
568
+ quoteChar = _ref8.quoteChar;
537
569
  return "jest.mock(".concat(quoteChar).concat(path).concat(quoteChar, ");");
538
570
  }
539
571
 
@@ -541,10 +573,10 @@ function buildAutomockStatement(_ref7) {
541
573
  * Creates a fix to remove a node with proper whitespace handling.
542
574
  * Removes surrounding newlines to avoid leaving blank lines.
543
575
  */
544
- function createNodeRemovalFix(_ref8) {
545
- var fixer = _ref8.fixer,
546
- node = _ref8.node,
547
- sourceCode = _ref8.sourceCode;
576
+ function createNodeRemovalFix(_ref9) {
577
+ var fixer = _ref9.fixer,
578
+ node = _ref9.node,
579
+ sourceCode = _ref9.sourceCode;
548
580
  var nodeStart = node.range[0];
549
581
  var nodeEnd = node.range[1];
550
582
 
@@ -570,13 +602,13 @@ function createNodeRemovalFix(_ref8) {
570
602
  * Generates new import statements and handles merging with existing imports.
571
603
  * Also updates Jest automocks (jest.mock calls with only a path) when present.
572
604
  */
573
- function createBarrelImportFix(_ref9) {
574
- var fixer = _ref9.fixer,
575
- node = _ref9.node,
576
- context = _ref9.context,
577
- importContext = _ref9.importContext,
578
- specifiersByTarget = _ref9.specifiersByTarget,
579
- unmappedSpecifiers = _ref9.unmappedSpecifiers;
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;
580
612
  var importPath = importContext.importPath,
581
613
  packageName = importContext.packageName;
582
614
  var sourceCode = context.sourceCode;
@@ -618,10 +650,10 @@ function createBarrelImportFix(_ref9) {
618
650
  : packageName + targetExportPath.slice(1); // Remove leading '.' for same-package imports
619
651
 
620
652
  // Transform specifiers if needed (handle aliasing)
621
- var specs = specsWithTarget.map(function (_ref1) {
622
- var spec = _ref1.spec,
623
- originalName = _ref1.originalName,
624
- kind = _ref1.kind;
653
+ var specs = specsWithTarget.map(function (_ref10) {
654
+ var spec = _ref10.spec,
655
+ originalName = _ref10.originalName,
656
+ kind = _ref10.kind;
625
657
  return transformSpecifierForExport({
626
658
  spec: spec,
627
659
  originalName: originalName,
@@ -632,9 +664,9 @@ function createBarrelImportFix(_ref9) {
632
664
  // Check if any specifier in this group is a value import (not type-only)
633
665
  // Only add automock paths for value imports (types don't need mocking at runtime)
634
666
  if (automocks.length > 0) {
635
- var hasValueImport = specsWithTarget.some(function (_ref10) {
636
- var kind = _ref10.kind,
637
- spec = _ref10.spec;
667
+ var hasValueImport = specsWithTarget.some(function (_ref11) {
668
+ var kind = _ref11.kind,
669
+ spec = _ref11.spec;
638
670
  return kind === 'value' && (spec.type !== 'ImportSpecifier' || spec.importKind !== 'type');
639
671
  });
640
672
  if (hasValueImport) {
@@ -705,9 +737,9 @@ function createBarrelImportFix(_ref9) {
705
737
 
706
738
  // If there are unmapped value specifiers and automocks, keep the original automock path too
707
739
  if (automocks.length > 0) {
708
- var hasUnmappedValueImport = unmappedSpecifiers.some(function (_ref0) {
709
- var kind = _ref0.kind,
710
- spec = _ref0.spec;
740
+ var hasUnmappedValueImport = unmappedSpecifiers.some(function (_ref1) {
741
+ var kind = _ref1.kind,
742
+ spec = _ref1.spec;
711
743
  return kind === 'value' && (spec.type !== 'ImportSpecifier' || spec.importKind !== 'type');
712
744
  });
713
745
  if (hasUnmappedValueImport) {
@@ -758,17 +790,375 @@ function createBarrelImportFix(_ref9) {
758
790
  }
759
791
  return fixes;
760
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
+ }
761
1151
 
762
1152
  /**
763
1153
  * Handles an ImportDeclaration node to check for barrel file imports.
764
1154
  * Reports and auto-fixes imports that could use more specific export paths.
765
1155
  */
766
- function handleImportDeclaration(_ref11) {
767
- var node = _ref11.node,
768
- context = _ref11.context,
769
- workspaceRoot = _ref11.workspaceRoot,
770
- fs = _ref11.fs,
771
- applyToImportsFrom = _ref11.applyToImportsFrom;
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;
772
1162
  // Resolve import context (validates and extracts package/export info)
773
1163
  // applyToImportsFrom is used here to filter which packages the rule applies to
774
1164
  var importContext = resolveImportContext({
@@ -787,15 +1177,15 @@ function handleImportDeclaration(_ref11) {
787
1177
  }
788
1178
 
789
1179
  // Classify specifiers by their target export paths
790
- var _classifySpecifiers = classifySpecifiers({
1180
+ var _classifySpecifiers3 = classifySpecifiers({
791
1181
  node: node,
792
1182
  importContext: importContext,
793
1183
  workspaceRoot: workspaceRoot,
794
1184
  fs: fs
795
1185
  }),
796
- specifiersByTarget = _classifySpecifiers.specifiersByTarget,
797
- unmappedSpecifiers = _classifySpecifiers.unmappedSpecifiers,
798
- hasNamespaceImport = _classifySpecifiers.hasNamespaceImport;
1186
+ specifiersByTarget = _classifySpecifiers3.specifiersByTarget,
1187
+ unmappedSpecifiers = _classifySpecifiers3.unmappedSpecifiers,
1188
+ hasNamespaceImport = _classifySpecifiers3.hasNamespaceImport;
799
1189
 
800
1190
  // If namespace import, report without auto-fix if there are specific exports available
801
1191
  if (hasNamespaceImport) {
@@ -862,6 +1252,24 @@ function createRule(fs) {
862
1252
  fs: fs,
863
1253
  applyToImportsFrom: applyToImportsFrom
864
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
+ });
865
1273
  }
866
1274
  };
867
1275
  }