@atlaskit/eslint-plugin-platform 2.8.0 → 2.9.1

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 (47) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/index.js +8 -1
  3. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +0 -1
  4. package/dist/cjs/rules/ensure-use-sync-external-store-server-snapshot/index.js +41 -0
  5. package/dist/cjs/rules/import/no-barrel-entry-imports/index.js +534 -74
  6. package/dist/cjs/rules/import/no-barrel-entry-jest-mock/index.js +428 -119
  7. package/dist/cjs/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  8. package/dist/cjs/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  9. package/dist/cjs/rules/import/shared/jest-utils.js +62 -9
  10. package/dist/cjs/rules/import/shared/package-resolution.js +300 -22
  11. package/dist/cjs/rules/no-restricted-fedramp-imports/index.js +65 -0
  12. package/dist/cjs/rules/visit-example-type-import-required/index.js +409 -0
  13. package/dist/es2019/index.js +8 -1
  14. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +0 -1
  15. package/dist/es2019/rules/ensure-use-sync-external-store-server-snapshot/index.js +43 -0
  16. package/dist/es2019/rules/import/no-barrel-entry-imports/index.js +431 -25
  17. package/dist/es2019/rules/import/no-barrel-entry-jest-mock/index.js +287 -25
  18. package/dist/es2019/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  19. package/dist/es2019/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  20. package/dist/es2019/rules/import/shared/jest-utils.js +44 -0
  21. package/dist/es2019/rules/import/shared/package-resolution.js +211 -4
  22. package/dist/es2019/rules/no-restricted-fedramp-imports/index.js +47 -0
  23. package/dist/es2019/rules/visit-example-type-import-required/index.js +375 -0
  24. package/dist/esm/index.js +8 -1
  25. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +0 -1
  26. package/dist/esm/rules/ensure-use-sync-external-store-server-snapshot/index.js +35 -0
  27. package/dist/esm/rules/import/no-barrel-entry-imports/index.js +535 -75
  28. package/dist/esm/rules/import/no-barrel-entry-jest-mock/index.js +430 -121
  29. package/dist/esm/rules/import/no-jest-mock-barrel-files/index.js +3 -2
  30. package/dist/esm/rules/import/no-relative-barrel-file-imports/index.js +7 -3
  31. package/dist/esm/rules/import/shared/jest-utils.js +61 -9
  32. package/dist/esm/rules/import/shared/package-resolution.js +298 -24
  33. package/dist/esm/rules/no-restricted-fedramp-imports/index.js +59 -0
  34. package/dist/esm/rules/visit-example-type-import-required/index.js +402 -0
  35. package/dist/types/index.d.ts +14 -0
  36. package/dist/types/rules/ensure-use-sync-external-store-server-snapshot/index.d.ts +3 -0
  37. package/dist/types/rules/import/shared/jest-utils.d.ts +8 -0
  38. package/dist/types/rules/import/shared/package-resolution.d.ts +47 -2
  39. package/dist/types/rules/no-restricted-fedramp-imports/index.d.ts +3 -0
  40. package/dist/types/rules/visit-example-type-import-required/index.d.ts +4 -0
  41. package/dist/types-ts4.5/index.d.ts +14 -0
  42. package/dist/types-ts4.5/rules/ensure-use-sync-external-store-server-snapshot/index.d.ts +3 -0
  43. package/dist/types-ts4.5/rules/import/shared/jest-utils.d.ts +8 -0
  44. package/dist/types-ts4.5/rules/import/shared/package-resolution.d.ts +47 -2
  45. package/dist/types-ts4.5/rules/no-restricted-fedramp-imports/index.d.ts +3 -0
  46. package/dist/types-ts4.5/rules/visit-example-type-import-required/index.d.ts +4 -0
  47. package/package.json +3 -1
