@atlaskit/eslint-plugin-platform 2.7.1 → 2.8.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.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/index.js +17 -9
- package/dist/cjs/rules/constants.js +1 -1
- package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +5 -5
- package/dist/cjs/rules/ensure-no-private-dependencies/index.js +48 -66
- package/dist/cjs/rules/feature-gating/inline-usage/index.js +14 -3
- package/dist/cjs/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/cjs/rules/feature-gating/no-module-level-eval/index.js +1 -1
- package/dist/cjs/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
- package/dist/cjs/rules/feature-gating/no-preconditioning/index.js +4 -1
- package/dist/cjs/rules/feature-gating/prefer-fg/index.js +1 -1
- package/dist/cjs/rules/feature-gating/static-feature-flags/index.js +2 -2
- package/dist/cjs/rules/feature-gating/use-recommended-utils/index.js +1 -1
- package/dist/cjs/rules/feature-gating/valid-gate-name/index.js +60 -0
- package/dist/cjs/rules/import/no-barrel-entry-imports/index.js +871 -0
- package/dist/cjs/rules/import/no-barrel-entry-jest-mock/index.js +1384 -0
- package/dist/cjs/rules/import/no-conversation-assistant-barrel-imports/index.js +43 -0
- package/dist/cjs/rules/import/no-jest-mock-barrel-files/index.js +1401 -0
- package/dist/cjs/rules/import/no-relative-barrel-file-imports/index.js +777 -0
- package/dist/cjs/rules/import/shared/barrel-parsing.js +511 -0
- package/dist/cjs/rules/import/shared/file-system.js +186 -0
- package/dist/cjs/rules/import/shared/jest-utils.js +191 -0
- package/dist/cjs/rules/import/shared/package-registry.js +263 -0
- package/dist/cjs/rules/import/shared/package-resolution.js +185 -0
- package/dist/cjs/rules/import/shared/perf.js +89 -0
- package/dist/cjs/rules/import/shared/types.js +67 -0
- package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
- package/dist/cjs/rules/no-sparse-checkout/index.js +1 -1
- package/dist/cjs/rules/prefer-crypto-random-uuid/index.js +87 -0
- package/dist/cjs/rules/use-entrypoints-in-examples/index.js +1 -1
- package/dist/es2019/index.js +17 -9
- package/dist/es2019/rules/constants.js +1 -1
- package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +5 -5
- package/dist/es2019/rules/ensure-no-private-dependencies/index.js +10 -9
- package/dist/es2019/rules/feature-gating/inline-usage/index.js +14 -3
- package/dist/es2019/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/es2019/rules/feature-gating/no-module-level-eval/index.js +1 -1
- package/dist/es2019/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
- package/dist/es2019/rules/feature-gating/no-preconditioning/index.js +4 -1
- package/dist/es2019/rules/feature-gating/prefer-fg/index.js +1 -1
- package/dist/es2019/rules/feature-gating/static-feature-flags/index.js +2 -2
- package/dist/es2019/rules/feature-gating/use-recommended-utils/index.js +1 -1
- package/dist/es2019/rules/feature-gating/valid-gate-name/index.js +52 -0
- package/dist/es2019/rules/import/no-barrel-entry-imports/index.js +801 -0
- package/dist/es2019/rules/import/no-barrel-entry-jest-mock/index.js +1113 -0
- package/dist/es2019/rules/import/no-conversation-assistant-barrel-imports/index.js +37 -0
- package/dist/es2019/rules/import/no-jest-mock-barrel-files/index.js +1179 -0
- package/dist/es2019/rules/import/no-relative-barrel-file-imports/index.js +738 -0
- package/dist/es2019/rules/import/shared/barrel-parsing.js +433 -0
- package/dist/es2019/rules/import/shared/file-system.js +174 -0
- package/dist/es2019/rules/import/shared/jest-utils.js +159 -0
- package/dist/es2019/rules/import/shared/package-registry.js +240 -0
- package/dist/es2019/rules/import/shared/package-resolution.js +161 -0
- package/dist/es2019/rules/import/shared/perf.js +83 -0
- package/dist/es2019/rules/import/shared/types.js +57 -0
- package/dist/es2019/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
- package/dist/es2019/rules/no-sparse-checkout/index.js +1 -1
- package/dist/es2019/rules/prefer-crypto-random-uuid/index.js +81 -0
- package/dist/es2019/rules/use-entrypoints-in-examples/index.js +1 -1
- package/dist/esm/index.js +17 -9
- package/dist/esm/rules/constants.js +1 -1
- package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +5 -5
- package/dist/esm/rules/ensure-no-private-dependencies/index.js +48 -65
- package/dist/esm/rules/feature-gating/inline-usage/index.js +14 -3
- package/dist/esm/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/esm/rules/feature-gating/no-module-level-eval/index.js +1 -1
- package/dist/esm/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
- package/dist/esm/rules/feature-gating/no-preconditioning/index.js +4 -1
- package/dist/esm/rules/feature-gating/prefer-fg/index.js +1 -1
- package/dist/esm/rules/feature-gating/static-feature-flags/index.js +2 -2
- package/dist/esm/rules/feature-gating/use-recommended-utils/index.js +1 -1
- package/dist/esm/rules/feature-gating/valid-gate-name/index.js +53 -0
- package/dist/esm/rules/import/no-barrel-entry-imports/index.js +864 -0
- package/dist/esm/rules/import/no-barrel-entry-jest-mock/index.js +1375 -0
- package/dist/esm/rules/import/no-conversation-assistant-barrel-imports/index.js +37 -0
- package/dist/esm/rules/import/no-jest-mock-barrel-files/index.js +1391 -0
- package/dist/esm/rules/import/no-relative-barrel-file-imports/index.js +770 -0
- package/dist/esm/rules/import/shared/barrel-parsing.js +500 -0
- package/dist/esm/rules/import/shared/file-system.js +176 -0
- package/dist/esm/rules/import/shared/jest-utils.js +179 -0
- package/dist/esm/rules/import/shared/package-registry.js +256 -0
- package/dist/esm/rules/import/shared/package-resolution.js +175 -0
- package/dist/esm/rules/import/shared/perf.js +80 -0
- package/dist/esm/rules/import/shared/types.js +61 -0
- package/dist/esm/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
- package/dist/esm/rules/no-sparse-checkout/index.js +1 -1
- package/dist/esm/rules/prefer-crypto-random-uuid/index.js +81 -0
- package/dist/esm/rules/use-entrypoints-in-examples/index.js +1 -1
- package/dist/types/index.d.ts +18 -16
- package/dist/types/rules/import/no-barrel-entry-imports/index.d.ts +9 -0
- package/dist/types/rules/import/no-barrel-entry-jest-mock/index.d.ts +9 -0
- package/dist/types/rules/import/no-conversation-assistant-barrel-imports/index.d.ts +3 -0
- package/dist/types/rules/import/no-jest-mock-barrel-files/index.d.ts +22 -0
- package/dist/types/rules/import/no-relative-barrel-file-imports/index.d.ts +5 -0
- package/dist/types/rules/import/shared/barrel-parsing.d.ts +30 -0
- package/dist/types/rules/import/shared/file-system.d.ts +38 -0
- package/dist/types/rules/import/shared/jest-utils.d.ts +47 -0
- package/dist/types/rules/import/shared/package-registry.d.ts +26 -0
- package/dist/types/rules/import/shared/package-resolution.d.ts +38 -0
- package/dist/types/rules/import/shared/perf.d.ts +13 -0
- package/dist/types/rules/import/shared/types.d.ts +131 -0
- package/dist/types/rules/prefer-crypto-random-uuid/index.d.ts +3 -0
- package/dist/types-ts4.5/index.d.ts +18 -28
- package/dist/types-ts4.5/rules/import/no-barrel-entry-imports/index.d.ts +9 -0
- package/dist/types-ts4.5/rules/import/no-barrel-entry-jest-mock/index.d.ts +9 -0
- package/dist/types-ts4.5/rules/import/no-jest-mock-barrel-files/index.d.ts +22 -0
- package/dist/types-ts4.5/rules/import/no-relative-barrel-file-imports/index.d.ts +5 -0
- package/dist/types-ts4.5/rules/import/shared/barrel-parsing.d.ts +30 -0
- package/dist/types-ts4.5/rules/import/shared/file-system.d.ts +38 -0
- package/dist/types-ts4.5/rules/import/shared/jest-utils.d.ts +47 -0
- package/dist/types-ts4.5/rules/import/shared/package-registry.d.ts +26 -0
- package/dist/types-ts4.5/rules/import/shared/package-resolution.d.ts +38 -0
- package/dist/types-ts4.5/rules/import/shared/perf.d.ts +13 -0
- package/dist/types-ts4.5/rules/import/shared/types.d.ts +131 -0
- package/package.json +4 -5
- package/dist/cjs/rules/ensure-feature-flag-prefix/index.js +0 -75
- package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +0 -158
- package/dist/es2019/rules/ensure-feature-flag-prefix/index.js +0 -65
- package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +0 -146
- package/dist/esm/rules/ensure-feature-flag-prefix/index.js +0 -69
- package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +0 -151
- /package/dist/types/rules/{ensure-native-and-af-exports-synced → feature-gating/valid-gate-name}/index.d.ts +0 -0
- /package/dist/types-ts4.5/rules/{ensure-feature-flag-prefix → feature-gating/valid-gate-name}/index.d.ts +0 -0
- /package/dist/types-ts4.5/rules/{ensure-native-and-af-exports-synced → import/no-conversation-assistant-barrel-imports}/index.d.ts +0 -0
- /package/dist/{types/rules/ensure-feature-flag-prefix → types-ts4.5/rules/prefer-crypto-random-uuid}/index.d.ts +0 -0
|
@@ -0,0 +1,777 @@
|
|
|
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 _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
10
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
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
|
+
* Specifier with additional metadata for tracking during barrel file resolution.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Context for barrel file resolution, returned by resolveBarrelFileContext.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Result of collecting specifiers by their source file.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// Cache per source package name to avoid repeated exports parsing during a single lint run.
|
|
36
|
+
// This is keyed by fs instance to avoid test pollution.
|
|
37
|
+
var sourcePackageExportsMapsByFs = new WeakMap();
|
|
38
|
+
function getSourcePackageExportsMaps(fs) {
|
|
39
|
+
var map = sourcePackageExportsMapsByFs.get(fs);
|
|
40
|
+
if (!map) {
|
|
41
|
+
map = new Map();
|
|
42
|
+
sourcePackageExportsMapsByFs.set(fs, map);
|
|
43
|
+
}
|
|
44
|
+
return map;
|
|
45
|
+
}
|
|
46
|
+
function getImportedName(spec) {
|
|
47
|
+
var imported = spec.imported;
|
|
48
|
+
return imported.type === 'Identifier' ? imported.name : String(imported.value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the exported name from an ExportSpecifier, handling both Identifier and Literal
|
|
53
|
+
*/
|
|
54
|
+
function getExportedName(node) {
|
|
55
|
+
return node.type === 'Identifier' ? node.name : String(node.value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Convert absolute file path back to relative import path
|
|
60
|
+
*/
|
|
61
|
+
function getImportPathForSourceFile(_ref) {
|
|
62
|
+
var _exportInfo$crossPack;
|
|
63
|
+
var sourceFilePath = _ref.sourceFilePath,
|
|
64
|
+
basedir = _ref.basedir,
|
|
65
|
+
originalImportPath = _ref.originalImportPath,
|
|
66
|
+
exportInfo = _ref.exportInfo,
|
|
67
|
+
workspaceRoot = _ref.workspaceRoot,
|
|
68
|
+
fs = _ref.fs;
|
|
69
|
+
var crossPackageName = exportInfo === null || exportInfo === void 0 || (_exportInfo$crossPack = exportInfo.crossPackageSource) === null || _exportInfo$crossPack === void 0 ? void 0 : _exportInfo$crossPack.packageName;
|
|
70
|
+
if (crossPackageName) {
|
|
71
|
+
var sourcePackageExportsMaps = getSourcePackageExportsMaps(fs);
|
|
72
|
+
var exportsMap = sourcePackageExportsMaps.get(crossPackageName);
|
|
73
|
+
if (!exportsMap) {
|
|
74
|
+
var pkgDir = (0, _packageRegistry.findPackageInRegistry)({
|
|
75
|
+
packageName: crossPackageName,
|
|
76
|
+
workspaceRoot: workspaceRoot,
|
|
77
|
+
fs: fs
|
|
78
|
+
});
|
|
79
|
+
if (pkgDir) {
|
|
80
|
+
exportsMap = (0, _packageResolution.parsePackageExports)({
|
|
81
|
+
packageDir: pkgDir,
|
|
82
|
+
fs: fs
|
|
83
|
+
});
|
|
84
|
+
sourcePackageExportsMaps.set(crossPackageName, exportsMap);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
var targetExportPath = exportsMap ? (0, _packageResolution.findExportForSourceFile)({
|
|
88
|
+
sourceFilePath: sourceFilePath,
|
|
89
|
+
exportsMap: exportsMap
|
|
90
|
+
}) : null;
|
|
91
|
+
return targetExportPath ? crossPackageName + targetExportPath.slice(1) : crossPackageName;
|
|
92
|
+
}
|
|
93
|
+
return getRelativeImportPath({
|
|
94
|
+
basedir: basedir,
|
|
95
|
+
absolutePath: sourceFilePath,
|
|
96
|
+
originalImportPath: originalImportPath
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function getRelativeImportPath(_ref2) {
|
|
100
|
+
var basedir = _ref2.basedir,
|
|
101
|
+
absolutePath = _ref2.absolutePath,
|
|
102
|
+
originalImportPath = _ref2.originalImportPath;
|
|
103
|
+
if (!absolutePath.startsWith('/') && !absolutePath.match(/^[a-zA-Z]:/)) {
|
|
104
|
+
return absolutePath;
|
|
105
|
+
}
|
|
106
|
+
var relativePath = (0, _path.relative)(basedir, absolutePath);
|
|
107
|
+
// Normalize to use forward slashes
|
|
108
|
+
relativePath = relativePath.replace(/\\/g, '/');
|
|
109
|
+
|
|
110
|
+
// Check for extension in original path
|
|
111
|
+
var extMatch = originalImportPath.match(/\.(js|jsx|ts|tsx|mjs|cjs)$/);
|
|
112
|
+
var originalExt = extMatch ? extMatch[0] : '';
|
|
113
|
+
|
|
114
|
+
// Get extension from the resolved absolute path
|
|
115
|
+
var targetExtMatch = absolutePath.match(/\.(js|jsx|ts|tsx|mjs|cjs)$/);
|
|
116
|
+
var targetExt = targetExtMatch ? targetExtMatch[0] : '';
|
|
117
|
+
|
|
118
|
+
// Remove file extension from the target path
|
|
119
|
+
relativePath = relativePath.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/, '');
|
|
120
|
+
|
|
121
|
+
// If original had extension, append it
|
|
122
|
+
if (originalExt) {
|
|
123
|
+
// If original was a TypeScript source extension, use the actual target extension
|
|
124
|
+
if (['.ts', '.tsx'].includes(originalExt) && targetExt) {
|
|
125
|
+
relativePath += targetExt;
|
|
126
|
+
} else {
|
|
127
|
+
relativePath += originalExt;
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
// Remove /index suffix only if no extension was present
|
|
131
|
+
if (relativePath.endsWith('/index')) {
|
|
132
|
+
relativePath = relativePath.slice(0, -6);
|
|
133
|
+
} else if (relativePath === 'index') {
|
|
134
|
+
relativePath = '.';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Ensure it starts with .. or .
|
|
139
|
+
if (!relativePath.startsWith('.') && !relativePath.startsWith('/')) {
|
|
140
|
+
relativePath = './' + relativePath;
|
|
141
|
+
}
|
|
142
|
+
return relativePath;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Build an import statement for a set of specifiers
|
|
147
|
+
*/
|
|
148
|
+
function buildImportStatement(_ref3) {
|
|
149
|
+
var specs = _ref3.specs,
|
|
150
|
+
path = _ref3.path,
|
|
151
|
+
quoteChar = _ref3.quoteChar,
|
|
152
|
+
_ref3$isTypeImport = _ref3.isTypeImport,
|
|
153
|
+
isTypeImport = _ref3$isTypeImport === void 0 ? false : _ref3$isTypeImport;
|
|
154
|
+
var importNames = specs.map(function (spec) {
|
|
155
|
+
if (spec.type === 'ImportDefaultSpecifier') {
|
|
156
|
+
return spec.local.name;
|
|
157
|
+
} else if (spec.type === 'ImportSpecifier') {
|
|
158
|
+
var imported = getImportedName(spec);
|
|
159
|
+
var local = spec.local.name;
|
|
160
|
+
var isInlineType = spec.importKind === 'type' && !isTypeImport;
|
|
161
|
+
var prefix = isInlineType ? 'type ' : '';
|
|
162
|
+
return imported === local ? "".concat(prefix).concat(imported) : "".concat(prefix).concat(imported, " as ").concat(local);
|
|
163
|
+
}
|
|
164
|
+
return '';
|
|
165
|
+
}).filter(function (name) {
|
|
166
|
+
return name.length > 0;
|
|
167
|
+
});
|
|
168
|
+
if (importNames.length === 0) {
|
|
169
|
+
return '';
|
|
170
|
+
}
|
|
171
|
+
var typeKeyword = isTypeImport ? 'type ' : '';
|
|
172
|
+
var hasDefault = specs.some(function (spec) {
|
|
173
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
174
|
+
});
|
|
175
|
+
var hasNamed = specs.some(function (spec) {
|
|
176
|
+
return spec.type === 'ImportSpecifier';
|
|
177
|
+
});
|
|
178
|
+
if (hasDefault && hasNamed) {
|
|
179
|
+
var _specs$find;
|
|
180
|
+
var defaultName = (_specs$find = specs.find(function (spec) {
|
|
181
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
182
|
+
})) === null || _specs$find === void 0 ? void 0 : _specs$find.local.name;
|
|
183
|
+
var namedImports = specs.filter(function (spec) {
|
|
184
|
+
return spec.type === 'ImportSpecifier';
|
|
185
|
+
}).map(function (spec) {
|
|
186
|
+
var imported = getImportedName(spec);
|
|
187
|
+
var local = spec.local.name;
|
|
188
|
+
var isInlineType = spec.importKind === 'type' && !isTypeImport;
|
|
189
|
+
var prefix = isInlineType ? 'type ' : '';
|
|
190
|
+
return imported === local ? "".concat(prefix).concat(imported) : "".concat(prefix).concat(imported, " as ").concat(local);
|
|
191
|
+
}).join(', ');
|
|
192
|
+
return "import ".concat(typeKeyword).concat(defaultName, ", { ").concat(namedImports, " } from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
|
|
193
|
+
} else if (hasDefault) {
|
|
194
|
+
var _specs$find2;
|
|
195
|
+
var _defaultName = (_specs$find2 = specs.find(function (spec) {
|
|
196
|
+
return spec.type === 'ImportDefaultSpecifier';
|
|
197
|
+
})) === null || _specs$find2 === void 0 ? void 0 : _specs$find2.local.name;
|
|
198
|
+
return "import ".concat(typeKeyword).concat(_defaultName, " from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
|
|
199
|
+
} else {
|
|
200
|
+
return "import ".concat(typeKeyword, "{ ").concat(importNames.join(', '), " } from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Build an export statement for a set of specifiers
|
|
206
|
+
*/
|
|
207
|
+
function buildExportStatement(_ref4) {
|
|
208
|
+
var specs = _ref4.specs,
|
|
209
|
+
path = _ref4.path,
|
|
210
|
+
quoteChar = _ref4.quoteChar,
|
|
211
|
+
_ref4$isTypeExport = _ref4.isTypeExport,
|
|
212
|
+
isTypeExport = _ref4$isTypeExport === void 0 ? false : _ref4$isTypeExport;
|
|
213
|
+
var exportNames = specs.map(function (spec) {
|
|
214
|
+
var isInlineType = spec.kind === 'type' && !isTypeExport;
|
|
215
|
+
var prefix = isInlineType ? 'type ' : '';
|
|
216
|
+
return spec.nameInSource === spec.nameInLocal ? "".concat(prefix).concat(spec.nameInSource) : "".concat(prefix).concat(spec.nameInSource, " as ").concat(spec.nameInLocal);
|
|
217
|
+
}).filter(function (name) {
|
|
218
|
+
return name.length > 0;
|
|
219
|
+
});
|
|
220
|
+
if (exportNames.length === 0) {
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
var typeKeyword = isTypeExport ? 'type ' : '';
|
|
224
|
+
return "export ".concat(typeKeyword, "{ ").concat(exportNames.join(', '), " } from ").concat(quoteChar).concat(path).concat(quoteChar, ";");
|
|
225
|
+
}
|
|
226
|
+
var ruleMeta = {
|
|
227
|
+
type: 'problem',
|
|
228
|
+
docs: {
|
|
229
|
+
description: 'Warn when imports are from a relative barrel file and provide an auto-fix to split them into specific imports.',
|
|
230
|
+
category: 'Best Practices',
|
|
231
|
+
recommended: false
|
|
232
|
+
},
|
|
233
|
+
fixable: 'code',
|
|
234
|
+
messages: {
|
|
235
|
+
barrelImport: "Import from barrel file '{{path}}' should be split into more specific imports. Use auto-fix to resolve."
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Resolve barrel file context from an import/export node.
|
|
241
|
+
* Returns null if the node should not be checked (not relative, not resolvable, not a barrel).
|
|
242
|
+
*/
|
|
243
|
+
function resolveBarrelFileContext(_ref5) {
|
|
244
|
+
var node = _ref5.node,
|
|
245
|
+
context = _ref5.context,
|
|
246
|
+
fs = _ref5.fs;
|
|
247
|
+
if (!node.source) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
var importPath = node.source.value;
|
|
251
|
+
if (!(0, _fileSystem.isRelativeImport)(importPath)) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
var basedir = (0, _path.dirname)(context.filename);
|
|
255
|
+
var resolvedPath = (0, _fileSystem.resolveImportPath)({
|
|
256
|
+
basedir: basedir,
|
|
257
|
+
importPath: importPath,
|
|
258
|
+
fs: fs
|
|
259
|
+
});
|
|
260
|
+
if (!resolvedPath) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
var workspaceRoot = (0, _fileSystem.findWorkspaceRoot)({
|
|
264
|
+
startPath: basedir,
|
|
265
|
+
fs: fs
|
|
266
|
+
});
|
|
267
|
+
var exportMap = (0, _barrelParsing.parseBarrelExports)({
|
|
268
|
+
barrelFilePath: resolvedPath,
|
|
269
|
+
workspaceRoot: workspaceRoot,
|
|
270
|
+
fs: fs
|
|
271
|
+
});
|
|
272
|
+
if (exportMap.size === 0) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
if (!(0, _barrelParsing.hasReExportsFromOtherFiles)({
|
|
276
|
+
exportMap: exportMap,
|
|
277
|
+
sourceFilePath: resolvedPath
|
|
278
|
+
})) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
importPath: importPath,
|
|
283
|
+
basedir: basedir,
|
|
284
|
+
resolvedPath: resolvedPath,
|
|
285
|
+
workspaceRoot: workspaceRoot,
|
|
286
|
+
exportMap: exportMap
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Collect specifiers grouped by their source file.
|
|
292
|
+
*/
|
|
293
|
+
function collectSpecifiersBySource(_ref6) {
|
|
294
|
+
var specifiers = _ref6.specifiers,
|
|
295
|
+
node = _ref6.node,
|
|
296
|
+
exportMap = _ref6.exportMap;
|
|
297
|
+
var importsBySource = new Map();
|
|
298
|
+
var unmappedSpecifiers = [];
|
|
299
|
+
var hasNamespaceImport = false;
|
|
300
|
+
var _iterator = _createForOfIteratorHelper(specifiers),
|
|
301
|
+
_step;
|
|
302
|
+
try {
|
|
303
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
304
|
+
var spec = _step.value;
|
|
305
|
+
var nameInSource = void 0;
|
|
306
|
+
var nameInLocal = void 0;
|
|
307
|
+
var kind = 'value';
|
|
308
|
+
if (spec.type === 'ImportNamespaceSpecifier') {
|
|
309
|
+
hasNamespaceImport = true;
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (spec.type === 'ImportDefaultSpecifier') {
|
|
313
|
+
nameInSource = 'default';
|
|
314
|
+
nameInLocal = spec.local.name;
|
|
315
|
+
} else if (spec.type === 'ImportSpecifier') {
|
|
316
|
+
nameInSource = getImportedName(spec);
|
|
317
|
+
nameInLocal = spec.local.name;
|
|
318
|
+
var parentImportKind = node.type === 'ImportDeclaration' ? node.importKind : undefined;
|
|
319
|
+
kind = parentImportKind === 'type' || spec.importKind === 'type' ? 'type' : 'value';
|
|
320
|
+
} else if (spec.type === 'ExportSpecifier') {
|
|
321
|
+
nameInSource = spec.local.name;
|
|
322
|
+
nameInLocal = spec.exported.name;
|
|
323
|
+
var parentExportKind = node.type === 'ExportNamedDeclaration' ? node.exportKind : undefined;
|
|
324
|
+
kind = parentExportKind === 'type' || spec.exportKind === 'type' ? 'type' : 'value';
|
|
325
|
+
} else {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
var exportInfo = exportMap.get(nameInSource);
|
|
329
|
+
if (exportInfo) {
|
|
330
|
+
if (!importsBySource.has(exportInfo.path)) {
|
|
331
|
+
importsBySource.set(exportInfo.path, []);
|
|
332
|
+
}
|
|
333
|
+
var effectiveKind = kind === 'type' || exportInfo.isTypeOnly ? 'type' : 'value';
|
|
334
|
+
importsBySource.get(exportInfo.path).push({
|
|
335
|
+
spec: spec,
|
|
336
|
+
originalName: exportInfo.originalName,
|
|
337
|
+
exportInfo: exportInfo,
|
|
338
|
+
nameInSource: nameInSource,
|
|
339
|
+
nameInLocal: nameInLocal,
|
|
340
|
+
kind: effectiveKind
|
|
341
|
+
});
|
|
342
|
+
} else {
|
|
343
|
+
unmappedSpecifiers.push(spec);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
} catch (err) {
|
|
347
|
+
_iterator.e(err);
|
|
348
|
+
} finally {
|
|
349
|
+
_iterator.f();
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
importsBySource: importsBySource,
|
|
353
|
+
unmappedSpecifiers: unmappedSpecifiers,
|
|
354
|
+
hasNamespaceImport: hasNamespaceImport
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Find an existing import statement that imports from the same source file.
|
|
360
|
+
*/
|
|
361
|
+
function findExistingImportForSourceFile(_ref7) {
|
|
362
|
+
var sourceFile = _ref7.sourceFile,
|
|
363
|
+
allImports = _ref7.allImports,
|
|
364
|
+
basedir = _ref7.basedir,
|
|
365
|
+
fs = _ref7.fs;
|
|
366
|
+
return allImports.find(function (n) {
|
|
367
|
+
var isSourceAbsolute = sourceFile.startsWith('/') || sourceFile.match(/^[a-zA-Z]:/);
|
|
368
|
+
if (!(0, _fileSystem.isRelativeImport)(sourceFile) && !isSourceAbsolute) {
|
|
369
|
+
return n.source.value === sourceFile;
|
|
370
|
+
}
|
|
371
|
+
if (!(0, _fileSystem.isRelativeImport)(n.source.value)) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
var existingPath = (0, _fileSystem.resolveImportPath)({
|
|
375
|
+
basedir: basedir,
|
|
376
|
+
importPath: n.source.value,
|
|
377
|
+
fs: fs
|
|
378
|
+
});
|
|
379
|
+
return existingPath === sourceFile;
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Find an existing export statement that exports from the same source file.
|
|
385
|
+
*/
|
|
386
|
+
function findExistingExportForSourceFile(_ref8) {
|
|
387
|
+
var sourceFile = _ref8.sourceFile,
|
|
388
|
+
allExports = _ref8.allExports,
|
|
389
|
+
basedir = _ref8.basedir,
|
|
390
|
+
fs = _ref8.fs;
|
|
391
|
+
return allExports.find(function (n) {
|
|
392
|
+
if (!n.source) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
var isSourceAbsolute = sourceFile.startsWith('/') || sourceFile.match(/^[a-zA-Z]:/);
|
|
396
|
+
if (!(0, _fileSystem.isRelativeImport)(sourceFile) && !isSourceAbsolute) {
|
|
397
|
+
return n.source.value === sourceFile;
|
|
398
|
+
}
|
|
399
|
+
if (!(0, _fileSystem.isRelativeImport)(n.source.value)) {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
var existingPath = (0, _fileSystem.resolveImportPath)({
|
|
403
|
+
basedir: basedir,
|
|
404
|
+
importPath: n.source.value,
|
|
405
|
+
fs: fs
|
|
406
|
+
});
|
|
407
|
+
return existingPath === sourceFile;
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Transform import specifiers to handle aliasing when the original name differs.
|
|
413
|
+
*/
|
|
414
|
+
function transformImportSpecifiers(_ref9) {
|
|
415
|
+
var specsWithOriginal = _ref9.specsWithOriginal;
|
|
416
|
+
return specsWithOriginal.map(function (_ref0) {
|
|
417
|
+
var spec = _ref0.spec,
|
|
418
|
+
originalName = _ref0.originalName,
|
|
419
|
+
kind = _ref0.kind;
|
|
420
|
+
if (!originalName) {
|
|
421
|
+
return spec;
|
|
422
|
+
}
|
|
423
|
+
if (originalName === 'default') {
|
|
424
|
+
if (spec.type === 'ImportDefaultSpecifier') {
|
|
425
|
+
return spec;
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
type: 'ImportDefaultSpecifier',
|
|
429
|
+
local: spec.local,
|
|
430
|
+
range: spec.range,
|
|
431
|
+
loc: spec.loc,
|
|
432
|
+
parent: spec.parent
|
|
433
|
+
};
|
|
434
|
+
} else {
|
|
435
|
+
return {
|
|
436
|
+
type: 'ImportSpecifier',
|
|
437
|
+
local: spec.local,
|
|
438
|
+
imported: {
|
|
439
|
+
type: 'Identifier',
|
|
440
|
+
name: originalName,
|
|
441
|
+
range: [0, 0],
|
|
442
|
+
loc: {
|
|
443
|
+
start: {
|
|
444
|
+
line: 0,
|
|
445
|
+
column: 0
|
|
446
|
+
},
|
|
447
|
+
end: {
|
|
448
|
+
line: 0,
|
|
449
|
+
column: 0
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
importKind: kind,
|
|
454
|
+
range: spec.range,
|
|
455
|
+
loc: spec.loc,
|
|
456
|
+
parent: spec.parent
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Transform export specifiers to use original names from source.
|
|
464
|
+
*/
|
|
465
|
+
function transformExportSpecifiers(_ref1) {
|
|
466
|
+
var specsWithOriginal = _ref1.specsWithOriginal;
|
|
467
|
+
return specsWithOriginal.map(function (_ref10) {
|
|
468
|
+
var originalName = _ref10.originalName,
|
|
469
|
+
nameInLocal = _ref10.nameInLocal,
|
|
470
|
+
kind = _ref10.kind;
|
|
471
|
+
return {
|
|
472
|
+
nameInSource: originalName || 'default',
|
|
473
|
+
nameInLocal: nameInLocal,
|
|
474
|
+
kind: kind
|
|
475
|
+
};
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function createRule(fs) {
|
|
479
|
+
return {
|
|
480
|
+
meta: ruleMeta,
|
|
481
|
+
create: function create(context) {
|
|
482
|
+
var checkNode = function checkNode(rawNode) {
|
|
483
|
+
var node = rawNode;
|
|
484
|
+
|
|
485
|
+
// Resolve barrel file context (handles early exits for non-barrel files)
|
|
486
|
+
var barrelContext = resolveBarrelFileContext({
|
|
487
|
+
node: node,
|
|
488
|
+
context: context,
|
|
489
|
+
fs: fs
|
|
490
|
+
});
|
|
491
|
+
if (!barrelContext) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
var importPath = barrelContext.importPath,
|
|
495
|
+
resolvedPath = barrelContext.resolvedPath,
|
|
496
|
+
exportMap = barrelContext.exportMap;
|
|
497
|
+
|
|
498
|
+
// Check if we have any imports from this barrel
|
|
499
|
+
var specifiers = node.specifiers;
|
|
500
|
+
if (specifiers.length === 0) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Collect imports by source file
|
|
505
|
+
var _collectSpecifiersByS = collectSpecifiersBySource({
|
|
506
|
+
specifiers: specifiers,
|
|
507
|
+
node: node,
|
|
508
|
+
exportMap: exportMap
|
|
509
|
+
}),
|
|
510
|
+
importsBySource = _collectSpecifiersByS.importsBySource,
|
|
511
|
+
unmappedSpecifiers = _collectSpecifiersByS.unmappedSpecifiers,
|
|
512
|
+
hasNamespaceImport = _collectSpecifiersByS.hasNamespaceImport;
|
|
513
|
+
|
|
514
|
+
// If we have import * as, warn but don't auto-fix (too complex)
|
|
515
|
+
if (hasNamespaceImport) {
|
|
516
|
+
context.report({
|
|
517
|
+
node: node,
|
|
518
|
+
messageId: 'barrelImport',
|
|
519
|
+
data: {
|
|
520
|
+
path: importPath
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Check if we actually found any imports that map to the barrel exports
|
|
527
|
+
// If we found 0 mapped imports (all are unknown or missing), don't warn
|
|
528
|
+
if (importsBySource.size === 0) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// If all imports map back to the resolved path itself, don't warn.
|
|
533
|
+
// This happens when the file (e.g. index.ts) exports the symbols directly (not re-exports),
|
|
534
|
+
// so it is not acting as a barrel file for these imports.
|
|
535
|
+
if (importsBySource.size === 1 && importsBySource.has(resolvedPath)) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Build the report with optional auto-fix
|
|
540
|
+
var reportObj = {
|
|
541
|
+
node: node,
|
|
542
|
+
messageId: 'barrelImport',
|
|
543
|
+
data: {
|
|
544
|
+
path: importPath
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
// Only provide auto-fix if all imports are mapped
|
|
549
|
+
// If there are unmapped specifiers, don't auto-fix to avoid issues
|
|
550
|
+
var nodeSource = node.source;
|
|
551
|
+
if (unmappedSpecifiers.length === 0 && nodeSource) {
|
|
552
|
+
reportObj.fix = function (fixer) {
|
|
553
|
+
var sourceCode = context.getSourceCode();
|
|
554
|
+
var quote = sourceCode.getText(nodeSource)[0]; // Get quote character
|
|
555
|
+
var basedirForFix = (0, _path.dirname)(context.filename);
|
|
556
|
+
var fixes = [];
|
|
557
|
+
var newStatementsForBarrelReplacement = [];
|
|
558
|
+
|
|
559
|
+
// Generate new import statements for each source file
|
|
560
|
+
var sourceFileArray = Array.from(importsBySource.entries());
|
|
561
|
+
var _loop = function _loop() {
|
|
562
|
+
var _sourceFileArray$i = (0, _slicedToArray2.default)(sourceFileArray[i], 2),
|
|
563
|
+
sourceFile = _sourceFileArray$i[0],
|
|
564
|
+
specsWithOriginal = _sourceFileArray$i[1];
|
|
565
|
+
if (node.type === 'ImportDeclaration') {
|
|
566
|
+
// Transform specifiers if needed (handle aliasing)
|
|
567
|
+
var specs = transformImportSpecifiers({
|
|
568
|
+
specsWithOriginal: specsWithOriginal
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
// Get all existing imports to check for merging
|
|
572
|
+
var allImports = sourceCode.ast.body.filter(function (n) {
|
|
573
|
+
return n.type === 'ImportDeclaration' && n !== node;
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
// Check for existing import
|
|
577
|
+
var existingImport = findExistingImportForSourceFile({
|
|
578
|
+
sourceFile: sourceFile,
|
|
579
|
+
allImports: allImports,
|
|
580
|
+
basedir: basedirForFix,
|
|
581
|
+
fs: fs
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// Skip merging if existing is namespace import
|
|
585
|
+
var isNamespace = existingImport === null || existingImport === void 0 ? void 0 : existingImport.specifiers.some(function (s) {
|
|
586
|
+
return s.type === 'ImportNamespaceSpecifier';
|
|
587
|
+
});
|
|
588
|
+
if (existingImport && !isNamespace) {
|
|
589
|
+
var _specsWithOriginal$0$, _specsWithOriginal$;
|
|
590
|
+
// Merge!
|
|
591
|
+
var existingSpecs = existingImport.specifiers.map(function (s) {
|
|
592
|
+
// Normalize importKind
|
|
593
|
+
if (existingImport.importKind === 'type') {
|
|
594
|
+
// If the parent declaration is 'type', treat all specifiers as 'type'
|
|
595
|
+
// We cast to AugmentedSpecifier to allow attaching importKind to DefaultSpecifier
|
|
596
|
+
return _objectSpread(_objectSpread({}, s), {}, {
|
|
597
|
+
importKind: 'type'
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
return s;
|
|
601
|
+
});
|
|
602
|
+
var newSpecs = specs.map(function (s) {
|
|
603
|
+
if (node.importKind === 'type') {
|
|
604
|
+
return _objectSpread(_objectSpread({}, s), {}, {
|
|
605
|
+
importKind: 'type'
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
return s;
|
|
609
|
+
});
|
|
610
|
+
var mergedSpecs = [].concat((0, _toConsumableArray2.default)(existingSpecs), (0, _toConsumableArray2.default)(newSpecs));
|
|
611
|
+
|
|
612
|
+
// Determine if we should use 'import type'
|
|
613
|
+
var allType = mergedSpecs.every(function (s) {
|
|
614
|
+
return s.importKind === 'type';
|
|
615
|
+
});
|
|
616
|
+
var relativePath = getImportPathForSourceFile({
|
|
617
|
+
sourceFilePath: sourceFile,
|
|
618
|
+
basedir: basedirForFix,
|
|
619
|
+
originalImportPath: importPath,
|
|
620
|
+
exportInfo: (_specsWithOriginal$0$ = (_specsWithOriginal$ = specsWithOriginal[0]) === null || _specsWithOriginal$ === void 0 ? void 0 : _specsWithOriginal$.exportInfo) !== null && _specsWithOriginal$0$ !== void 0 ? _specsWithOriginal$0$ : null,
|
|
621
|
+
workspaceRoot: (0, _fileSystem.findWorkspaceRoot)({
|
|
622
|
+
startPath: basedirForFix,
|
|
623
|
+
fs: fs
|
|
624
|
+
}),
|
|
625
|
+
fs: fs
|
|
626
|
+
});
|
|
627
|
+
var newImportStatement = buildImportStatement({
|
|
628
|
+
specs: mergedSpecs,
|
|
629
|
+
path: relativePath,
|
|
630
|
+
quoteChar: quote,
|
|
631
|
+
isTypeImport: allType // Use type import if all are types
|
|
632
|
+
});
|
|
633
|
+
if (newImportStatement.length > 0) {
|
|
634
|
+
fixes.push(fixer.replaceText(existingImport, newImportStatement));
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
var _specsWithOriginal$0$2, _specsWithOriginal$2;
|
|
638
|
+
// Create new import
|
|
639
|
+
var _relativePath = getImportPathForSourceFile({
|
|
640
|
+
sourceFilePath: sourceFile,
|
|
641
|
+
basedir: basedirForFix,
|
|
642
|
+
originalImportPath: importPath,
|
|
643
|
+
exportInfo: (_specsWithOriginal$0$2 = (_specsWithOriginal$2 = specsWithOriginal[0]) === null || _specsWithOriginal$2 === void 0 ? void 0 : _specsWithOriginal$2.exportInfo) !== null && _specsWithOriginal$0$2 !== void 0 ? _specsWithOriginal$0$2 : null,
|
|
644
|
+
workspaceRoot: (0, _fileSystem.findWorkspaceRoot)({
|
|
645
|
+
startPath: basedirForFix,
|
|
646
|
+
fs: fs
|
|
647
|
+
}),
|
|
648
|
+
fs: fs
|
|
649
|
+
});
|
|
650
|
+
var isTypeImport = node.importKind === 'type';
|
|
651
|
+
var importStatement = buildImportStatement({
|
|
652
|
+
specs: specs,
|
|
653
|
+
path: _relativePath,
|
|
654
|
+
quoteChar: quote,
|
|
655
|
+
isTypeImport: isTypeImport
|
|
656
|
+
});
|
|
657
|
+
if (importStatement.length > 0) {
|
|
658
|
+
newStatementsForBarrelReplacement.push(importStatement);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
} else if (node.type === 'ExportNamedDeclaration') {
|
|
662
|
+
// Handle ExportNamedDeclaration
|
|
663
|
+
var _specs = transformExportSpecifiers({
|
|
664
|
+
specsWithOriginal: specsWithOriginal
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// Get all existing exports to check for merging
|
|
668
|
+
var allExports = sourceCode.ast.body.filter(function (n) {
|
|
669
|
+
return n.type === 'ExportNamedDeclaration' && n !== node && !!n.source;
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
// Check for existing export
|
|
673
|
+
var existingExport = findExistingExportForSourceFile({
|
|
674
|
+
sourceFile: sourceFile,
|
|
675
|
+
allExports: allExports,
|
|
676
|
+
basedir: basedirForFix,
|
|
677
|
+
fs: fs
|
|
678
|
+
});
|
|
679
|
+
if (existingExport) {
|
|
680
|
+
var _specsWithOriginal$0$3, _specsWithOriginal$3;
|
|
681
|
+
// Merge!
|
|
682
|
+
var _existingSpecs = existingExport.specifiers.map(function (s) {
|
|
683
|
+
// For `export type { A, B }`, the parent's exportKind is 'type'
|
|
684
|
+
// Individual specifiers have exportKind: 'type' only for inline type (export { type A })
|
|
685
|
+
// If parent is type-only, all specifiers are types
|
|
686
|
+
// Otherwise, check individual specifier's exportKind
|
|
687
|
+
var effectiveKind = existingExport.exportKind === 'type' || s.exportKind === 'type' ? 'type' : 'value';
|
|
688
|
+
return {
|
|
689
|
+
nameInSource: getExportedName(s.local),
|
|
690
|
+
nameInLocal: getExportedName(s.exported),
|
|
691
|
+
kind: effectiveKind
|
|
692
|
+
};
|
|
693
|
+
});
|
|
694
|
+
var _newSpecs = _specs.map(function (s) {
|
|
695
|
+
if (node.exportKind === 'type') {
|
|
696
|
+
return _objectSpread(_objectSpread({}, s), {}, {
|
|
697
|
+
kind: 'type'
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
return s;
|
|
701
|
+
});
|
|
702
|
+
var _mergedSpecs = [].concat((0, _toConsumableArray2.default)(_existingSpecs), (0, _toConsumableArray2.default)(_newSpecs));
|
|
703
|
+
|
|
704
|
+
// Determine if we should use 'export type'
|
|
705
|
+
var _allType = _mergedSpecs.every(function (s) {
|
|
706
|
+
return s.kind === 'type';
|
|
707
|
+
});
|
|
708
|
+
var _relativePath2 = getImportPathForSourceFile({
|
|
709
|
+
sourceFilePath: sourceFile,
|
|
710
|
+
basedir: basedirForFix,
|
|
711
|
+
originalImportPath: importPath,
|
|
712
|
+
exportInfo: (_specsWithOriginal$0$3 = (_specsWithOriginal$3 = specsWithOriginal[0]) === null || _specsWithOriginal$3 === void 0 ? void 0 : _specsWithOriginal$3.exportInfo) !== null && _specsWithOriginal$0$3 !== void 0 ? _specsWithOriginal$0$3 : null,
|
|
713
|
+
workspaceRoot: (0, _fileSystem.findWorkspaceRoot)({
|
|
714
|
+
startPath: basedirForFix,
|
|
715
|
+
fs: fs
|
|
716
|
+
}),
|
|
717
|
+
fs: fs
|
|
718
|
+
});
|
|
719
|
+
var newExportStatement = buildExportStatement({
|
|
720
|
+
specs: _mergedSpecs,
|
|
721
|
+
path: _relativePath2,
|
|
722
|
+
quoteChar: quote,
|
|
723
|
+
isTypeExport: _allType
|
|
724
|
+
});
|
|
725
|
+
if (newExportStatement.length > 0) {
|
|
726
|
+
fixes.push(fixer.replaceText(existingExport, newExportStatement));
|
|
727
|
+
}
|
|
728
|
+
} else {
|
|
729
|
+
var _specsWithOriginal$0$4, _specsWithOriginal$4;
|
|
730
|
+
// Create new export
|
|
731
|
+
var _relativePath3 = getImportPathForSourceFile({
|
|
732
|
+
sourceFilePath: sourceFile,
|
|
733
|
+
basedir: basedirForFix,
|
|
734
|
+
originalImportPath: importPath,
|
|
735
|
+
exportInfo: (_specsWithOriginal$0$4 = (_specsWithOriginal$4 = specsWithOriginal[0]) === null || _specsWithOriginal$4 === void 0 ? void 0 : _specsWithOriginal$4.exportInfo) !== null && _specsWithOriginal$0$4 !== void 0 ? _specsWithOriginal$0$4 : null,
|
|
736
|
+
workspaceRoot: (0, _fileSystem.findWorkspaceRoot)({
|
|
737
|
+
startPath: basedirForFix,
|
|
738
|
+
fs: fs
|
|
739
|
+
}),
|
|
740
|
+
fs: fs
|
|
741
|
+
});
|
|
742
|
+
var isTypeExport = node.exportKind === 'type';
|
|
743
|
+
var exportStatement = buildExportStatement({
|
|
744
|
+
specs: _specs,
|
|
745
|
+
path: _relativePath3,
|
|
746
|
+
quoteChar: quote,
|
|
747
|
+
isTypeExport: isTypeExport
|
|
748
|
+
});
|
|
749
|
+
if (exportStatement.length > 0) {
|
|
750
|
+
newStatementsForBarrelReplacement.push(exportStatement);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
for (var i = 0; i < sourceFileArray.length; i++) {
|
|
756
|
+
_loop();
|
|
757
|
+
}
|
|
758
|
+
if (newStatementsForBarrelReplacement.length > 0) {
|
|
759
|
+
fixes.push(fixer.replaceText(node, newStatementsForBarrelReplacement.join('\n')));
|
|
760
|
+
} else {
|
|
761
|
+
// If all were merged, remove the node
|
|
762
|
+
fixes.push(fixer.remove(node));
|
|
763
|
+
}
|
|
764
|
+
return fixes;
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
context.report(reportObj);
|
|
768
|
+
};
|
|
769
|
+
return {
|
|
770
|
+
ImportDeclaration: checkNode,
|
|
771
|
+
ExportNamedDeclaration: checkNode
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
var rule = createRule(_types.realFileSystem);
|
|
777
|
+
var _default = exports.default = rule;
|