@atlaskit/eslint-plugin-platform 2.9.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.
- package/CHANGELOG.md +7 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +0 -1
- package/dist/cjs/rules/import/no-barrel-entry-imports/index.js +68 -16
- package/dist/cjs/rules/import/no-barrel-entry-jest-mock/index.js +42 -8
- package/dist/cjs/rules/import/shared/package-resolution.js +153 -8
- package/dist/cjs/rules/no-restricted-fedramp-imports/index.js +65 -0
- package/dist/cjs/rules/visit-example-type-import-required/index.js +1 -1
- package/dist/es2019/index.js +2 -0
- package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +0 -1
- package/dist/es2019/rules/import/no-barrel-entry-imports/index.js +66 -17
- package/dist/es2019/rules/import/no-barrel-entry-jest-mock/index.js +43 -9
- package/dist/es2019/rules/import/shared/package-resolution.js +119 -4
- package/dist/es2019/rules/no-restricted-fedramp-imports/index.js +47 -0
- package/dist/es2019/rules/visit-example-type-import-required/index.js +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +0 -1
- package/dist/esm/rules/import/no-barrel-entry-imports/index.js +69 -17
- package/dist/esm/rules/import/no-barrel-entry-jest-mock/index.js +43 -9
- package/dist/esm/rules/import/shared/package-resolution.js +151 -8
- package/dist/esm/rules/no-restricted-fedramp-imports/index.js +59 -0
- package/dist/esm/rules/visit-example-type-import-required/index.js +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/rules/import/shared/package-resolution.d.ts +25 -0
- package/dist/types/rules/no-restricted-fedramp-imports/index.d.ts +3 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/rules/import/shared/package-resolution.d.ts +25 -0
- package/dist/types-ts4.5/rules/no-restricted-fedramp-imports/index.d.ts +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 2.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`5fed54075f1b8`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/5fed54075f1b8) -
|
|
8
|
+
add eslint rule for restricting isFedramp and isIsolatedCloud imports
|
|
9
|
+
|
|
3
10
|
## 2.9.0
|
|
4
11
|
|
|
5
12
|
### Minor Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -36,6 +36,7 @@ var _noSparseCheckout = _interopRequireDefault(require("./rules/no-sparse-checko
|
|
|
36
36
|
var _noDirectDocumentUsage = _interopRequireDefault(require("./rules/no-direct-document-usage"));
|
|
37
37
|
var _noSetImmediate = _interopRequireDefault(require("./rules/no-set-immediate"));
|
|
38
38
|
var _preferCryptoRandomUuid = _interopRequireDefault(require("./rules/prefer-crypto-random-uuid"));
|
|
39
|
+
var _noRestrictedFedrampImports = _interopRequireDefault(require("./rules/no-restricted-fedramp-imports"));
|
|
39
40
|
var _noBarrelEntryImports = _interopRequireDefault(require("./rules/import/no-barrel-entry-imports"));
|
|
40
41
|
var _noBarrelEntryJestMock = _interopRequireDefault(require("./rules/import/no-barrel-entry-jest-mock"));
|
|
41
42
|
var _noJestMockBarrelFiles = _interopRequireDefault(require("./rules/import/no-jest-mock-barrel-files"));
|
|
@@ -94,6 +95,7 @@ var rules = exports.rules = {
|
|
|
94
95
|
'no-direct-document-usage': _noDirectDocumentUsage.default,
|
|
95
96
|
'no-set-immediate': _noSetImmediate.default,
|
|
96
97
|
'prefer-crypto-random-uuid': _preferCryptoRandomUuid.default,
|
|
98
|
+
'no-restricted-fedramp-imports': _noRestrictedFedrampImports.default,
|
|
97
99
|
'no-barrel-entry-imports': _noBarrelEntryImports.default,
|
|
98
100
|
'no-barrel-entry-jest-mock': _noBarrelEntryJestMock.default,
|
|
99
101
|
'no-jest-mock-barrel-files': _noJestMockBarrelFiles.default,
|
|
@@ -18,7 +18,6 @@ var DESIRED_PKG_VERSIONS = {
|
|
|
18
18
|
tslib: ['2.6', '2.8'],
|
|
19
19
|
'@types/react': ['16.14', '18.2', '18.3'],
|
|
20
20
|
'react-relay': ['npm:atl-react-relay@0.0.0-main-39e79f66'],
|
|
21
|
-
'relay-compiler': ['npm:atl-relay-compiler@0.0.0-main-39e79f66'],
|
|
22
21
|
'relay-runtime': ['npm:atl-relay-runtime@0.0.0-main-39e79f66'],
|
|
23
22
|
'relay-test-utils': ['npm:atl-relay-test-utils@0.0.0-main-39e79f66']
|
|
24
23
|
};
|
|
@@ -48,6 +48,10 @@ var ruleMeta = {
|
|
|
48
48
|
type: 'string'
|
|
49
49
|
},
|
|
50
50
|
description: 'The folder paths (relative to workspace root) containing packages whose imports will be checked and autofixed.'
|
|
51
|
+
},
|
|
52
|
+
preferImportedPackageSubpath: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
description: 'Prefer subpaths on the imported barrel package when they bridge to the dependency (e.g. @scope/pkg/subpath instead of @scope/dependency).'
|
|
51
55
|
}
|
|
52
56
|
},
|
|
53
57
|
additionalProperties: false
|
|
@@ -247,10 +251,12 @@ function classifySpecifiers(_ref4) {
|
|
|
247
251
|
var node = _ref4.node,
|
|
248
252
|
importContext = _ref4.importContext,
|
|
249
253
|
workspaceRoot = _ref4.workspaceRoot,
|
|
250
|
-
fs = _ref4.fs
|
|
254
|
+
fs = _ref4.fs,
|
|
255
|
+
preferImportedPackageSubpath = _ref4.preferImportedPackageSubpath;
|
|
251
256
|
var currentExportPath = importContext.currentExportPath,
|
|
252
257
|
exportsMap = importContext.exportsMap,
|
|
253
|
-
exportMap = importContext.exportMap
|
|
258
|
+
exportMap = importContext.exportMap,
|
|
259
|
+
importedPackageName = importContext.packageName;
|
|
254
260
|
var specifiers = node.specifiers;
|
|
255
261
|
var specifiersByTarget = new Map();
|
|
256
262
|
var unmappedSpecifiers = [];
|
|
@@ -271,6 +277,7 @@ function classifySpecifiers(_ref4) {
|
|
|
271
277
|
var kind = 'value';
|
|
272
278
|
if (spec.type === 'ImportDefaultSpecifier') {
|
|
273
279
|
nameInSource = 'default';
|
|
280
|
+
kind = node.importKind === 'type' ? 'type' : 'value';
|
|
274
281
|
} else if (spec.type === 'ImportSpecifier') {
|
|
275
282
|
nameInSource = getImportedName(spec);
|
|
276
283
|
var parentImportKind = node.importKind;
|
|
@@ -286,6 +293,36 @@ function classifySpecifiers(_ref4) {
|
|
|
286
293
|
// Check if this is a cross-package re-export
|
|
287
294
|
var sourcePackageName = (_exportInfo$crossPack = exportInfo.crossPackageSource) === null || _exportInfo$crossPack === void 0 ? void 0 : _exportInfo$crossPack.packageName;
|
|
288
295
|
if (sourcePackageName) {
|
|
296
|
+
var targetKey = void 0;
|
|
297
|
+
var resolvedOriginalName = exportInfo.originalName;
|
|
298
|
+
if (preferImportedPackageSubpath) {
|
|
299
|
+
var bridge = (0, _packageResolution.findCrossPackageBridgeExportPath)({
|
|
300
|
+
exportsMap: exportsMap,
|
|
301
|
+
crossPackageName: sourcePackageName,
|
|
302
|
+
exportedName: nameInSource,
|
|
303
|
+
fs: fs
|
|
304
|
+
});
|
|
305
|
+
if (bridge) {
|
|
306
|
+
targetKey = importedPackageName + bridge.exportPath.slice(1);
|
|
307
|
+
if (bridge.entryPointExportName !== undefined) {
|
|
308
|
+
resolvedOriginalName = bridge.entryPointExportName === nameInSource ? undefined : bridge.entryPointExportName;
|
|
309
|
+
}
|
|
310
|
+
if (!specifiersByTarget.has(targetKey)) {
|
|
311
|
+
specifiersByTarget.set(targetKey, []);
|
|
312
|
+
}
|
|
313
|
+
specifiersByTarget.get(targetKey).push({
|
|
314
|
+
spec: _objectSpread(_objectSpread({}, spec), {}, {
|
|
315
|
+
importKind: effectiveKind
|
|
316
|
+
}),
|
|
317
|
+
originalName: resolvedOriginalName,
|
|
318
|
+
targetExportPath: targetKey,
|
|
319
|
+
kind: effectiveKind,
|
|
320
|
+
sourcePackageName: sourcePackageName
|
|
321
|
+
});
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
289
326
|
// For cross-package re-exports, find the most specific subpath in the source package
|
|
290
327
|
// Note: Package resolution is not constrained by applyToImportsFrom - any package can be resolved
|
|
291
328
|
var sourcePackageExportsMap = sourcePackageExportsMaps.get(sourcePackageName);
|
|
@@ -306,7 +343,6 @@ function classifySpecifiers(_ref4) {
|
|
|
306
343
|
|
|
307
344
|
// Find the best export path in the source package
|
|
308
345
|
var _targetExportPath = null;
|
|
309
|
-
var resolvedOriginalName = exportInfo.originalName;
|
|
310
346
|
if (sourcePackageExportsMap) {
|
|
311
347
|
var _exportInfo$originalN, _matchResult$exportPa;
|
|
312
348
|
var _sourceExportName = (_exportInfo$originalN = exportInfo.originalName) !== null && _exportInfo$originalN !== void 0 ? _exportInfo$originalN : nameInSource;
|
|
@@ -323,7 +359,7 @@ function classifySpecifiers(_ref4) {
|
|
|
323
359
|
}
|
|
324
360
|
|
|
325
361
|
// Build the full import path: @package/subpath or just @package if no subpath found
|
|
326
|
-
|
|
362
|
+
targetKey = _targetExportPath ? sourcePackageName + _targetExportPath.slice(1) // Remove leading '.' from subpath
|
|
327
363
|
: sourcePackageName;
|
|
328
364
|
if (!specifiersByTarget.has(targetKey)) {
|
|
329
365
|
specifiersByTarget.set(targetKey, []);
|
|
@@ -698,7 +734,10 @@ function createBarrelImportFix(_ref0) {
|
|
|
698
734
|
}
|
|
699
735
|
} else {
|
|
700
736
|
// Create new import
|
|
701
|
-
var
|
|
737
|
+
var allSpecsAreType = specsWithTarget.every(function (s) {
|
|
738
|
+
return s.kind === 'type';
|
|
739
|
+
});
|
|
740
|
+
var _isTypeImport = node.importKind === 'type' || allSpecsAreType;
|
|
702
741
|
var importStatement = buildImportStatement({
|
|
703
742
|
specs: specs,
|
|
704
743
|
path: newImportPath,
|
|
@@ -724,7 +763,10 @@ function createBarrelImportFix(_ref0) {
|
|
|
724
763
|
var unmappedSpecs = unmappedSpecifiers.map(function (u) {
|
|
725
764
|
return u.spec;
|
|
726
765
|
});
|
|
727
|
-
var
|
|
766
|
+
var allUnmappedAreType = unmappedSpecifiers.every(function (u) {
|
|
767
|
+
return u.kind === 'type';
|
|
768
|
+
});
|
|
769
|
+
var isTypeImport = node.importKind === 'type' || allUnmappedAreType;
|
|
728
770
|
var remainingImport = buildImportStatement({
|
|
729
771
|
specs: unmappedSpecs,
|
|
730
772
|
path: importPath,
|
|
@@ -900,7 +942,8 @@ function handleRequireMemberExpression(_ref13) {
|
|
|
900
942
|
context = _ref13.context,
|
|
901
943
|
workspaceRoot = _ref13.workspaceRoot,
|
|
902
944
|
fs = _ref13.fs,
|
|
903
|
-
applyToImportsFrom = _ref13.applyToImportsFrom
|
|
945
|
+
applyToImportsFrom = _ref13.applyToImportsFrom,
|
|
946
|
+
preferImportedPackageSubpath = _ref13.preferImportedPackageSubpath;
|
|
904
947
|
if (node.computed || node.property.type !== 'Identifier') {
|
|
905
948
|
return;
|
|
906
949
|
}
|
|
@@ -924,7 +967,8 @@ function handleRequireMemberExpression(_ref13) {
|
|
|
924
967
|
node: synthetic,
|
|
925
968
|
importContext: importContext,
|
|
926
969
|
workspaceRoot: workspaceRoot,
|
|
927
|
-
fs: fs
|
|
970
|
+
fs: fs,
|
|
971
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
928
972
|
}),
|
|
929
973
|
specifiersByTarget = _classifySpecifiers.specifiersByTarget,
|
|
930
974
|
hasNamespaceImport = _classifySpecifiers.hasNamespaceImport;
|
|
@@ -982,7 +1026,8 @@ function handleRequireDestructuringDeclarator(_ref16) {
|
|
|
982
1026
|
context = _ref16.context,
|
|
983
1027
|
workspaceRoot = _ref16.workspaceRoot,
|
|
984
1028
|
fs = _ref16.fs,
|
|
985
|
-
applyToImportsFrom = _ref16.applyToImportsFrom
|
|
1029
|
+
applyToImportsFrom = _ref16.applyToImportsFrom,
|
|
1030
|
+
preferImportedPackageSubpath = _ref16.preferImportedPackageSubpath;
|
|
986
1031
|
if (node.id.type !== 'ObjectPattern' || !node.init || node.init.type !== 'CallExpression') {
|
|
987
1032
|
return;
|
|
988
1033
|
}
|
|
@@ -1048,7 +1093,8 @@ function handleRequireDestructuringDeclarator(_ref16) {
|
|
|
1048
1093
|
node: synthetic,
|
|
1049
1094
|
importContext: importContext,
|
|
1050
1095
|
workspaceRoot: workspaceRoot,
|
|
1051
|
-
fs: fs
|
|
1096
|
+
fs: fs,
|
|
1097
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1052
1098
|
}),
|
|
1053
1099
|
specifiersByTarget = _classifySpecifiers2.specifiersByTarget,
|
|
1054
1100
|
unmappedSpecifiers = _classifySpecifiers2.unmappedSpecifiers,
|
|
@@ -1158,7 +1204,8 @@ function handleImportDeclaration(_ref19) {
|
|
|
1158
1204
|
context = _ref19.context,
|
|
1159
1205
|
workspaceRoot = _ref19.workspaceRoot,
|
|
1160
1206
|
fs = _ref19.fs,
|
|
1161
|
-
applyToImportsFrom = _ref19.applyToImportsFrom
|
|
1207
|
+
applyToImportsFrom = _ref19.applyToImportsFrom,
|
|
1208
|
+
preferImportedPackageSubpath = _ref19.preferImportedPackageSubpath;
|
|
1162
1209
|
// Resolve import context (validates and extracts package/export info)
|
|
1163
1210
|
// applyToImportsFrom is used here to filter which packages the rule applies to
|
|
1164
1211
|
var importContext = resolveImportContext({
|
|
@@ -1181,7 +1228,8 @@ function handleImportDeclaration(_ref19) {
|
|
|
1181
1228
|
node: node,
|
|
1182
1229
|
importContext: importContext,
|
|
1183
1230
|
workspaceRoot: workspaceRoot,
|
|
1184
|
-
fs: fs
|
|
1231
|
+
fs: fs,
|
|
1232
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1185
1233
|
}),
|
|
1186
1234
|
specifiersByTarget = _classifySpecifiers3.specifiersByTarget,
|
|
1187
1235
|
unmappedSpecifiers = _classifySpecifiers3.unmappedSpecifiers,
|
|
@@ -1234,9 +1282,10 @@ function createRule(fs) {
|
|
|
1234
1282
|
return {
|
|
1235
1283
|
meta: ruleMeta,
|
|
1236
1284
|
create: function create(context) {
|
|
1237
|
-
var _options$applyToImpor;
|
|
1285
|
+
var _options$applyToImpor, _options$preferImport;
|
|
1238
1286
|
var options = context.options[0] || {};
|
|
1239
1287
|
var applyToImportsFrom = (_options$applyToImpor = options.applyToImportsFrom) !== null && _options$applyToImpor !== void 0 ? _options$applyToImpor : _fileSystem.DEFAULT_TARGET_FOLDERS;
|
|
1288
|
+
var preferImportedPackageSubpath = (_options$preferImport = options.preferImportedPackageSubpath) !== null && _options$preferImport !== void 0 ? _options$preferImport : false;
|
|
1240
1289
|
var workspaceRoot = (0, _fileSystem.findWorkspaceRoot)({
|
|
1241
1290
|
startPath: (0, _path.dirname)(context.filename),
|
|
1242
1291
|
fs: fs,
|
|
@@ -1250,7 +1299,8 @@ function createRule(fs) {
|
|
|
1250
1299
|
context: context,
|
|
1251
1300
|
workspaceRoot: workspaceRoot,
|
|
1252
1301
|
fs: fs,
|
|
1253
|
-
applyToImportsFrom: applyToImportsFrom
|
|
1302
|
+
applyToImportsFrom: applyToImportsFrom,
|
|
1303
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1254
1304
|
});
|
|
1255
1305
|
},
|
|
1256
1306
|
MemberExpression: function MemberExpression(rawNode) {
|
|
@@ -1259,7 +1309,8 @@ function createRule(fs) {
|
|
|
1259
1309
|
context: context,
|
|
1260
1310
|
workspaceRoot: workspaceRoot,
|
|
1261
1311
|
fs: fs,
|
|
1262
|
-
applyToImportsFrom: applyToImportsFrom
|
|
1312
|
+
applyToImportsFrom: applyToImportsFrom,
|
|
1313
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1263
1314
|
});
|
|
1264
1315
|
},
|
|
1265
1316
|
VariableDeclarator: function VariableDeclarator(rawNode) {
|
|
@@ -1268,7 +1319,8 @@ function createRule(fs) {
|
|
|
1268
1319
|
context: context,
|
|
1269
1320
|
workspaceRoot: workspaceRoot,
|
|
1270
1321
|
fs: fs,
|
|
1271
|
-
applyToImportsFrom: applyToImportsFrom
|
|
1322
|
+
applyToImportsFrom: applyToImportsFrom,
|
|
1323
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1272
1324
|
});
|
|
1273
1325
|
}
|
|
1274
1326
|
};
|
|
@@ -671,7 +671,9 @@ function traceSymbolsToExports(_ref10) {
|
|
|
671
671
|
exportMap = _ref10.exportMap,
|
|
672
672
|
exportsMap = _ref10.exportsMap,
|
|
673
673
|
currentExportPath = _ref10.currentExportPath,
|
|
674
|
-
fs = _ref10.fs
|
|
674
|
+
fs = _ref10.fs,
|
|
675
|
+
barrelPackageName = _ref10.barrelPackageName,
|
|
676
|
+
preferImportedPackageSubpath = _ref10.preferImportedPackageSubpath;
|
|
675
677
|
var groupedByExport = new Map();
|
|
676
678
|
var crossPackageGroups = new Map();
|
|
677
679
|
var unmappedSymbols = [];
|
|
@@ -689,16 +691,38 @@ function traceSymbolsToExports(_ref10) {
|
|
|
689
691
|
|
|
690
692
|
// Check for cross-package source first
|
|
691
693
|
if (exportInfo.crossPackageSource) {
|
|
692
|
-
var key =
|
|
694
|
+
var key = void 0;
|
|
695
|
+
var tracedOriginalName = exportInfo.originalName;
|
|
696
|
+
var barrelBridgeExportPath = void 0;
|
|
697
|
+
if (preferImportedPackageSubpath) {
|
|
698
|
+
var bridge = (0, _packageResolution.findCrossPackageBridgeExportPath)({
|
|
699
|
+
exportsMap: exportsMap,
|
|
700
|
+
crossPackageName: exportInfo.crossPackageSource.packageName,
|
|
701
|
+
exportedName: symbolName,
|
|
702
|
+
fs: fs
|
|
703
|
+
});
|
|
704
|
+
if (bridge) {
|
|
705
|
+
key = "".concat(barrelPackageName).concat(bridge.exportPath.slice(1));
|
|
706
|
+
barrelBridgeExportPath = bridge.exportPath;
|
|
707
|
+
if (bridge.entryPointExportName !== undefined) {
|
|
708
|
+
tracedOriginalName = bridge.entryPointExportName === symbolName ? undefined : bridge.entryPointExportName;
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
key = "".concat(exportInfo.crossPackageSource.packageName).concat(exportInfo.crossPackageSource.exportPath === '.' ? '' : exportInfo.crossPackageSource.exportPath.slice(1));
|
|
712
|
+
}
|
|
713
|
+
} else {
|
|
714
|
+
key = "".concat(exportInfo.crossPackageSource.packageName).concat(exportInfo.crossPackageSource.exportPath === '.' ? '' : exportInfo.crossPackageSource.exportPath.slice(1));
|
|
715
|
+
}
|
|
693
716
|
if (!crossPackageGroups.has(key)) {
|
|
694
717
|
crossPackageGroups.set(key, []);
|
|
695
718
|
}
|
|
696
719
|
crossPackageGroups.get(key).push({
|
|
697
720
|
symbolName: symbolName,
|
|
698
|
-
originalName:
|
|
721
|
+
originalName: tracedOriginalName,
|
|
699
722
|
sourceFilePath: exportInfo.path,
|
|
700
723
|
isTypeOnly: exportInfo.isTypeOnly,
|
|
701
|
-
crossPackageSource: exportInfo.crossPackageSource
|
|
724
|
+
crossPackageSource: exportInfo.crossPackageSource,
|
|
725
|
+
barrelBridgeExportPath: barrelBridgeExportPath
|
|
702
726
|
});
|
|
703
727
|
continue;
|
|
704
728
|
}
|
|
@@ -1069,6 +1093,10 @@ var ruleMeta = {
|
|
|
1069
1093
|
type: 'string'
|
|
1070
1094
|
},
|
|
1071
1095
|
description: 'The folder paths (relative to workspace root) containing packages whose imports will be checked and autofixed.'
|
|
1096
|
+
},
|
|
1097
|
+
preferImportedPackageSubpath: {
|
|
1098
|
+
type: 'boolean',
|
|
1099
|
+
description: 'Prefer subpaths on the mocked barrel package when they bridge to the dependency.'
|
|
1072
1100
|
}
|
|
1073
1101
|
},
|
|
1074
1102
|
additionalProperties: false
|
|
@@ -1087,9 +1115,10 @@ function createRule(fs) {
|
|
|
1087
1115
|
return {
|
|
1088
1116
|
meta: ruleMeta,
|
|
1089
1117
|
create: function create(context) {
|
|
1090
|
-
var _options$applyToImpor;
|
|
1118
|
+
var _options$applyToImpor, _options$preferImport;
|
|
1091
1119
|
var options = context.options[0] || {};
|
|
1092
1120
|
var applyToImportsFrom = (_options$applyToImpor = options.applyToImportsFrom) !== null && _options$applyToImpor !== void 0 ? _options$applyToImpor : _fileSystem.DEFAULT_TARGET_FOLDERS;
|
|
1121
|
+
var preferImportedPackageSubpath = (_options$preferImport = options.preferImportedPackageSubpath) !== null && _options$preferImport !== void 0 ? _options$preferImport : false;
|
|
1093
1122
|
var workspaceRoot = (0, _fileSystem.findWorkspaceRoot)({
|
|
1094
1123
|
startPath: (0, _path.dirname)(context.filename),
|
|
1095
1124
|
fs: fs,
|
|
@@ -1184,7 +1213,9 @@ function createRule(fs) {
|
|
|
1184
1213
|
exportMap: raContext.exportMap,
|
|
1185
1214
|
exportsMap: raContext.exportsMap,
|
|
1186
1215
|
currentExportPath: raContext.currentExportPath,
|
|
1187
|
-
fs: fs
|
|
1216
|
+
fs: fs,
|
|
1217
|
+
barrelPackageName: raContext.packageName,
|
|
1218
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1188
1219
|
}),
|
|
1189
1220
|
_groupedByExport = _traceSymbolsToExport.groupedByExport,
|
|
1190
1221
|
_crossPackageGroups = _traceSymbolsToExport.crossPackageGroups;
|
|
@@ -1281,7 +1312,9 @@ function createRule(fs) {
|
|
|
1281
1312
|
exportMap: mockContext.exportMap,
|
|
1282
1313
|
exportsMap: mockContext.exportsMap,
|
|
1283
1314
|
currentExportPath: mockContext.currentExportPath,
|
|
1284
|
-
fs: fs
|
|
1315
|
+
fs: fs,
|
|
1316
|
+
barrelPackageName: mockContext.packageName,
|
|
1317
|
+
preferImportedPackageSubpath: preferImportedPackageSubpath
|
|
1285
1318
|
}),
|
|
1286
1319
|
groupedByExport = _traceSymbolsToExport2.groupedByExport,
|
|
1287
1320
|
crossPackageGroups = _traceSymbolsToExport2.crossPackageGroups,
|
|
@@ -1373,8 +1406,9 @@ function createRule(fs) {
|
|
|
1373
1406
|
|
|
1374
1407
|
// Get cross-package source info from the first symbol (all symbols in same group have same source)
|
|
1375
1408
|
var crossPackageSource = _symbols[0].crossPackageSource;
|
|
1409
|
+
var bridgeExportPath = _symbols[0].barrelBridgeExportPath;
|
|
1376
1410
|
crossPackageMockGroups.push({
|
|
1377
|
-
exportPath: crossPackageSource.exportPath,
|
|
1411
|
+
exportPath: bridgeExportPath !== null && bridgeExportPath !== void 0 ? bridgeExportPath : crossPackageSource.exportPath,
|
|
1378
1412
|
importPath: _importPath,
|
|
1379
1413
|
propertyNames: _symbols.map(function (s) {
|
|
1380
1414
|
return s.symbolName;
|
|
@@ -6,7 +6,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.extractPackageNameFromImport = extractPackageNameFromImport;
|
|
9
|
+
exports.findCrossPackageBridgeExportPath = findCrossPackageBridgeExportPath;
|
|
9
10
|
exports.findExportForSourceFile = findExportForSourceFile;
|
|
11
|
+
exports.isKebabCaseExportKey = isKebabCaseExportKey;
|
|
10
12
|
exports.parsePackageExports = parsePackageExports;
|
|
11
13
|
exports.resolveCrossPackageImport = resolveCrossPackageImport;
|
|
12
14
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
@@ -173,10 +175,52 @@ function parsePackageExports(_ref2) {
|
|
|
173
175
|
});
|
|
174
176
|
return exportsMap;
|
|
175
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Check whether a subpath export key (e.g. `"./checkbox-select"`) is kebab-case.
|
|
180
|
+
*
|
|
181
|
+
* A key is considered kebab-case when the portion after the leading `"./"` prefix
|
|
182
|
+
* consists only of lowercase letters, digits, hyphens, dots, and forward-slash
|
|
183
|
+
* separators — i.e. no uppercase letters, underscores, or camelCase humps.
|
|
184
|
+
*/
|
|
185
|
+
function isKebabCaseExportKey(key) {
|
|
186
|
+
var body = key.replace(/^\.\//, '');
|
|
187
|
+
if (body.length === 0) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return /^[a-z0-9][a-z0-9\-./]*$/.test(body);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Given a list of candidate {@link ExportMatchResult}s that all resolve to the same
|
|
195
|
+
* source file, pick the best one. When any candidate's export path is kebab-case
|
|
196
|
+
* and points to an entry-point file, prefer it over non-kebab-case alternatives.
|
|
197
|
+
* Falls back to the first candidate if no kebab-case entry-point candidate is found.
|
|
198
|
+
*/
|
|
199
|
+
function pickBestMatch(candidates, exportsMap) {
|
|
200
|
+
if (candidates.length === 1) {
|
|
201
|
+
return candidates[0];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Among candidates whose value is an entry-point file, prefer kebab-case keys.
|
|
205
|
+
var entryPointKebab = candidates.filter(function (c) {
|
|
206
|
+
var resolved = exportsMap.get(c.exportPath);
|
|
207
|
+
return resolved && isInEntryPointsFolder(resolved) && isKebabCaseExportKey(c.exportPath);
|
|
208
|
+
});
|
|
209
|
+
if (entryPointKebab.length > 0) {
|
|
210
|
+
return entryPointKebab[0];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Fall back to the first candidate (preserves previous behaviour).
|
|
214
|
+
return candidates[0];
|
|
215
|
+
}
|
|
216
|
+
|
|
176
217
|
/**
|
|
177
218
|
* Find a matching export entry for a given source file path.
|
|
178
219
|
* Returns the export path (e.g., "./controllers/analytics") or null if not found.
|
|
179
220
|
*
|
|
221
|
+
* When multiple export paths resolve to the same source file **and** point to an
|
|
222
|
+
* entry-point file, kebab-case keys are preferred over other casing styles.
|
|
223
|
+
*
|
|
180
224
|
* When `fs` is provided, also checks entry-point wrapper files. If an export resolves
|
|
181
225
|
* to a file inside a recognized entry-points folder (entry-points, entrypoints, etc.),
|
|
182
226
|
* the wrapper is parsed to see if it re-exports from `sourceFilePath`.
|
|
@@ -190,6 +234,8 @@ function findExportForSourceFile(_ref3) {
|
|
|
190
234
|
exportsMap = _ref3.exportsMap,
|
|
191
235
|
fs = _ref3.fs,
|
|
192
236
|
sourceExportName = _ref3.sourceExportName;
|
|
237
|
+
// --- Phase 1: direct matches (export value === sourceFilePath) ---
|
|
238
|
+
var directMatches = [];
|
|
193
239
|
var _iterator3 = _createForOfIteratorHelper(exportsMap),
|
|
194
240
|
_step3;
|
|
195
241
|
try {
|
|
@@ -198,9 +244,9 @@ function findExportForSourceFile(_ref3) {
|
|
|
198
244
|
_exportPath = _step3$value[0],
|
|
199
245
|
_resolvedPath = _step3$value[1];
|
|
200
246
|
if (_resolvedPath === sourceFilePath) {
|
|
201
|
-
|
|
247
|
+
directMatches.push({
|
|
202
248
|
exportPath: _exportPath
|
|
203
|
-
};
|
|
249
|
+
});
|
|
204
250
|
}
|
|
205
251
|
}
|
|
206
252
|
} catch (err) {
|
|
@@ -208,7 +254,13 @@ function findExportForSourceFile(_ref3) {
|
|
|
208
254
|
} finally {
|
|
209
255
|
_iterator3.f();
|
|
210
256
|
}
|
|
257
|
+
if (directMatches.length > 0) {
|
|
258
|
+
return pickBestMatch(directMatches, exportsMap);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// --- Phase 2: entry-point wrapper re-export matches ---
|
|
211
262
|
if (fs) {
|
|
263
|
+
var entryPointMatches = [];
|
|
212
264
|
var _iterator4 = _createForOfIteratorHelper(exportsMap),
|
|
213
265
|
_step4;
|
|
214
266
|
try {
|
|
@@ -231,10 +283,10 @@ function findExportForSourceFile(_ref3) {
|
|
|
231
283
|
if (sourceExportName !== undefined && reExport.nameMap.has(sourceExportName)) {
|
|
232
284
|
entryPointExportName = reExport.nameMap.get(sourceExportName);
|
|
233
285
|
}
|
|
234
|
-
|
|
286
|
+
entryPointMatches.push({
|
|
235
287
|
exportPath: exportPath,
|
|
236
288
|
entryPointExportName: entryPointExportName
|
|
237
|
-
};
|
|
289
|
+
});
|
|
238
290
|
}
|
|
239
291
|
}
|
|
240
292
|
} catch (err) {
|
|
@@ -249,6 +301,99 @@ function findExportForSourceFile(_ref3) {
|
|
|
249
301
|
} finally {
|
|
250
302
|
_iterator4.f();
|
|
251
303
|
}
|
|
304
|
+
if (entryPointMatches.length > 0) {
|
|
305
|
+
return pickBestMatch(entryPointMatches, exportsMap);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* When a symbol reaches the consumer through a barrel package that re-exports from
|
|
313
|
+
* `crossPackageName`, find a `package.json` export subpath of that barrel whose entry
|
|
314
|
+
* file directly re-exports the symbol from `crossPackageName` (named exports only).
|
|
315
|
+
*
|
|
316
|
+
* This enables rewriting imports to `@scope/barrel/subpath` instead of
|
|
317
|
+
* `@scope/cross-package/...` when the barrel exposes such a subpath (e.g. `@atlaskit/select/react-select`).
|
|
318
|
+
*/
|
|
319
|
+
function findCrossPackageBridgeExportPath(_ref4) {
|
|
320
|
+
var exportsMap = _ref4.exportsMap,
|
|
321
|
+
crossPackageName = _ref4.crossPackageName,
|
|
322
|
+
exportedName = _ref4.exportedName,
|
|
323
|
+
fs = _ref4.fs;
|
|
324
|
+
var _iterator6 = _createForOfIteratorHelper(exportsMap),
|
|
325
|
+
_step6;
|
|
326
|
+
try {
|
|
327
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
328
|
+
var _step6$value = (0, _slicedToArray2.default)(_step6.value, 2),
|
|
329
|
+
exportPath = _step6$value[0],
|
|
330
|
+
resolvedPath = _step6$value[1];
|
|
331
|
+
var content = (0, _fileSystem.readFileContent)({
|
|
332
|
+
filePath: resolvedPath,
|
|
333
|
+
fs: fs
|
|
334
|
+
});
|
|
335
|
+
if (!content) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
try {
|
|
339
|
+
var sourceFile = ts.createSourceFile(resolvedPath, content, ts.ScriptTarget.Latest, true);
|
|
340
|
+
var _iterator7 = _createForOfIteratorHelper(sourceFile.statements),
|
|
341
|
+
_step7;
|
|
342
|
+
try {
|
|
343
|
+
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
344
|
+
var statement = _step7.value;
|
|
345
|
+
if (!ts.isExportDeclaration(statement) || statement.isTypeOnly) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (!statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (statement.moduleSpecifier.text !== crossPackageName) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (!statement.exportClause || ts.isNamespaceExport(statement.exportClause)) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (!ts.isNamedExports(statement.exportClause)) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
var _iterator8 = _createForOfIteratorHelper(statement.exportClause.elements),
|
|
361
|
+
_step8;
|
|
362
|
+
try {
|
|
363
|
+
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
364
|
+
var element = _step8.value;
|
|
365
|
+
if (element.isTypeOnly) {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
var publicName = element.name.text;
|
|
369
|
+
if (publicName !== exportedName) {
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
var entryPointExportName = element.propertyName ? element.propertyName.text : undefined;
|
|
373
|
+
return {
|
|
374
|
+
exportPath: exportPath,
|
|
375
|
+
entryPointExportName: entryPointExportName
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
} catch (err) {
|
|
379
|
+
_iterator8.e(err);
|
|
380
|
+
} finally {
|
|
381
|
+
_iterator8.f();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
} catch (err) {
|
|
385
|
+
_iterator7.e(err);
|
|
386
|
+
} finally {
|
|
387
|
+
_iterator7.f();
|
|
388
|
+
}
|
|
389
|
+
} catch (_unused4) {
|
|
390
|
+
// Ignore parse errors for individual export entry files
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
} catch (err) {
|
|
394
|
+
_iterator6.e(err);
|
|
395
|
+
} finally {
|
|
396
|
+
_iterator6.f();
|
|
252
397
|
}
|
|
253
398
|
return null;
|
|
254
399
|
}
|
|
@@ -272,10 +417,10 @@ function extractPackageNameFromImport(moduleSpecifier) {
|
|
|
272
417
|
* Resolve a cross-package import to its package directory and export info.
|
|
273
418
|
* Returns null if the package is not in the target folder or cannot be resolved.
|
|
274
419
|
*/
|
|
275
|
-
function resolveCrossPackageImport(
|
|
276
|
-
var moduleSpecifier =
|
|
277
|
-
workspaceRoot =
|
|
278
|
-
fs =
|
|
420
|
+
function resolveCrossPackageImport(_ref5) {
|
|
421
|
+
var moduleSpecifier = _ref5.moduleSpecifier,
|
|
422
|
+
workspaceRoot = _ref5.workspaceRoot,
|
|
423
|
+
fs = _ref5.fs;
|
|
279
424
|
// Only handle @atlassian/* scoped packages
|
|
280
425
|
var parsed = extractPackageNameFromImport(moduleSpecifier);
|
|
281
426
|
if (!parsed) {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
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; } } }; }
|
|
8
|
+
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; } }
|
|
9
|
+
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; }
|
|
10
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
11
|
+
|
|
12
|
+
var RESTRICTED_IMPORTS = {
|
|
13
|
+
'@atlassian/atl-context': ['isFedRamp', 'isIsolatedCloud'],
|
|
14
|
+
'@atlaskit/atlassian-context': ['isFedRamp', 'isIsolatedCloud'],
|
|
15
|
+
'@atlassian/teams-common': ['isFedramp']
|
|
16
|
+
};
|
|
17
|
+
var rule = {
|
|
18
|
+
meta: {
|
|
19
|
+
type: 'problem',
|
|
20
|
+
docs: {
|
|
21
|
+
description: 'Disallow importing deprecated FedRamp/IsolatedCloud context functions. Use isFeatureEnabled from AEM (Atlassian Environment Manager) instead.',
|
|
22
|
+
recommended: true
|
|
23
|
+
},
|
|
24
|
+
messages: {
|
|
25
|
+
noRestrictedFedrampImports: '{{name}} from {{source}} will be deprecated soon. Please use isFeatureEnabled from AEM (Atlassian Environment Manager) instead. See go/AEM for more details.'
|
|
26
|
+
},
|
|
27
|
+
schema: []
|
|
28
|
+
},
|
|
29
|
+
create: function create(context) {
|
|
30
|
+
return {
|
|
31
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
|
32
|
+
var source = node.source.value;
|
|
33
|
+
if (typeof source !== 'string') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
var restrictedNames = RESTRICTED_IMPORTS[source];
|
|
37
|
+
if (!restrictedNames) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
var _iterator = _createForOfIteratorHelper(node.specifiers),
|
|
41
|
+
_step;
|
|
42
|
+
try {
|
|
43
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
44
|
+
var specifier = _step.value;
|
|
45
|
+
if (specifier.type === 'ImportSpecifier' && restrictedNames.includes(specifier.imported.name)) {
|
|
46
|
+
context.report({
|
|
47
|
+
node: specifier,
|
|
48
|
+
messageId: 'noRestrictedFedrampImports',
|
|
49
|
+
data: {
|
|
50
|
+
name: specifier.imported.name,
|
|
51
|
+
source: source
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
_iterator.e(err);
|
|
58
|
+
} finally {
|
|
59
|
+
_iterator.f();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var _default = exports.default = rule;
|
|
@@ -24,7 +24,7 @@ var messages = {
|
|
|
24
24
|
suggestFixPath: 'Update import path to match visitExample arguments'
|
|
25
25
|
};
|
|
26
26
|
function isTargetFile(filename) {
|
|
27
|
-
return filename.endsWith('.spec.tsx');
|
|
27
|
+
return filename.endsWith('.spec.tsx') || filename.endsWith('.spec.ts');
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
package/dist/es2019/index.js
CHANGED
|
@@ -29,6 +29,7 @@ import noSparseCheckout from './rules/no-sparse-checkout';
|
|
|
29
29
|
import noDirectDocumentUsage from './rules/no-direct-document-usage';
|
|
30
30
|
import noSetImmediate from './rules/no-set-immediate';
|
|
31
31
|
import preferCryptoRandomUuid from './rules/prefer-crypto-random-uuid';
|
|
32
|
+
import noRestrictedFedrampImports from './rules/no-restricted-fedramp-imports';
|
|
32
33
|
import noBarrelEntryImports from './rules/import/no-barrel-entry-imports';
|
|
33
34
|
import noBarrelEntryJestMock from './rules/import/no-barrel-entry-jest-mock';
|
|
34
35
|
import noJestMockBarrelFiles from './rules/import/no-jest-mock-barrel-files';
|
|
@@ -85,6 +86,7 @@ const rules = {
|
|
|
85
86
|
'no-direct-document-usage': noDirectDocumentUsage,
|
|
86
87
|
'no-set-immediate': noSetImmediate,
|
|
87
88
|
'prefer-crypto-random-uuid': preferCryptoRandomUuid,
|
|
89
|
+
'no-restricted-fedramp-imports': noRestrictedFedrampImports,
|
|
88
90
|
'no-barrel-entry-imports': noBarrelEntryImports,
|
|
89
91
|
'no-barrel-entry-jest-mock': noBarrelEntryJestMock,
|
|
90
92
|
'no-jest-mock-barrel-files': noJestMockBarrelFiles,
|