@@ -222,6 +222,7 @@ function getImportPathForSourceFile(_ref) {
222
222
  fs = _ref.fs;
223
223
  var crossPackageName = exportInfo === null || exportInfo === void 0 || (_exportInfo$crossPack = exportInfo.crossPackageSource) === null || _exportInfo$crossPack === void 0 ? void 0 : _exportInfo$crossPack.packageName;
224
224
  if (crossPackageName) {
225
+ var _findExportForSourceF;
225
226
  var sourcePackageExportsMaps = getSourcePackageExportsMaps(fs);
226
227
  var exportsMap = sourcePackageExportsMaps.get(crossPackageName);
227
228
  if (!exportsMap) {
@@ -238,10 +239,10 @@ function getImportPathForSourceFile(_ref) {
238
239
  sourcePackageExportsMaps.set(crossPackageName, exportsMap);
239
240
  }
240
241
  }
241
- var targetExportPath = exportsMap ? findExportForSourceFile({
242
+ var targetExportPath = exportsMap ? (_findExportForSourceF = findExportForSourceFile({
242
243
  sourceFilePath: sourceFilePath,
243
244
  exportsMap: exportsMap
244
- }) : null;
245
+ })) === null || _findExportForSourceF === void 0 ? void 0 : _findExportForSourceF.exportPath : null;
245
246
  return targetExportPath ? crossPackageName + targetExportPath.slice(1) : crossPackageName;
246
247
  }
247
248
  return getRelativeImportPath({
@@ -61,6 +61,7 @@ function getImportPathForSourceFile(_ref) {
61
61
  fs = _ref.fs;
62
62
  var crossPackageName = exportInfo === null || exportInfo === void 0 || (_exportInfo$crossPack = exportInfo.crossPackageSource) === null || _exportInfo$crossPack === void 0 ? void 0 : _exportInfo$crossPack.packageName;
63
63
  if (crossPackageName) {
64
+ var _findExportForSourceF;
64
65
  var sourcePackageExportsMaps = getSourcePackageExportsMaps(fs);
65
66
  var exportsMap = sourcePackageExportsMaps.get(crossPackageName);
66
67
  if (!exportsMap) {
@@ -77,10 +78,10 @@ function getImportPathForSourceFile(_ref) {
77
78
  sourcePackageExportsMaps.set(crossPackageName, exportsMap);
78
79
  }
79
80
  }
80
- var targetExportPath = exportsMap ? findExportForSourceFile({
81
+ var targetExportPath = exportsMap ? (_findExportForSourceF = findExportForSourceFile({
81
82
  sourceFilePath: sourceFilePath,
82
83
  exportsMap: exportsMap
83
- }) : null;
84
+ })) === null || _findExportForSourceF === void 0 ? void 0 : _findExportForSourceF.exportPath : null;
84
85
  return targetExportPath ? crossPackageName + targetExportPath.slice(1) : crossPackageName;
85
86
  }
86
87
  return getRelativeImportPath({
@@ -459,10 +460,13 @@ function transformExportSpecifiers(_ref1) {
459
460
  var specsWithOriginal = _ref1.specsWithOriginal;
460
461
  return specsWithOriginal.map(function (_ref10) {
461
462
  var originalName = _ref10.originalName,
463
+ nameInSource = _ref10.nameInSource,
462
464
  nameInLocal = _ref10.nameInLocal,
463
465
  kind = _ref10.kind;
464
466
  return {
465
- nameInSource: originalName || 'default',
467
+ // Use originalName if available (means there was an alias in the barrel),
468
+ // otherwise use nameInSource (the direct export name from the barrel)
469
+ nameInSource: originalName !== null && originalName !== void 0 ? originalName : nameInSource,
466
470
  nameInLocal: nameInLocal,
467
471
  kind: kind
468
472
  };
@@ -124,6 +124,58 @@ export function findJestRequireMockCalls(_ref) {
124
124
  return results;
125
125
  }
126
126
 
127
+ /**
128
+ * Find all jest.requireActual() calls in the AST whose import path matches a given target.
129
+ * Works identically to findJestRequireMockCalls but for requireActual.
130
+ */
131
+ export function findJestRequireActualCalls(_ref2) {
132
+ var ast = _ref2.ast,
133
+ matchPath = _ref2.matchPath;
134
+ var results = [];
135
+ var visited = new WeakSet();
136
+ var skipKeys = new Set(['parent', 'loc', 'range', 'tokens', 'comments']);
137
+ function visit(node) {
138
+ if (visited.has(node)) {
139
+ return;
140
+ }
141
+ visited.add(node);
142
+ if (node.type === 'CallExpression' && isJestRequireActual(node)) {
143
+ var path = extractImportPath(node);
144
+ if (path && matchPath(path)) {
145
+ results.push(node);
146
+ }
147
+ }
148
+ for (var key in node) {
149
+ if (skipKeys.has(key)) {
150
+ continue;
151
+ }
152
+ var value = node[key];
153
+ if (value && _typeof(value) === 'object') {
154
+ if (Array.isArray(value)) {
155
+ var _iterator2 = _createForOfIteratorHelper(value),
156
+ _step2;
157
+ try {
158
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
159
+ var child = _step2.value;
160
+ if (child && _typeof(child) === 'object' && 'type' in child) {
161
+ visit(child);
162
+ }
163
+ }
164
+ } catch (err) {
165
+ _iterator2.e(err);
166
+ } finally {
167
+ _iterator2.f();
168
+ }
169
+ } else if ('type' in value) {
170
+ visit(value);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ visit(ast);
176
+ return results;
177
+ }
178
+
127
179
  /**
128
180
  * Determine the best new import path for a jest.requireMock() call by inspecting
129
181
  * the destructured symbols or property access at the call site.
@@ -132,20 +184,20 @@ export function findJestRequireMockCalls(_ref) {
132
184
  * @param symbolToNewPath - Map from symbol name to the new mock path that provides it
133
185
  * @returns The resolved new path, or null if it cannot be determined
134
186
  */
135
- export function resolveNewPathForRequireMock(_ref2) {
136
- var requireMockNode = _ref2.requireMockNode,
137
- symbolToNewPath = _ref2.symbolToNewPath;
187
+ export function resolveNewPathForRequireMock(_ref3) {
188
+ var requireMockNode = _ref3.requireMockNode,
189
+ symbolToNewPath = _ref3.symbolToNewPath;
138
190
  var parent = requireMockNode.parent;
139
191
  if (parent) {
140
192
  var _parent;
141
193
  // Check for destructuring pattern: const { foo } = jest.requireMock('...')
142
194
  var declarator = parent.type === 'VariableDeclarator' ? parent : ((_parent = parent.parent) === null || _parent === void 0 ? void 0 : _parent.type) === 'VariableDeclarator' ? parent.parent : null;
143
195
  if (declarator && declarator.type === 'VariableDeclarator' && declarator.id.type === 'ObjectPattern') {
144
- var _iterator2 = _createForOfIteratorHelper(declarator.id.properties),
145
- _step2;
196
+ var _iterator3 = _createForOfIteratorHelper(declarator.id.properties),
197
+ _step3;
146
198
  try {
147
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
148
- var prop = _step2.value;
199
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
200
+ var prop = _step3.value;
149
201
  if (prop.type === 'Property' && prop.key.type === 'Identifier') {
150
202
  var matchedPath = symbolToNewPath.get(prop.key.name);
151
203
  if (matchedPath) {
@@ -154,9 +206,9 @@ export function resolveNewPathForRequireMock(_ref2) {
154
206
  }
155
207
  }
156
208
  } catch (err) {
157
- _iterator2.e(err);
209
+ _iterator3.e(err);
158
210
  } finally {
159
- _iterator2.f();
211
+ _iterator3.f();
160
212
  }
161
213
  }
162
214
 
@@ -3,15 +3,93 @@ import _typeof from "@babel/runtime/helpers/typeof";
3
3
  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; } } }; }
4
4
  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; } }
5
5
  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; }
6
- import { join } from 'path';
7
- import { readFileContent, resolveImportPath } from './file-system';
6
+ import { dirname, join } from 'path';
7
+ import * as ts from 'typescript';
8
+ import { isRelativeImport, readFileContent, resolveImportPath } from './file-system';
8
9
  import { findPackageInRegistry } from './package-registry';
10
+ var ENTRY_POINT_FOLDER_NAMES = new Set(['entry-points', 'entrypoints', 'entrypoint', 'entry-point']);
11
+ function isInEntryPointsFolder(filePath) {
12
+ var parts = filePath.split(/[/\\]/);
13
+ return parts.some(function (part) {
14
+ return ENTRY_POINT_FOLDER_NAMES.has(part);
15
+ });
16
+ }
9
17
  /**
10
- * Parse the package.json exports field and return a map of export paths to resolved file paths.
18
+ * Parse an entry-point wrapper file and resolve the source files it re-exports from,
19
+ * along with name mappings (source export name → entry-point export name).
11
20
  */
12
- export function parsePackageExports(_ref) {
13
- var packageDir = _ref.packageDir,
21
+ function resolveEntryPointReExports(_ref) {
22
+ var entryPointFilePath = _ref.entryPointFilePath,
14
23
  fs = _ref.fs;
24
+ var content = readFileContent({
25
+ filePath: entryPointFilePath,
26
+ fs: fs
27
+ });
28
+ if (!content) {
29
+ return [];
30
+ }
31
+ try {
32
+ var sourceFile = ts.createSourceFile(entryPointFilePath, content, ts.ScriptTarget.Latest, true);
33
+ var basedir = dirname(entryPointFilePath);
34
+ var results = [];
35
+ var _iterator = _createForOfIteratorHelper(sourceFile.statements),
36
+ _step;
37
+ try {
38
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
39
+ var statement = _step.value;
40
+ if (ts.isExportDeclaration(statement) && statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier)) {
41
+ var modulePath = statement.moduleSpecifier.text;
42
+ if (!isRelativeImport(modulePath)) {
43
+ continue;
44
+ }
45
+ var resolved = resolveImportPath({
46
+ basedir: basedir,
47
+ importPath: modulePath,
48
+ fs: fs
49
+ });
50
+ if (!resolved) {
51
+ continue;
52
+ }
53
+ var nameMap = new Map();
54
+ if (statement.exportClause && ts.isNamedExports(statement.exportClause)) {
55
+ var _iterator2 = _createForOfIteratorHelper(statement.exportClause.elements),
56
+ _step2;
57
+ try {
58
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
59
+ var element = _step2.value;
60
+ var exportedName = element.name.text;
61
+ var sourceName = element.propertyName ? element.propertyName.text : exportedName;
62
+ nameMap.set(sourceName, exportedName);
63
+ }
64
+ } catch (err) {
65
+ _iterator2.e(err);
66
+ } finally {
67
+ _iterator2.f();
68
+ }
69
+ }
70
+ results.push({
71
+ sourcePath: resolved,
72
+ nameMap: nameMap
73
+ });
74
+ }
75
+ }
76
+ } catch (err) {
77
+ _iterator.e(err);
78
+ } finally {
79
+ _iterator.f();
80
+ }
81
+ return results;
82
+ } catch (_unused) {
83
+ return [];
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Parse the package.json exports field and return a map of export paths to resolved file paths.
89
+ */
90
+ export function parsePackageExports(_ref2) {
91
+ var packageDir = _ref2.packageDir,
92
+ fs = _ref2.fs;
15
93
  // Memoize per-package to avoid repeated reads/parses during IDE lint runs.
16
94
  // Additionally, invalidate per-package if the package.json mtime changes
17
95
  // (covers unstaged local edits in IDE).
@@ -23,7 +101,7 @@ export function parsePackageExports(_ref) {
23
101
  try {
24
102
  var _fs$statSync$mtimeMs;
25
103
  currentMtimeMs = (_fs$statSync$mtimeMs = fs.statSync(packageJsonPath).mtimeMs) !== null && _fs$statSync$mtimeMs !== void 0 ? _fs$statSync$mtimeMs : null;
26
- } catch (_unused) {
104
+ } catch (_unused2) {
27
105
  // If package.json can't be stat'ed (missing/inaccessible), use null to force re-read
28
106
  currentMtimeMs = null;
29
107
  }
@@ -72,7 +150,7 @@ export function parsePackageExports(_ref) {
72
150
  }
73
151
  }
74
152
  }
75
- } catch (_unused2) {
153
+ } catch (_unused3) {
76
154
  // Ignore parsing errors
77
155
  }
78
156
 
@@ -83,29 +161,225 @@ export function parsePackageExports(_ref) {
83
161
  });
84
162
  return exportsMap;
85
163
  }
164
+ /**
165
+ * Check whether a subpath export key (e.g. `"./checkbox-select"`) is kebab-case.
166
+ *
167
+ * A key is considered kebab-case when the portion after the leading `"./"` prefix
168
+ * consists only of lowercase letters, digits, hyphens, dots, and forward-slash
169
+ * separators — i.e. no uppercase letters, underscores, or camelCase humps.
170
+ */
171
+ export function isKebabCaseExportKey(key) {
172
+ var body = key.replace(/^\.\//, '');
173
+ if (body.length === 0) {
174
+ return false;
175
+ }
176
+ return /^[a-z0-9][a-z0-9\-./]*$/.test(body);
177
+ }
178
+
179
+ /**
180
+ * Given a list of candidate {@link ExportMatchResult}s that all resolve to the same
181
+ * source file, pick the best one. When any candidate's export path is kebab-case
182
+ * and points to an entry-point file, prefer it over non-kebab-case alternatives.
183
+ * Falls back to the first candidate if no kebab-case entry-point candidate is found.
184
+ */
185
+ function pickBestMatch(candidates, exportsMap) {
186
+ if (candidates.length === 1) {
187
+ return candidates[0];
188
+ }
189
+
190
+ // Among candidates whose value is an entry-point file, prefer kebab-case keys.
191
+ var entryPointKebab = candidates.filter(function (c) {
192
+ var resolved = exportsMap.get(c.exportPath);
193
+ return resolved && isInEntryPointsFolder(resolved) && isKebabCaseExportKey(c.exportPath);
194
+ });
195
+ if (entryPointKebab.length > 0) {
196
+ return entryPointKebab[0];
197
+ }
198
+
199
+ // Fall back to the first candidate (preserves previous behaviour).
200
+ return candidates[0];
201
+ }
86
202
 
87
203
  /**
88
204
  * Find a matching export entry for a given source file path.
89
205
  * Returns the export path (e.g., "./controllers/analytics") or null if not found.
206
+ *
207
+ * When multiple export paths resolve to the same source file **and** point to an
208
+ * entry-point file, kebab-case keys are preferred over other casing styles.
209
+ *
210
+ * When `fs` is provided, also checks entry-point wrapper files. If an export resolves
211
+ * to a file inside a recognized entry-points folder (entry-points, entrypoints, etc.),
212
+ * the wrapper is parsed to see if it re-exports from `sourceFilePath`.
213
+ *
214
+ * `sourceExportName` is the name under which the symbol is exported from the source file
215
+ * (e.g. `'default'`). Used to look up the corresponding entry-point export name so the
216
+ * caller can generate the correct import style.
90
217
  */
91
- export function findExportForSourceFile(_ref2) {
92
- var sourceFilePath = _ref2.sourceFilePath,
93
- exportsMap = _ref2.exportsMap;
94
- var _iterator = _createForOfIteratorHelper(exportsMap),
95
- _step;
218
+ export function findExportForSourceFile(_ref3) {
219
+ var sourceFilePath = _ref3.sourceFilePath,
220
+ exportsMap = _ref3.exportsMap,
221
+ fs = _ref3.fs,
222
+ sourceExportName = _ref3.sourceExportName;
223
+ // --- Phase 1: direct matches (export value === sourceFilePath) ---
224
+ var directMatches = [];
225
+ var _iterator3 = _createForOfIteratorHelper(exportsMap),
226
+ _step3;
96
227
  try {
97
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
98
- var _step$value = _slicedToArray(_step.value, 2),
99
- exportPath = _step$value[0],
100
- resolvedPath = _step$value[1];
101
- if (resolvedPath === sourceFilePath) {
102
- return exportPath;
228
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
229
+ var _step3$value = _slicedToArray(_step3.value, 2),
230
+ _exportPath = _step3$value[0],
231
+ _resolvedPath = _step3$value[1];
232
+ if (_resolvedPath === sourceFilePath) {
233
+ directMatches.push({
234
+ exportPath: _exportPath
235
+ });
236
+ }
237
+ }
238
+ } catch (err) {
239
+ _iterator3.e(err);
240
+ } finally {
241
+ _iterator3.f();
242
+ }
243
+ if (directMatches.length > 0) {
244
+ return pickBestMatch(directMatches, exportsMap);
245
+ }
246
+
247
+ // --- Phase 2: entry-point wrapper re-export matches ---
248
+ if (fs) {
249
+ var entryPointMatches = [];
250
+ var _iterator4 = _createForOfIteratorHelper(exportsMap),
251
+ _step4;
252
+ try {
253
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
254
+ var _step4$value = _slicedToArray(_step4.value, 2),
255
+ exportPath = _step4$value[0],
256
+ resolvedPath = _step4$value[1];
257
+ if (isInEntryPointsFolder(resolvedPath)) {
258
+ var reExports = resolveEntryPointReExports({
259
+ entryPointFilePath: resolvedPath,
260
+ fs: fs
261
+ });
262
+ var _iterator5 = _createForOfIteratorHelper(reExports),
263
+ _step5;
264
+ try {
265
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
266
+ var reExport = _step5.value;
267
+ if (reExport.sourcePath === sourceFilePath) {
268
+ var entryPointExportName = void 0;
269
+ if (sourceExportName !== undefined && reExport.nameMap.has(sourceExportName)) {
270
+ entryPointExportName = reExport.nameMap.get(sourceExportName);
271
+ }
272
+ entryPointMatches.push({
273
+ exportPath: exportPath,
274
+ entryPointExportName: entryPointExportName
275
+ });
276
+ }
277
+ }
278
+ } catch (err) {
279
+ _iterator5.e(err);
280
+ } finally {
281
+ _iterator5.f();
282
+ }
283
+ }
284
+ }
285
+ } catch (err) {
286
+ _iterator4.e(err);
287
+ } finally {
288
+ _iterator4.f();
289
+ }
290
+ if (entryPointMatches.length > 0) {
291
+ return pickBestMatch(entryPointMatches, exportsMap);
292
+ }
293
+ }
294
+ return null;
295
+ }
296
+
297
+ /**
298
+ * When a symbol reaches the consumer through a barrel package that re-exports from
299
+ * `crossPackageName`, find a `package.json` export subpath of that barrel whose entry
300
+ * file directly re-exports the symbol from `crossPackageName` (named exports only).
301
+ *
302
+ * This enables rewriting imports to `@scope/barrel/subpath` instead of
303
+ * `@scope/cross-package/...` when the barrel exposes such a subpath (e.g. `@atlaskit/select/react-select`).
304
+ */
305
+ export function findCrossPackageBridgeExportPath(_ref4) {
306
+ var exportsMap = _ref4.exportsMap,
307
+ crossPackageName = _ref4.crossPackageName,
308
+ exportedName = _ref4.exportedName,
309
+ fs = _ref4.fs;
310
+ var _iterator6 = _createForOfIteratorHelper(exportsMap),
311
+ _step6;
312
+ try {
313
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
314
+ var _step6$value = _slicedToArray(_step6.value, 2),
315
+ exportPath = _step6$value[0],
316
+ resolvedPath = _step6$value[1];
317
+ var content = readFileContent({
318
+ filePath: resolvedPath,
319
+ fs: fs
320
+ });
321
+ if (!content) {
322
+ continue;
323
+ }
324
+ try {
325
+ var sourceFile = ts.createSourceFile(resolvedPath, content, ts.ScriptTarget.Latest, true);
326
+ var _iterator7 = _createForOfIteratorHelper(sourceFile.statements),
327
+ _step7;
328
+ try {
329
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
330
+ var statement = _step7.value;
331
+ if (!ts.isExportDeclaration(statement) || statement.isTypeOnly) {
332
+ continue;
333
+ }
334
+ if (!statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier)) {
335
+ continue;
336
+ }
337
+ if (statement.moduleSpecifier.text !== crossPackageName) {
338
+ continue;
339
+ }
340
+ if (!statement.exportClause || ts.isNamespaceExport(statement.exportClause)) {
341
+ continue;
342
+ }
343
+ if (!ts.isNamedExports(statement.exportClause)) {
344
+ continue;
345
+ }
346
+ var _iterator8 = _createForOfIteratorHelper(statement.exportClause.elements),
347
+ _step8;
348
+ try {
349
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
350
+ var element = _step8.value;
351
+ if (element.isTypeOnly) {
352
+ continue;
353
+ }
354
+ var publicName = element.name.text;
355
+ if (publicName !== exportedName) {
356
+ continue;
357
+ }
358
+ var entryPointExportName = element.propertyName ? element.propertyName.text : undefined;
359
+ return {
360
+ exportPath: exportPath,
361
+ entryPointExportName: entryPointExportName
362
+ };
363
+ }
364
+ } catch (err) {
365
+ _iterator8.e(err);
366
+ } finally {
367
+ _iterator8.f();
368
+ }
369
+ }
370
+ } catch (err) {
371
+ _iterator7.e(err);
372
+ } finally {
373
+ _iterator7.f();
374
+ }
375
+ } catch (_unused4) {
376
+ // Ignore parse errors for individual export entry files
103
377
  }
104
378
  }
105
379
  } catch (err) {
106
- _iterator.e(err);
380
+ _iterator6.e(err);
107
381
  } finally {
108
- _iterator.f();
382
+ _iterator6.f();
109
383
  }
110
384
  return null;
111
385
  }
@@ -129,10 +403,10 @@ export function extractPackageNameFromImport(moduleSpecifier) {
129
403
  * Resolve a cross-package import to its package directory and export info.
130
404
  * Returns null if the package is not in the target folder or cannot be resolved.
131
405
  */
132
- export function resolveCrossPackageImport(_ref3) {
133
- var moduleSpecifier = _ref3.moduleSpecifier,
134
- workspaceRoot = _ref3.workspaceRoot,
135
- fs = _ref3.fs;
406
+ export function resolveCrossPackageImport(_ref5) {
407
+ var moduleSpecifier = _ref5.moduleSpecifier,
408
+ workspaceRoot = _ref5.workspaceRoot,
409
+ fs = _ref5.fs;
136
410
  // Only handle @atlassian/* scoped packages
137
411
  var parsed = extractPackageNameFromImport(moduleSpecifier);
138
412
  if (!parsed) {
@@ -0,0 +1,59 @@
1
+ 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; } } }; }
2
+ 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; } }
3
+ 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; }
4
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+
6
+ var RESTRICTED_IMPORTS = {
7
+ '@atlassian/atl-context': ['isFedRamp', 'isIsolatedCloud'],
8
+ '@atlaskit/atlassian-context': ['isFedRamp', 'isIsolatedCloud'],
9
+ '@atlassian/teams-common': ['isFedramp']
10
+ };
11
+ var rule = {
12
+ meta: {
13
+ type: 'problem',
14
+ docs: {
15
+ description: 'Disallow importing deprecated FedRamp/IsolatedCloud context functions. Use isFeatureEnabled from AEM (Atlassian Environment Manager) instead.',
16
+ recommended: true
17
+ },
18
+ messages: {
19
+ noRestrictedFedrampImports: '{{name}} from {{source}} will be deprecated soon. Please use isFeatureEnabled from AEM (Atlassian Environment Manager) instead. See go/AEM for more details.'
20
+ },
21
+ schema: []
22
+ },
23
+ create: function create(context) {
24
+ return {
25
+ ImportDeclaration: function ImportDeclaration(node) {
26
+ var source = node.source.value;
27
+ if (typeof source !== 'string') {
28
+ return;
29
+ }
30
+ var restrictedNames = RESTRICTED_IMPORTS[source];
31
+ if (!restrictedNames) {
32
+ return;
33
+ }
34
+ var _iterator = _createForOfIteratorHelper(node.specifiers),
35
+ _step;
36
+ try {
37
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
38
+ var specifier = _step.value;
39
+ if (specifier.type === 'ImportSpecifier' && restrictedNames.includes(specifier.imported.name)) {
40
+ context.report({
41
+ node: specifier,
42
+ messageId: 'noRestrictedFedrampImports',
43
+ data: {
44
+ name: specifier.imported.name,
45
+ source: source
46
+ }
47
+ });
48
+ }
49
+ }
50
+ } catch (err) {
51
+ _iterator.e(err);
52
+ } finally {
53
+ _iterator.f();
54
+ }
55
+ }
56
+ };
57
+ }
58
+ };
59
+ export default rule;