@conarti/eslint-plugin-feature-sliced 2.0.0-rc.6 → 2.0.0-rc.7
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/dist/index.cjs +237 -10
- package/dist/index.d.cts +33 -3
- package/dist/index.d.ts +33 -3
- package/dist/index.js +237 -10
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,8 @@ var RULE_NAMES = {
|
|
|
4
4
|
LAYERS_SLICES: `${PLUGIN_NAME}/layers-slices`,
|
|
5
5
|
ABSOLUTE_RELATIVE: `${PLUGIN_NAME}/absolute-relative`,
|
|
6
6
|
PUBLIC_API: `${PLUGIN_NAME}/public-api`,
|
|
7
|
-
IMPORT_ORDER: `${PLUGIN_NAME}/import-order
|
|
7
|
+
IMPORT_ORDER: `${PLUGIN_NAME}/import-order`,
|
|
8
|
+
NO_CROSS_SEGMENT_REEXPORT: `${PLUGIN_NAME}/no-cross-segment-reexport`
|
|
8
9
|
};
|
|
9
10
|
var layers = [
|
|
10
11
|
"shared",
|
|
@@ -79,7 +80,7 @@ function canLayerContainSlices(layer, config) {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
// package.json
|
|
82
|
-
var version = "2.0.0-rc.
|
|
83
|
+
var version = "2.0.0-rc.7";
|
|
83
84
|
|
|
84
85
|
// src/rules/index.ts
|
|
85
86
|
var _eslintpluginimportx = require('eslint-plugin-import-x'); var _eslintpluginimportx2 = _interopRequireDefault(_eslintpluginimportx);
|
|
@@ -840,6 +841,228 @@ var layers_slices_default = createEslintRule({
|
|
|
840
841
|
}
|
|
841
842
|
});
|
|
842
843
|
|
|
844
|
+
// src/rules/no-cross-segment-reexport/config.ts
|
|
845
|
+
var ERROR_MESSAGE_ID3 = {
|
|
846
|
+
NO_CROSS_SEGMENT_REEXPORT: "no-cross-segment-reexport",
|
|
847
|
+
MOVE_TO_SLICE_PUBLIC_API_SUGGESTION: "move-to-slice-public-api-suggestion"
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// src/rules/no-cross-segment-reexport/model/errors.ts
|
|
851
|
+
function buildSlicePublicApiPath(sourcePath, targetSegment) {
|
|
852
|
+
const parts = sourcePath.split("/");
|
|
853
|
+
const segmentIndex = parts.findIndex((part) => part === targetSegment);
|
|
854
|
+
if (segmentIndex !== -1) {
|
|
855
|
+
return parts.slice(0, segmentIndex).join("/");
|
|
856
|
+
}
|
|
857
|
+
return parts.slice(0, -1).join("/") || "..";
|
|
858
|
+
}
|
|
859
|
+
function reportCrossSegmentReexport(context, node, currentSegment, targetSegment) {
|
|
860
|
+
const sourcePath = node.source.value;
|
|
861
|
+
const suggestedPath = buildSlicePublicApiPath(sourcePath, targetSegment);
|
|
862
|
+
context.report({
|
|
863
|
+
node: node.source,
|
|
864
|
+
messageId: ERROR_MESSAGE_ID3.NO_CROSS_SEGMENT_REEXPORT,
|
|
865
|
+
data: {
|
|
866
|
+
currentSegment,
|
|
867
|
+
targetSegment
|
|
868
|
+
},
|
|
869
|
+
suggest: [
|
|
870
|
+
{
|
|
871
|
+
messageId: ERROR_MESSAGE_ID3.MOVE_TO_SLICE_PUBLIC_API_SUGGESTION,
|
|
872
|
+
data: {
|
|
873
|
+
suggestedPath
|
|
874
|
+
},
|
|
875
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
876
|
+
getSourceRangeWithoutQuotes(node.source.range),
|
|
877
|
+
suggestedPath
|
|
878
|
+
)
|
|
879
|
+
}
|
|
880
|
+
]
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/rules/no-cross-segment-reexport/model/is-cross-segment-reexport.ts
|
|
885
|
+
var NOT_CROSS_SEGMENT = {
|
|
886
|
+
isCrossSegmentReexport: false,
|
|
887
|
+
currentSegment: null,
|
|
888
|
+
targetSegment: null
|
|
889
|
+
};
|
|
890
|
+
var FILE_EXT_REGEXP = /\..+$/;
|
|
891
|
+
var KNOWN_SEGMENTS = segments.map((s) => s.toLowerCase());
|
|
892
|
+
function splitPathParts(path3) {
|
|
893
|
+
return path3.split("/").filter(Boolean);
|
|
894
|
+
}
|
|
895
|
+
function normalizeToDirParts(parts) {
|
|
896
|
+
const INDEX_FILE_REGEXP = /^index\..+$/;
|
|
897
|
+
return parts.reduce((acc, part) => {
|
|
898
|
+
if (INDEX_FILE_REGEXP.test(part))
|
|
899
|
+
return acc;
|
|
900
|
+
if (FILE_EXT_REGEXP.test(part)) {
|
|
901
|
+
acc.push(part.replace(FILE_EXT_REGEXP, ""));
|
|
902
|
+
return acc;
|
|
903
|
+
}
|
|
904
|
+
acc.push(part);
|
|
905
|
+
return acc;
|
|
906
|
+
}, []);
|
|
907
|
+
}
|
|
908
|
+
function findLayerIndex(parts, layersWithSlices2) {
|
|
909
|
+
return parts.findIndex(
|
|
910
|
+
(part) => layersWithSlices2.includes(part.toLowerCase())
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function extractSegmentAndSlice(pathParts) {
|
|
914
|
+
if (pathParts.length < 2)
|
|
915
|
+
return null;
|
|
916
|
+
const knownSegmentIndex = pathParts.findIndex(
|
|
917
|
+
(part) => KNOWN_SEGMENTS.includes(part.toLowerCase())
|
|
918
|
+
);
|
|
919
|
+
let segmentIndex;
|
|
920
|
+
if (knownSegmentIndex > 0) {
|
|
921
|
+
segmentIndex = knownSegmentIndex;
|
|
922
|
+
} else if (knownSegmentIndex === 0) {
|
|
923
|
+
return null;
|
|
924
|
+
} else {
|
|
925
|
+
segmentIndex = pathParts.length - 1;
|
|
926
|
+
if (segmentIndex < 1)
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
const segment = pathParts[segmentIndex];
|
|
930
|
+
const sliceParts = pathParts.slice(0, segmentIndex);
|
|
931
|
+
if (sliceParts.length === 0)
|
|
932
|
+
return null;
|
|
933
|
+
return { segment, sliceParts };
|
|
934
|
+
}
|
|
935
|
+
function findTargetSegmentInSameSlice(targetPathParts, currentSliceParts, currentSegment) {
|
|
936
|
+
if (targetPathParts.length === 0)
|
|
937
|
+
return null;
|
|
938
|
+
if (currentSliceParts.length > targetPathParts.length)
|
|
939
|
+
return null;
|
|
940
|
+
const targetHasSameSlice = currentSliceParts.every(
|
|
941
|
+
(part, i) => part.toLowerCase() === _optionalChain([targetPathParts, 'access', _9 => _9[i], 'optionalAccess', _10 => _10.toLowerCase, 'call', _11 => _11()])
|
|
942
|
+
);
|
|
943
|
+
if (!targetHasSameSlice)
|
|
944
|
+
return null;
|
|
945
|
+
const targetSegmentCandidate = targetPathParts[currentSliceParts.length];
|
|
946
|
+
if (!targetSegmentCandidate)
|
|
947
|
+
return null;
|
|
948
|
+
if (targetSegmentCandidate.toLowerCase() !== currentSegment.toLowerCase()) {
|
|
949
|
+
return targetSegmentCandidate;
|
|
950
|
+
}
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
function isCrossSegmentReexport(normalizedCurrentFilePath, absoluteTargetPath, config) {
|
|
954
|
+
const layersConfig = _nullishCoalesce(config, () => ( normalizeLayersConfig()));
|
|
955
|
+
const layersWithSlices2 = getLayersWithSlices(layersConfig).map((l) => l.toLowerCase());
|
|
956
|
+
const currentParts = splitPathParts(normalizedCurrentFilePath);
|
|
957
|
+
const targetParts = splitPathParts(absoluteTargetPath);
|
|
958
|
+
const currentLayerIndex = findLayerIndex(currentParts, layersWithSlices2);
|
|
959
|
+
if (currentLayerIndex === -1)
|
|
960
|
+
return NOT_CROSS_SEGMENT;
|
|
961
|
+
const currentAfterLayer = currentParts.slice(currentLayerIndex + 1);
|
|
962
|
+
const currentPathParts = normalizeToDirParts(currentAfterLayer);
|
|
963
|
+
const currentInfo = extractSegmentAndSlice(currentPathParts);
|
|
964
|
+
if (!currentInfo)
|
|
965
|
+
return NOT_CROSS_SEGMENT;
|
|
966
|
+
const targetLayerIndex = findLayerIndex(targetParts, layersWithSlices2);
|
|
967
|
+
if (targetLayerIndex === -1)
|
|
968
|
+
return NOT_CROSS_SEGMENT;
|
|
969
|
+
if (currentParts[currentLayerIndex].toLowerCase() !== targetParts[targetLayerIndex].toLowerCase()) {
|
|
970
|
+
return NOT_CROSS_SEGMENT;
|
|
971
|
+
}
|
|
972
|
+
const targetAfterLayer = targetParts.slice(targetLayerIndex + 1);
|
|
973
|
+
const targetPathParts = normalizeToDirParts(targetAfterLayer);
|
|
974
|
+
const targetSegment = findTargetSegmentInSameSlice(
|
|
975
|
+
targetPathParts,
|
|
976
|
+
currentInfo.sliceParts,
|
|
977
|
+
currentInfo.segment
|
|
978
|
+
);
|
|
979
|
+
if (!targetSegment)
|
|
980
|
+
return NOT_CROSS_SEGMENT;
|
|
981
|
+
return {
|
|
982
|
+
isCrossSegmentReexport: true,
|
|
983
|
+
currentSegment: currentInfo.segment,
|
|
984
|
+
targetSegment
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// src/rules/no-cross-segment-reexport/model/validate-and-report.ts
|
|
989
|
+
function validateAndReport3(node, context, optionsWithDefault, config) {
|
|
990
|
+
if (!hasPath(node))
|
|
991
|
+
return;
|
|
992
|
+
const isIgnored2 = isIgnoredTarget(node, optionsWithDefault) || isIgnoredCurrentFile(context, optionsWithDefault);
|
|
993
|
+
if (isIgnored2)
|
|
994
|
+
return;
|
|
995
|
+
const {
|
|
996
|
+
normalizedCurrentFilePath,
|
|
997
|
+
absoluteTargetPath
|
|
998
|
+
} = extractPaths(node, context);
|
|
999
|
+
const result = isCrossSegmentReexport(
|
|
1000
|
+
normalizedCurrentFilePath,
|
|
1001
|
+
absoluteTargetPath,
|
|
1002
|
+
config
|
|
1003
|
+
);
|
|
1004
|
+
if (!result.isCrossSegmentReexport)
|
|
1005
|
+
return;
|
|
1006
|
+
reportCrossSegmentReexport(
|
|
1007
|
+
context,
|
|
1008
|
+
node,
|
|
1009
|
+
result.currentSegment,
|
|
1010
|
+
result.targetSegment
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/rules/no-cross-segment-reexport/index.ts
|
|
1015
|
+
var no_cross_segment_reexport_default = createEslintRule({
|
|
1016
|
+
name: "no-cross-segment-reexport",
|
|
1017
|
+
meta: {
|
|
1018
|
+
type: "problem",
|
|
1019
|
+
docs: {
|
|
1020
|
+
description: "Checks for cross-segment re-exports within the same slice"
|
|
1021
|
+
},
|
|
1022
|
+
hasSuggestions: true,
|
|
1023
|
+
messages: {
|
|
1024
|
+
[ERROR_MESSAGE_ID3.NO_CROSS_SEGMENT_REEXPORT]: 'Segment "{{ currentSegment }}" should not re-export from sibling segment "{{ targetSegment }}". Move the re-export to the slice public API.',
|
|
1025
|
+
[ERROR_MESSAGE_ID3.MOVE_TO_SLICE_PUBLIC_API_SUGGESTION]: 'Replace import path with slice public API ("{{ suggestedPath }}")'
|
|
1026
|
+
},
|
|
1027
|
+
schema: [
|
|
1028
|
+
{
|
|
1029
|
+
type: "object",
|
|
1030
|
+
properties: {
|
|
1031
|
+
ignoreImports: {
|
|
1032
|
+
type: "array",
|
|
1033
|
+
items: {
|
|
1034
|
+
type: "string"
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
ignoreFiles: {
|
|
1038
|
+
type: "array",
|
|
1039
|
+
items: {
|
|
1040
|
+
type: "string"
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
]
|
|
1046
|
+
},
|
|
1047
|
+
defaultOptions: [
|
|
1048
|
+
{
|
|
1049
|
+
ignoreImports: [],
|
|
1050
|
+
ignoreFiles: []
|
|
1051
|
+
}
|
|
1052
|
+
],
|
|
1053
|
+
create(context, optionsWithDefault) {
|
|
1054
|
+
const layersConfig = extractLayersConfig(context);
|
|
1055
|
+
return {
|
|
1056
|
+
ExportAllDeclaration(node) {
|
|
1057
|
+
validateAndReport3(node, context, optionsWithDefault, layersConfig);
|
|
1058
|
+
},
|
|
1059
|
+
ExportNamedDeclaration(node) {
|
|
1060
|
+
validateAndReport3(node, context, optionsWithDefault, layersConfig);
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
|
|
843
1066
|
// src/rules/public-api/config.ts
|
|
844
1067
|
var MESSAGE_ID = {
|
|
845
1068
|
SHOULD_BE_FROM_PUBLIC_API: "should-be-from-public-api",
|
|
@@ -963,7 +1186,7 @@ function shouldBeFromPublicApi(node, context, optionsWithDefault, layersConfig)
|
|
|
963
1186
|
}
|
|
964
1187
|
|
|
965
1188
|
// src/rules/public-api/model/validate-and-report.ts
|
|
966
|
-
function
|
|
1189
|
+
function validateAndReport4(node, context, optionsWithDefault, layersConfig) {
|
|
967
1190
|
if (!hasPath(node)) {
|
|
968
1191
|
return;
|
|
969
1192
|
}
|
|
@@ -1053,16 +1276,16 @@ var public_api_default = createEslintRule({
|
|
|
1053
1276
|
const layersConfig = extractLayersConfig(context);
|
|
1054
1277
|
return {
|
|
1055
1278
|
ImportDeclaration(node) {
|
|
1056
|
-
|
|
1279
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1057
1280
|
},
|
|
1058
1281
|
ImportExpression(node) {
|
|
1059
|
-
|
|
1282
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1060
1283
|
},
|
|
1061
1284
|
ExportAllDeclaration(node) {
|
|
1062
|
-
|
|
1285
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1063
1286
|
},
|
|
1064
1287
|
ExportNamedDeclaration(node) {
|
|
1065
|
-
|
|
1288
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1066
1289
|
},
|
|
1067
1290
|
Program(node) {
|
|
1068
1291
|
validateAndReportProgram(node, context, optionsWithDefault);
|
|
@@ -1076,6 +1299,7 @@ var rules = {
|
|
|
1076
1299
|
"absolute-relative": absolute_relative_default,
|
|
1077
1300
|
"import-order": _eslintpluginimportx2.default.rules.order,
|
|
1078
1301
|
"layers-slices": layers_slices_default,
|
|
1302
|
+
"no-cross-segment-reexport": no_cross_segment_reexport_default,
|
|
1079
1303
|
"public-api": public_api_default
|
|
1080
1304
|
};
|
|
1081
1305
|
var rules_default = rules;
|
|
@@ -1159,10 +1383,11 @@ function createPlugin(options = {}) {
|
|
|
1159
1383
|
sortImports = "recommended",
|
|
1160
1384
|
absoluteRelative,
|
|
1161
1385
|
layersSlices,
|
|
1162
|
-
publicApi
|
|
1386
|
+
publicApi,
|
|
1387
|
+
noCrossSegmentReexport
|
|
1163
1388
|
} = options;
|
|
1164
1389
|
const normalizedLayers = normalizeLayersConfig(layers2);
|
|
1165
|
-
const rules2 = defineRules({ severity, absoluteRelative, layersSlices, publicApi, sortImports }, normalizedLayers);
|
|
1390
|
+
const rules2 = defineRules({ severity, absoluteRelative, layersSlices, publicApi, noCrossSegmentReexport, sortImports }, normalizedLayers);
|
|
1166
1391
|
return {
|
|
1167
1392
|
name: PLUGIN_NAME,
|
|
1168
1393
|
plugins: {
|
|
@@ -1182,6 +1407,7 @@ function defineRules(options, layersConfig) {
|
|
|
1182
1407
|
absoluteRelative = {},
|
|
1183
1408
|
layersSlices = {},
|
|
1184
1409
|
publicApi = {},
|
|
1410
|
+
noCrossSegmentReexport = {},
|
|
1185
1411
|
sortImports = "recommended"
|
|
1186
1412
|
} = options;
|
|
1187
1413
|
const createRuleEntry = (ruleOptions) => {
|
|
@@ -1194,7 +1420,8 @@ function defineRules(options, layersConfig) {
|
|
|
1194
1420
|
const rules2 = {
|
|
1195
1421
|
[RULE_NAMES.LAYERS_SLICES]: createRuleEntry(layersSlices),
|
|
1196
1422
|
[RULE_NAMES.ABSOLUTE_RELATIVE]: createRuleEntry(absoluteRelative),
|
|
1197
|
-
[RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi)
|
|
1423
|
+
[RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi),
|
|
1424
|
+
[RULE_NAMES.NO_CROSS_SEGMENT_REEXPORT]: createRuleEntry(noCrossSegmentReexport)
|
|
1198
1425
|
};
|
|
1199
1426
|
if (sortImports) {
|
|
1200
1427
|
const importOrderConfigs = createImportOrderRuleConfigs(layersConfig);
|
package/dist/index.d.cts
CHANGED
|
@@ -12,6 +12,7 @@ declare const RULE_NAMES: {
|
|
|
12
12
|
readonly ABSOLUTE_RELATIVE: "@conarti/feature-sliced/absolute-relative";
|
|
13
13
|
readonly PUBLIC_API: "@conarti/feature-sliced/public-api";
|
|
14
14
|
readonly IMPORT_ORDER: "@conarti/feature-sliced/import-order";
|
|
15
|
+
readonly NO_CROSS_SEGMENT_REEXPORT: "@conarti/feature-sliced/no-cross-segment-reexport";
|
|
15
16
|
};
|
|
16
17
|
type Layers = ReadonlyArray<'shared' | 'entities' | 'features' | 'widgets' | 'pages' | 'processes' | 'app'>;
|
|
17
18
|
type Layer = Layers[number];
|
|
@@ -62,9 +63,9 @@ declare const VALIDATION_LEVEL: {
|
|
|
62
63
|
readonly SEGMENTS: "segments";
|
|
63
64
|
readonly SLICES: "slices";
|
|
64
65
|
};
|
|
65
|
-
type MessageIds$
|
|
66
|
+
type MessageIds$3 = typeof MESSAGE_ID[keyof typeof MESSAGE_ID];
|
|
66
67
|
type ValidationLevel = typeof VALIDATION_LEVEL[keyof typeof VALIDATION_LEVEL];
|
|
67
|
-
type Options$
|
|
68
|
+
type Options$3 = [
|
|
68
69
|
{
|
|
69
70
|
level: ValidationLevel;
|
|
70
71
|
ignoreImports: string[];
|
|
@@ -131,6 +132,21 @@ interface PublicApiOptions {
|
|
|
131
132
|
*/
|
|
132
133
|
ignoreFiles?: string[];
|
|
133
134
|
}
|
|
135
|
+
interface NoCrossSegmentReexportOptions {
|
|
136
|
+
/**
|
|
137
|
+
* Severity level for this rule
|
|
138
|
+
* @default uses global severity or 'error'
|
|
139
|
+
*/
|
|
140
|
+
severity?: Severity;
|
|
141
|
+
/**
|
|
142
|
+
* Ignore certain import paths (import foo from '<path-to-ignore>')
|
|
143
|
+
*/
|
|
144
|
+
ignoreImports?: string[];
|
|
145
|
+
/**
|
|
146
|
+
* Disable the rule in certain files
|
|
147
|
+
*/
|
|
148
|
+
ignoreFiles?: string[];
|
|
149
|
+
}
|
|
134
150
|
interface ESLintPluginFeatureSlicedOptions {
|
|
135
151
|
/**
|
|
136
152
|
* Global severity level for all rules.
|
|
@@ -155,10 +171,23 @@ interface ESLintPluginFeatureSlicedOptions {
|
|
|
155
171
|
absoluteRelative?: false | Partial<AbsoluteRelativeOptions>;
|
|
156
172
|
layersSlices?: false | Partial<LayersSlicesOptions>;
|
|
157
173
|
publicApi?: false | Partial<PublicApiOptions>;
|
|
174
|
+
noCrossSegmentReexport?: false | Partial<NoCrossSegmentReexportOptions>;
|
|
158
175
|
sortImports?: false | ImportOrderConfigName;
|
|
159
176
|
}
|
|
160
177
|
declare function createPlugin(options?: ESLintPluginFeatureSlicedOptions): TypedFlatConfigItem;
|
|
161
178
|
|
|
179
|
+
declare const ERROR_MESSAGE_ID$2: {
|
|
180
|
+
readonly NO_CROSS_SEGMENT_REEXPORT: "no-cross-segment-reexport";
|
|
181
|
+
readonly MOVE_TO_SLICE_PUBLIC_API_SUGGESTION: "move-to-slice-public-api-suggestion";
|
|
182
|
+
};
|
|
183
|
+
type MessageIds$2 = typeof ERROR_MESSAGE_ID$2[keyof typeof ERROR_MESSAGE_ID$2];
|
|
184
|
+
type Options$2 = [
|
|
185
|
+
{
|
|
186
|
+
ignoreImports: string[];
|
|
187
|
+
ignoreFiles: string[];
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
|
|
162
191
|
declare const ERROR_MESSAGE_ID$1: {
|
|
163
192
|
readonly CAN_NOT_IMPORT: "can-not-import";
|
|
164
193
|
readonly INVALID_CROSS_IMPORT: "invalid-cross-import";
|
|
@@ -193,7 +222,8 @@ declare const plugin: {
|
|
|
193
222
|
'absolute-relative': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds, Options, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
194
223
|
'import-order': _typescript_eslint_utils_ts_eslint.RuleModule<"error" | "order" | "noLineWithinGroup" | "noLineBetweenGroups" | "oneLineBetweenGroups" | "oneLineBetweenTheMultiLineImport" | "oneLineBetweenThisMultiLineImport" | "noLineBetweenSingleLineImport", [(eslint_plugin_import_x_rules_order.Options | undefined)?], eslint_plugin_import_x_utils.ImportXPluginDocs, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
195
224
|
'layers-slices': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$1, Options$1, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
196
|
-
'
|
|
225
|
+
'no-cross-segment-reexport': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$2, Options$2, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
226
|
+
'public-api': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$3, Options$3, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
197
227
|
};
|
|
198
228
|
};
|
|
199
229
|
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare const RULE_NAMES: {
|
|
|
12
12
|
readonly ABSOLUTE_RELATIVE: "@conarti/feature-sliced/absolute-relative";
|
|
13
13
|
readonly PUBLIC_API: "@conarti/feature-sliced/public-api";
|
|
14
14
|
readonly IMPORT_ORDER: "@conarti/feature-sliced/import-order";
|
|
15
|
+
readonly NO_CROSS_SEGMENT_REEXPORT: "@conarti/feature-sliced/no-cross-segment-reexport";
|
|
15
16
|
};
|
|
16
17
|
type Layers = ReadonlyArray<'shared' | 'entities' | 'features' | 'widgets' | 'pages' | 'processes' | 'app'>;
|
|
17
18
|
type Layer = Layers[number];
|
|
@@ -62,9 +63,9 @@ declare const VALIDATION_LEVEL: {
|
|
|
62
63
|
readonly SEGMENTS: "segments";
|
|
63
64
|
readonly SLICES: "slices";
|
|
64
65
|
};
|
|
65
|
-
type MessageIds$
|
|
66
|
+
type MessageIds$3 = typeof MESSAGE_ID[keyof typeof MESSAGE_ID];
|
|
66
67
|
type ValidationLevel = typeof VALIDATION_LEVEL[keyof typeof VALIDATION_LEVEL];
|
|
67
|
-
type Options$
|
|
68
|
+
type Options$3 = [
|
|
68
69
|
{
|
|
69
70
|
level: ValidationLevel;
|
|
70
71
|
ignoreImports: string[];
|
|
@@ -131,6 +132,21 @@ interface PublicApiOptions {
|
|
|
131
132
|
*/
|
|
132
133
|
ignoreFiles?: string[];
|
|
133
134
|
}
|
|
135
|
+
interface NoCrossSegmentReexportOptions {
|
|
136
|
+
/**
|
|
137
|
+
* Severity level for this rule
|
|
138
|
+
* @default uses global severity or 'error'
|
|
139
|
+
*/
|
|
140
|
+
severity?: Severity;
|
|
141
|
+
/**
|
|
142
|
+
* Ignore certain import paths (import foo from '<path-to-ignore>')
|
|
143
|
+
*/
|
|
144
|
+
ignoreImports?: string[];
|
|
145
|
+
/**
|
|
146
|
+
* Disable the rule in certain files
|
|
147
|
+
*/
|
|
148
|
+
ignoreFiles?: string[];
|
|
149
|
+
}
|
|
134
150
|
interface ESLintPluginFeatureSlicedOptions {
|
|
135
151
|
/**
|
|
136
152
|
* Global severity level for all rules.
|
|
@@ -155,10 +171,23 @@ interface ESLintPluginFeatureSlicedOptions {
|
|
|
155
171
|
absoluteRelative?: false | Partial<AbsoluteRelativeOptions>;
|
|
156
172
|
layersSlices?: false | Partial<LayersSlicesOptions>;
|
|
157
173
|
publicApi?: false | Partial<PublicApiOptions>;
|
|
174
|
+
noCrossSegmentReexport?: false | Partial<NoCrossSegmentReexportOptions>;
|
|
158
175
|
sortImports?: false | ImportOrderConfigName;
|
|
159
176
|
}
|
|
160
177
|
declare function createPlugin(options?: ESLintPluginFeatureSlicedOptions): TypedFlatConfigItem;
|
|
161
178
|
|
|
179
|
+
declare const ERROR_MESSAGE_ID$2: {
|
|
180
|
+
readonly NO_CROSS_SEGMENT_REEXPORT: "no-cross-segment-reexport";
|
|
181
|
+
readonly MOVE_TO_SLICE_PUBLIC_API_SUGGESTION: "move-to-slice-public-api-suggestion";
|
|
182
|
+
};
|
|
183
|
+
type MessageIds$2 = typeof ERROR_MESSAGE_ID$2[keyof typeof ERROR_MESSAGE_ID$2];
|
|
184
|
+
type Options$2 = [
|
|
185
|
+
{
|
|
186
|
+
ignoreImports: string[];
|
|
187
|
+
ignoreFiles: string[];
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
|
|
162
191
|
declare const ERROR_MESSAGE_ID$1: {
|
|
163
192
|
readonly CAN_NOT_IMPORT: "can-not-import";
|
|
164
193
|
readonly INVALID_CROSS_IMPORT: "invalid-cross-import";
|
|
@@ -193,7 +222,8 @@ declare const plugin: {
|
|
|
193
222
|
'absolute-relative': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds, Options, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
194
223
|
'import-order': _typescript_eslint_utils_ts_eslint.RuleModule<"error" | "order" | "noLineWithinGroup" | "noLineBetweenGroups" | "oneLineBetweenGroups" | "oneLineBetweenTheMultiLineImport" | "oneLineBetweenThisMultiLineImport" | "noLineBetweenSingleLineImport", [(eslint_plugin_import_x_rules_order.Options | undefined)?], eslint_plugin_import_x_utils.ImportXPluginDocs, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
195
224
|
'layers-slices': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$1, Options$1, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
196
|
-
'
|
|
225
|
+
'no-cross-segment-reexport': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$2, Options$2, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
226
|
+
'public-api': _typescript_eslint_utils_ts_eslint.RuleModule<MessageIds$3, Options$3, unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
197
227
|
};
|
|
198
228
|
};
|
|
199
229
|
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,8 @@ var RULE_NAMES = {
|
|
|
4
4
|
LAYERS_SLICES: `${PLUGIN_NAME}/layers-slices`,
|
|
5
5
|
ABSOLUTE_RELATIVE: `${PLUGIN_NAME}/absolute-relative`,
|
|
6
6
|
PUBLIC_API: `${PLUGIN_NAME}/public-api`,
|
|
7
|
-
IMPORT_ORDER: `${PLUGIN_NAME}/import-order
|
|
7
|
+
IMPORT_ORDER: `${PLUGIN_NAME}/import-order`,
|
|
8
|
+
NO_CROSS_SEGMENT_REEXPORT: `${PLUGIN_NAME}/no-cross-segment-reexport`
|
|
8
9
|
};
|
|
9
10
|
var layers = [
|
|
10
11
|
"shared",
|
|
@@ -79,7 +80,7 @@ function canLayerContainSlices(layer, config) {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
// package.json
|
|
82
|
-
var version = "2.0.0-rc.
|
|
83
|
+
var version = "2.0.0-rc.7";
|
|
83
84
|
|
|
84
85
|
// src/rules/index.ts
|
|
85
86
|
import pluginImport from "eslint-plugin-import-x";
|
|
@@ -840,6 +841,228 @@ var layers_slices_default = createEslintRule({
|
|
|
840
841
|
}
|
|
841
842
|
});
|
|
842
843
|
|
|
844
|
+
// src/rules/no-cross-segment-reexport/config.ts
|
|
845
|
+
var ERROR_MESSAGE_ID3 = {
|
|
846
|
+
NO_CROSS_SEGMENT_REEXPORT: "no-cross-segment-reexport",
|
|
847
|
+
MOVE_TO_SLICE_PUBLIC_API_SUGGESTION: "move-to-slice-public-api-suggestion"
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// src/rules/no-cross-segment-reexport/model/errors.ts
|
|
851
|
+
function buildSlicePublicApiPath(sourcePath, targetSegment) {
|
|
852
|
+
const parts = sourcePath.split("/");
|
|
853
|
+
const segmentIndex = parts.findIndex((part) => part === targetSegment);
|
|
854
|
+
if (segmentIndex !== -1) {
|
|
855
|
+
return parts.slice(0, segmentIndex).join("/");
|
|
856
|
+
}
|
|
857
|
+
return parts.slice(0, -1).join("/") || "..";
|
|
858
|
+
}
|
|
859
|
+
function reportCrossSegmentReexport(context, node, currentSegment, targetSegment) {
|
|
860
|
+
const sourcePath = node.source.value;
|
|
861
|
+
const suggestedPath = buildSlicePublicApiPath(sourcePath, targetSegment);
|
|
862
|
+
context.report({
|
|
863
|
+
node: node.source,
|
|
864
|
+
messageId: ERROR_MESSAGE_ID3.NO_CROSS_SEGMENT_REEXPORT,
|
|
865
|
+
data: {
|
|
866
|
+
currentSegment,
|
|
867
|
+
targetSegment
|
|
868
|
+
},
|
|
869
|
+
suggest: [
|
|
870
|
+
{
|
|
871
|
+
messageId: ERROR_MESSAGE_ID3.MOVE_TO_SLICE_PUBLIC_API_SUGGESTION,
|
|
872
|
+
data: {
|
|
873
|
+
suggestedPath
|
|
874
|
+
},
|
|
875
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
876
|
+
getSourceRangeWithoutQuotes(node.source.range),
|
|
877
|
+
suggestedPath
|
|
878
|
+
)
|
|
879
|
+
}
|
|
880
|
+
]
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/rules/no-cross-segment-reexport/model/is-cross-segment-reexport.ts
|
|
885
|
+
var NOT_CROSS_SEGMENT = {
|
|
886
|
+
isCrossSegmentReexport: false,
|
|
887
|
+
currentSegment: null,
|
|
888
|
+
targetSegment: null
|
|
889
|
+
};
|
|
890
|
+
var FILE_EXT_REGEXP = /\..+$/;
|
|
891
|
+
var KNOWN_SEGMENTS = segments.map((s) => s.toLowerCase());
|
|
892
|
+
function splitPathParts(path3) {
|
|
893
|
+
return path3.split("/").filter(Boolean);
|
|
894
|
+
}
|
|
895
|
+
function normalizeToDirParts(parts) {
|
|
896
|
+
const INDEX_FILE_REGEXP = /^index\..+$/;
|
|
897
|
+
return parts.reduce((acc, part) => {
|
|
898
|
+
if (INDEX_FILE_REGEXP.test(part))
|
|
899
|
+
return acc;
|
|
900
|
+
if (FILE_EXT_REGEXP.test(part)) {
|
|
901
|
+
acc.push(part.replace(FILE_EXT_REGEXP, ""));
|
|
902
|
+
return acc;
|
|
903
|
+
}
|
|
904
|
+
acc.push(part);
|
|
905
|
+
return acc;
|
|
906
|
+
}, []);
|
|
907
|
+
}
|
|
908
|
+
function findLayerIndex(parts, layersWithSlices2) {
|
|
909
|
+
return parts.findIndex(
|
|
910
|
+
(part) => layersWithSlices2.includes(part.toLowerCase())
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function extractSegmentAndSlice(pathParts) {
|
|
914
|
+
if (pathParts.length < 2)
|
|
915
|
+
return null;
|
|
916
|
+
const knownSegmentIndex = pathParts.findIndex(
|
|
917
|
+
(part) => KNOWN_SEGMENTS.includes(part.toLowerCase())
|
|
918
|
+
);
|
|
919
|
+
let segmentIndex;
|
|
920
|
+
if (knownSegmentIndex > 0) {
|
|
921
|
+
segmentIndex = knownSegmentIndex;
|
|
922
|
+
} else if (knownSegmentIndex === 0) {
|
|
923
|
+
return null;
|
|
924
|
+
} else {
|
|
925
|
+
segmentIndex = pathParts.length - 1;
|
|
926
|
+
if (segmentIndex < 1)
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
const segment = pathParts[segmentIndex];
|
|
930
|
+
const sliceParts = pathParts.slice(0, segmentIndex);
|
|
931
|
+
if (sliceParts.length === 0)
|
|
932
|
+
return null;
|
|
933
|
+
return { segment, sliceParts };
|
|
934
|
+
}
|
|
935
|
+
function findTargetSegmentInSameSlice(targetPathParts, currentSliceParts, currentSegment) {
|
|
936
|
+
if (targetPathParts.length === 0)
|
|
937
|
+
return null;
|
|
938
|
+
if (currentSliceParts.length > targetPathParts.length)
|
|
939
|
+
return null;
|
|
940
|
+
const targetHasSameSlice = currentSliceParts.every(
|
|
941
|
+
(part, i) => part.toLowerCase() === targetPathParts[i]?.toLowerCase()
|
|
942
|
+
);
|
|
943
|
+
if (!targetHasSameSlice)
|
|
944
|
+
return null;
|
|
945
|
+
const targetSegmentCandidate = targetPathParts[currentSliceParts.length];
|
|
946
|
+
if (!targetSegmentCandidate)
|
|
947
|
+
return null;
|
|
948
|
+
if (targetSegmentCandidate.toLowerCase() !== currentSegment.toLowerCase()) {
|
|
949
|
+
return targetSegmentCandidate;
|
|
950
|
+
}
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
function isCrossSegmentReexport(normalizedCurrentFilePath, absoluteTargetPath, config) {
|
|
954
|
+
const layersConfig = config ?? normalizeLayersConfig();
|
|
955
|
+
const layersWithSlices2 = getLayersWithSlices(layersConfig).map((l) => l.toLowerCase());
|
|
956
|
+
const currentParts = splitPathParts(normalizedCurrentFilePath);
|
|
957
|
+
const targetParts = splitPathParts(absoluteTargetPath);
|
|
958
|
+
const currentLayerIndex = findLayerIndex(currentParts, layersWithSlices2);
|
|
959
|
+
if (currentLayerIndex === -1)
|
|
960
|
+
return NOT_CROSS_SEGMENT;
|
|
961
|
+
const currentAfterLayer = currentParts.slice(currentLayerIndex + 1);
|
|
962
|
+
const currentPathParts = normalizeToDirParts(currentAfterLayer);
|
|
963
|
+
const currentInfo = extractSegmentAndSlice(currentPathParts);
|
|
964
|
+
if (!currentInfo)
|
|
965
|
+
return NOT_CROSS_SEGMENT;
|
|
966
|
+
const targetLayerIndex = findLayerIndex(targetParts, layersWithSlices2);
|
|
967
|
+
if (targetLayerIndex === -1)
|
|
968
|
+
return NOT_CROSS_SEGMENT;
|
|
969
|
+
if (currentParts[currentLayerIndex].toLowerCase() !== targetParts[targetLayerIndex].toLowerCase()) {
|
|
970
|
+
return NOT_CROSS_SEGMENT;
|
|
971
|
+
}
|
|
972
|
+
const targetAfterLayer = targetParts.slice(targetLayerIndex + 1);
|
|
973
|
+
const targetPathParts = normalizeToDirParts(targetAfterLayer);
|
|
974
|
+
const targetSegment = findTargetSegmentInSameSlice(
|
|
975
|
+
targetPathParts,
|
|
976
|
+
currentInfo.sliceParts,
|
|
977
|
+
currentInfo.segment
|
|
978
|
+
);
|
|
979
|
+
if (!targetSegment)
|
|
980
|
+
return NOT_CROSS_SEGMENT;
|
|
981
|
+
return {
|
|
982
|
+
isCrossSegmentReexport: true,
|
|
983
|
+
currentSegment: currentInfo.segment,
|
|
984
|
+
targetSegment
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// src/rules/no-cross-segment-reexport/model/validate-and-report.ts
|
|
989
|
+
function validateAndReport3(node, context, optionsWithDefault, config) {
|
|
990
|
+
if (!hasPath(node))
|
|
991
|
+
return;
|
|
992
|
+
const isIgnored2 = isIgnoredTarget(node, optionsWithDefault) || isIgnoredCurrentFile(context, optionsWithDefault);
|
|
993
|
+
if (isIgnored2)
|
|
994
|
+
return;
|
|
995
|
+
const {
|
|
996
|
+
normalizedCurrentFilePath,
|
|
997
|
+
absoluteTargetPath
|
|
998
|
+
} = extractPaths(node, context);
|
|
999
|
+
const result = isCrossSegmentReexport(
|
|
1000
|
+
normalizedCurrentFilePath,
|
|
1001
|
+
absoluteTargetPath,
|
|
1002
|
+
config
|
|
1003
|
+
);
|
|
1004
|
+
if (!result.isCrossSegmentReexport)
|
|
1005
|
+
return;
|
|
1006
|
+
reportCrossSegmentReexport(
|
|
1007
|
+
context,
|
|
1008
|
+
node,
|
|
1009
|
+
result.currentSegment,
|
|
1010
|
+
result.targetSegment
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/rules/no-cross-segment-reexport/index.ts
|
|
1015
|
+
var no_cross_segment_reexport_default = createEslintRule({
|
|
1016
|
+
name: "no-cross-segment-reexport",
|
|
1017
|
+
meta: {
|
|
1018
|
+
type: "problem",
|
|
1019
|
+
docs: {
|
|
1020
|
+
description: "Checks for cross-segment re-exports within the same slice"
|
|
1021
|
+
},
|
|
1022
|
+
hasSuggestions: true,
|
|
1023
|
+
messages: {
|
|
1024
|
+
[ERROR_MESSAGE_ID3.NO_CROSS_SEGMENT_REEXPORT]: 'Segment "{{ currentSegment }}" should not re-export from sibling segment "{{ targetSegment }}". Move the re-export to the slice public API.',
|
|
1025
|
+
[ERROR_MESSAGE_ID3.MOVE_TO_SLICE_PUBLIC_API_SUGGESTION]: 'Replace import path with slice public API ("{{ suggestedPath }}")'
|
|
1026
|
+
},
|
|
1027
|
+
schema: [
|
|
1028
|
+
{
|
|
1029
|
+
type: "object",
|
|
1030
|
+
properties: {
|
|
1031
|
+
ignoreImports: {
|
|
1032
|
+
type: "array",
|
|
1033
|
+
items: {
|
|
1034
|
+
type: "string"
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
ignoreFiles: {
|
|
1038
|
+
type: "array",
|
|
1039
|
+
items: {
|
|
1040
|
+
type: "string"
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
]
|
|
1046
|
+
},
|
|
1047
|
+
defaultOptions: [
|
|
1048
|
+
{
|
|
1049
|
+
ignoreImports: [],
|
|
1050
|
+
ignoreFiles: []
|
|
1051
|
+
}
|
|
1052
|
+
],
|
|
1053
|
+
create(context, optionsWithDefault) {
|
|
1054
|
+
const layersConfig = extractLayersConfig(context);
|
|
1055
|
+
return {
|
|
1056
|
+
ExportAllDeclaration(node) {
|
|
1057
|
+
validateAndReport3(node, context, optionsWithDefault, layersConfig);
|
|
1058
|
+
},
|
|
1059
|
+
ExportNamedDeclaration(node) {
|
|
1060
|
+
validateAndReport3(node, context, optionsWithDefault, layersConfig);
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
|
|
843
1066
|
// src/rules/public-api/config.ts
|
|
844
1067
|
var MESSAGE_ID = {
|
|
845
1068
|
SHOULD_BE_FROM_PUBLIC_API: "should-be-from-public-api",
|
|
@@ -963,7 +1186,7 @@ function shouldBeFromPublicApi(node, context, optionsWithDefault, layersConfig)
|
|
|
963
1186
|
}
|
|
964
1187
|
|
|
965
1188
|
// src/rules/public-api/model/validate-and-report.ts
|
|
966
|
-
function
|
|
1189
|
+
function validateAndReport4(node, context, optionsWithDefault, layersConfig) {
|
|
967
1190
|
if (!hasPath(node)) {
|
|
968
1191
|
return;
|
|
969
1192
|
}
|
|
@@ -1053,16 +1276,16 @@ var public_api_default = createEslintRule({
|
|
|
1053
1276
|
const layersConfig = extractLayersConfig(context);
|
|
1054
1277
|
return {
|
|
1055
1278
|
ImportDeclaration(node) {
|
|
1056
|
-
|
|
1279
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1057
1280
|
},
|
|
1058
1281
|
ImportExpression(node) {
|
|
1059
|
-
|
|
1282
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1060
1283
|
},
|
|
1061
1284
|
ExportAllDeclaration(node) {
|
|
1062
|
-
|
|
1285
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1063
1286
|
},
|
|
1064
1287
|
ExportNamedDeclaration(node) {
|
|
1065
|
-
|
|
1288
|
+
validateAndReport4(node, context, optionsWithDefault, layersConfig);
|
|
1066
1289
|
},
|
|
1067
1290
|
Program(node) {
|
|
1068
1291
|
validateAndReportProgram(node, context, optionsWithDefault);
|
|
@@ -1076,6 +1299,7 @@ var rules = {
|
|
|
1076
1299
|
"absolute-relative": absolute_relative_default,
|
|
1077
1300
|
"import-order": pluginImport.rules.order,
|
|
1078
1301
|
"layers-slices": layers_slices_default,
|
|
1302
|
+
"no-cross-segment-reexport": no_cross_segment_reexport_default,
|
|
1079
1303
|
"public-api": public_api_default
|
|
1080
1304
|
};
|
|
1081
1305
|
var rules_default = rules;
|
|
@@ -1159,10 +1383,11 @@ function createPlugin(options = {}) {
|
|
|
1159
1383
|
sortImports = "recommended",
|
|
1160
1384
|
absoluteRelative,
|
|
1161
1385
|
layersSlices,
|
|
1162
|
-
publicApi
|
|
1386
|
+
publicApi,
|
|
1387
|
+
noCrossSegmentReexport
|
|
1163
1388
|
} = options;
|
|
1164
1389
|
const normalizedLayers = normalizeLayersConfig(layers2);
|
|
1165
|
-
const rules2 = defineRules({ severity, absoluteRelative, layersSlices, publicApi, sortImports }, normalizedLayers);
|
|
1390
|
+
const rules2 = defineRules({ severity, absoluteRelative, layersSlices, publicApi, noCrossSegmentReexport, sortImports }, normalizedLayers);
|
|
1166
1391
|
return {
|
|
1167
1392
|
name: PLUGIN_NAME,
|
|
1168
1393
|
plugins: {
|
|
@@ -1182,6 +1407,7 @@ function defineRules(options, layersConfig) {
|
|
|
1182
1407
|
absoluteRelative = {},
|
|
1183
1408
|
layersSlices = {},
|
|
1184
1409
|
publicApi = {},
|
|
1410
|
+
noCrossSegmentReexport = {},
|
|
1185
1411
|
sortImports = "recommended"
|
|
1186
1412
|
} = options;
|
|
1187
1413
|
const createRuleEntry = (ruleOptions) => {
|
|
@@ -1194,7 +1420,8 @@ function defineRules(options, layersConfig) {
|
|
|
1194
1420
|
const rules2 = {
|
|
1195
1421
|
[RULE_NAMES.LAYERS_SLICES]: createRuleEntry(layersSlices),
|
|
1196
1422
|
[RULE_NAMES.ABSOLUTE_RELATIVE]: createRuleEntry(absoluteRelative),
|
|
1197
|
-
[RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi)
|
|
1423
|
+
[RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi),
|
|
1424
|
+
[RULE_NAMES.NO_CROSS_SEGMENT_REEXPORT]: createRuleEntry(noCrossSegmentReexport)
|
|
1198
1425
|
};
|
|
1199
1426
|
if (sortImports) {
|
|
1200
1427
|
const importOrderConfigs = createImportOrderRuleConfigs(layersConfig);
|
package/package.json
CHANGED