@conarti/eslint-plugin-feature-sliced 2.0.0-rc.1 → 2.0.0-rc.3

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/README.md CHANGED
@@ -71,9 +71,7 @@ npm i eslint --save-dev
71
71
  Next, install `@conarti/eslint-plugin-feature-sliced`:
72
72
 
73
73
  ```sh
74
- npm install -D @conarti/eslint-plugin-feature-sliced
75
- # or by yarn
76
- yarn add -D @conarti/eslint-plugin-feature-sliced
74
+ npm i -D @conarti/eslint-plugin-feature-sliced
77
75
  ```
78
76
 
79
77
  Note: the plugin may conflict with other import sorting plugins installed in your project.
@@ -81,45 +79,49 @@ If you do not want to use this plugin's sorting, disable it. More about this bel
81
79
 
82
80
  ## Usage
83
81
 
84
- [//]: # (// TODO)
82
+ For simple use with loose settings, just call the function:
85
83
 
86
- Add `@conarti/feature-sliced/recommended` to extends section of your `.eslintrc` configuration file.
87
- It enables all rules and additional recommended configs of other eslint plugins, like `eslint-plugin-import`.
84
+ ```js
85
+ // eslint.config.js
86
+ import featureSliced from '@conarti/eslint-plugin-feature-sliced';
88
87
 
89
- ```json
90
- {
91
- "extends": [
92
- "plugin:@conarti/feature-sliced/recommended"
93
- ]
94
- }
88
+ export default [
89
+ featureSliced(),
90
+ ]
95
91
  ```
96
92
 
97
93
  ## Customisation
98
94
 
99
- If you want to use only plugin rules, add `@conarti/feature-sliced/rules` instead.
100
-
101
- ```json
102
- {
103
- "extends": [
104
- "plugin:@conarti/feature-sliced/rules"
105
- ]
106
- }
107
- ```
108
-
109
- If you only want to use certain rules, you can add them individually. To do this, you need to add `@conarti/feature-sliced` to the 'plugins'
110
- section of the configuration file and add the desired rules to the 'rules' section. Also now you don't need to use the 'extends' section like before
111
-
112
- ```json
113
- {
114
- "plugins": [
115
- "@conarti/feature-sliced"
116
- ],
117
- "rules": {
118
- "@conarti/feature-sliced/layers-slices": "error",
119
- "@conarti/feature-sliced/absolute-relative": "error",
120
- "@conarti/feature-sliced/public-api": "error"
121
- }
122
- }
95
+ You can also manage any rule and disable them:
96
+
97
+ ```js
98
+ import featureSliced from '@conarti/eslint-plugin-feature-sliced';
99
+
100
+ export default [
101
+ featureSliced({
102
+ /* Enables public api check in segments */
103
+ publicApi: { level: 'segments' },
104
+ /* Uses a different import sorter. You can disable it and use your own plugins and configurations */
105
+ sortImports: 'with-newlines',
106
+ /* This is how you can completely disable the rule */
107
+ absoluteRelative: false,
108
+ layersSlices: {
109
+ /* This is how you can disable the rule for imports in any files (ignore paths in code) */
110
+ ignorePatterns: [
111
+ /**
112
+ * Please note that the plugin reads the entire file path from the root of your system, not the project.
113
+ * That's why we added "**" to the beginning.
114
+ */
115
+ "**/src/components/**/*"
116
+ ],
117
+ /* This is how you can disable the rule for files or folders (ignore all paths in files or folders) */
118
+ ignoreInFilesPatterns: [
119
+ /* Do not check imports like "import foo from '@/app/some-module/foo'" */
120
+ "@/app/some-module/*",
121
+ ],
122
+ },
123
+ }),
124
+ ]
123
125
  ```
124
126
 
125
127
  ## Rules
package/dist/index.cjs CHANGED
@@ -28,17 +28,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- default: () => src_default
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ default: () => index_default
34
34
  });
35
- module.exports = __toCommonJS(src_exports);
36
-
37
- // src/create-plugin.ts
38
- var import_eslint_flat_config_utils = require("eslint-flat-config-utils");
35
+ module.exports = __toCommonJS(index_exports);
39
36
 
40
37
  // src/config.ts
41
38
  var PLUGIN_NAME = "@conarti/feature-sliced";
39
+ var RULE_NAMES = {
40
+ LAYERS_SLICES: `${PLUGIN_NAME}/layers-slices`,
41
+ ABSOLUTE_RELATIVE: `${PLUGIN_NAME}/absolute-relative`,
42
+ PUBLIC_API: `${PLUGIN_NAME}/public-api`,
43
+ IMPORT_ORDER: `${PLUGIN_NAME}/import-order`
44
+ };
42
45
  var layers = [
43
46
  "shared",
44
47
  "entities",
@@ -63,135 +66,11 @@ var segments = [
63
66
  ];
64
67
  var pathSeparator = "/";
65
68
 
66
- // src/configs/import-order/shared.ts
67
- var import_eslint_plugin_import_x = __toESM(require("eslint-plugin-import-x"), 1);
68
- var plugins = {
69
- import: import_eslint_plugin_import_x.default
70
- };
71
- var LAYERS_REVERSED = [...layers].reverse();
72
-
73
- // src/configs/import-order/recommended.ts
74
- var recommended = {
75
- name: "@conarti/sort-imports/recommended",
76
- plugins,
77
- rules: {
78
- "import/order": [
79
- 2,
80
- {
81
- "alphabetize": {
82
- order: "asc",
83
- caseInsensitive: true
84
- },
85
- "newlines-between": "never",
86
- "pathGroups": LAYERS_REVERSED.map(
87
- (layer) => ({
88
- pattern: `**/?(*)${layer}{,/**}`,
89
- group: "internal",
90
- position: "after"
91
- })
92
- ),
93
- "distinctGroup": false,
94
- "pathGroupsExcludedImportTypes": ["builtin"],
95
- "groups": ["builtin", "external", "internal", "parent", "sibling", "index"]
96
- }
97
- ]
98
- }
99
- };
100
-
101
- // src/configs/import-order/with-newlines.ts
102
- var withNewlines = {
103
- name: "@conarti/sort-imports/with-newlines",
104
- plugins,
105
- rules: {
106
- "import/order": [
107
- 2,
108
- {
109
- "alphabetize": {
110
- order: "asc",
111
- caseInsensitive: true
112
- },
113
- "newlines-between": "always",
114
- "pathGroups": LAYERS_REVERSED.map(
115
- (layer) => ({
116
- pattern: `**/?(*)${layer}{,/**}`,
117
- group: "internal",
118
- position: "after"
119
- })
120
- ),
121
- "distinctGroup": false,
122
- "pathGroupsExcludedImportTypes": ["builtin"],
123
- "groups": ["builtin", "external", "internal", "parent", "sibling", "index"]
124
- }
125
- ]
126
- }
127
- };
128
-
129
- // src/configs/import-order/with-newlines-and-type-group.ts
130
- var withNewlinesAndTypeGroup = {
131
- name: "@conarti/sort-imports/with-newlines-and-type-group",
132
- plugins,
133
- rules: {
134
- "import/order": [
135
- 2,
136
- {
137
- "alphabetize": {
138
- order: "asc",
139
- caseInsensitive: true
140
- },
141
- "newlines-between": "always",
142
- "pathGroups": LAYERS_REVERSED.map(
143
- (layer) => ({
144
- pattern: `**/?(*)${layer}{,/**}`,
145
- group: "internal",
146
- position: "after"
147
- })
148
- ),
149
- "distinctGroup": false,
150
- "pathGroupsExcludedImportTypes": ["builtin", "type"],
151
- "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
152
- }
153
- ]
154
- }
155
- };
156
-
157
- // src/configs/import-order/with-type-group.ts
158
- var withTypeGroup = {
159
- name: "@conarti/sort-imports/with-type-group",
160
- plugins,
161
- rules: {
162
- "import/order": [
163
- 2,
164
- {
165
- "alphabetize": {
166
- order: "asc",
167
- caseInsensitive: true
168
- },
169
- "newlines-between": "never",
170
- "pathGroups": LAYERS_REVERSED.map(
171
- (layer) => ({
172
- pattern: `**/?(*)${layer}{,/**}`,
173
- group: "internal",
174
- position: "after"
175
- })
176
- ),
177
- "distinctGroup": false,
178
- "pathGroupsExcludedImportTypes": ["builtin", "type"],
179
- "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
180
- }
181
- ]
182
- }
183
- };
184
-
185
- // src/configs/import-order/index.ts
186
- var importOrder = {
187
- recommended,
188
- "with-newlines": withNewlines,
189
- "with-type-group": withTypeGroup,
190
- "with-newlines-and-type-group": withNewlinesAndTypeGroup
191
- };
192
-
193
69
  // package.json
194
- var version = "2.0.0-rc.1";
70
+ var version = "2.0.0-rc.3";
71
+
72
+ // src/rules/index.ts
73
+ var import_eslint_plugin_import_x = __toESM(require("eslint-plugin-import-x"), 1);
195
74
 
196
75
  // src/lib/rule/create-rule.ts
197
76
  var import_eslint_utils = require("@typescript-eslint/utils/eslint-utils");
@@ -464,7 +343,7 @@ function compareFeatureSlicedParts(fsPartsToCompare) {
464
343
  } = fsPartsToCompare;
465
344
  const hasUnknownLayers = target.validatedFeatureSlicedParts.hasNotLayer || currentFile.validatedFeatureSlicedParts.hasNotLayer;
466
345
  const isSameLayer = target.validatedFeatureSlicedParts.hasLayer && currentFile.validatedFeatureSlicedParts.hasLayer && target.fsdParts.layer === currentFile.fsdParts.layer;
467
- const isSameSlice = target.validatedFeatureSlicedParts.hasSlice && currentFile.validatedFeatureSlicedParts.hasSlice && target.fsdParts.slice === currentFile.fsdParts.slice;
346
+ const isSameSlice = isSameLayer && target.validatedFeatureSlicedParts.hasSlice && currentFile.validatedFeatureSlicedParts.hasSlice && target.fsdParts.slice === currentFile.fsdParts.slice;
468
347
  const isSameSegment = target.fsdParts.segment === currentFile.fsdParts.segment;
469
348
  const isSameLayerWithoutSlices = isSameLayer && !target.validatedFeatureSlicedParts.canLayerContainSlices && !currentFile.validatedFeatureSlicedParts.canLayerContainSlices;
470
349
  return {
@@ -845,7 +724,8 @@ function extractValueToRemove(pathsInfo) {
845
724
  function convertToPublicApi(pathsInfo) {
846
725
  const { normalizedTargetPath } = pathsInfo;
847
726
  const valueToRemove = extractValueToRemove(pathsInfo);
848
- const publicApiPath = normalizedTargetPath.replace(`/${valueToRemove}`, "");
727
+ let publicApiPath = normalizedTargetPath.replace(`/${valueToRemove}`, "");
728
+ publicApiPath = publicApiPath.replace(/\.\w+$/, "");
849
729
  return [publicApiPath, valueToRemove];
850
730
  }
851
731
 
@@ -1019,6 +899,7 @@ var public_api_default = createEslintRule({
1019
899
  // src/rules/index.ts
1020
900
  var rules = {
1021
901
  "absolute-relative": absolute_relative_default,
902
+ "import-order": import_eslint_plugin_import_x.default.rules.order,
1022
903
  "layers-slices": layers_slices_default,
1023
904
  "public-api": public_api_default
1024
905
  };
@@ -1033,6 +914,57 @@ var plugin = {
1033
914
  rules: rules_default
1034
915
  };
1035
916
 
917
+ // src/rules/import-order/configs.ts
918
+ var LAYERS_REVERSED = [...layers].reverse();
919
+ var baseConfig = {
920
+ alphabetize: {
921
+ order: "asc",
922
+ caseInsensitive: true
923
+ },
924
+ pathGroups: LAYERS_REVERSED.map((layer) => ({
925
+ pattern: `**/?(*)${layer}{,/**}`,
926
+ group: "internal",
927
+ position: "after"
928
+ })),
929
+ distinctGroup: false,
930
+ pathGroupsExcludedImportTypes: ["builtin"],
931
+ groups: ["builtin", "external", "internal", "parent", "sibling", "index"]
932
+ };
933
+ var importOrderRuleConfigs = {
934
+ "recommended": [
935
+ "error",
936
+ {
937
+ ...baseConfig,
938
+ "newlines-between": "never"
939
+ }
940
+ ],
941
+ "with-newlines": [
942
+ "error",
943
+ {
944
+ ...baseConfig,
945
+ "newlines-between": "always"
946
+ }
947
+ ],
948
+ "with-type-group": [
949
+ "error",
950
+ {
951
+ ...baseConfig,
952
+ "newlines-between": "never",
953
+ "pathGroupsExcludedImportTypes": ["builtin", "type"],
954
+ "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
955
+ }
956
+ ],
957
+ "with-newlines-and-type-group": [
958
+ "error",
959
+ {
960
+ ...baseConfig,
961
+ "newlines-between": "always",
962
+ "pathGroupsExcludedImportTypes": ["builtin", "type"],
963
+ "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
964
+ }
965
+ ]
966
+ };
967
+
1036
968
  // src/create-plugin.ts
1037
969
  function createPlugin(options = {}) {
1038
970
  const {
@@ -1041,42 +973,33 @@ function createPlugin(options = {}) {
1041
973
  layersSlices,
1042
974
  publicApi
1043
975
  } = options;
1044
- const rules2 = defineRules({ absoluteRelative, layersSlices, publicApi });
1045
- const config = {
976
+ const rules2 = defineRules({ absoluteRelative, layersSlices, publicApi, sortImports });
977
+ return {
1046
978
  name: PLUGIN_NAME,
1047
979
  plugins: {
1048
980
  [PLUGIN_NAME]: plugin
1049
981
  },
1050
982
  rules: rules2
1051
983
  };
1052
- return enhanceWithImportOrder(config, sortImports);
1053
984
  }
1054
985
  function defineRules(options) {
1055
986
  const {
1056
987
  absoluteRelative = {},
1057
988
  layersSlices = {},
1058
- publicApi = {}
989
+ publicApi = {},
990
+ sortImports = "recommended"
1059
991
  } = options;
1060
- const createRuleName = (rule) => `${PLUGIN_NAME}/${rule}`;
1061
992
  const createRuleEntry = (ruleOptions) => ruleOptions ? ["error", ruleOptions] : ["off"];
1062
993
  const rules2 = {
1063
- [createRuleName("layers-slices")]: createRuleEntry(layersSlices),
1064
- [createRuleName("absolute-relative")]: createRuleEntry(absoluteRelative),
1065
- [createRuleName("public-api")]: createRuleEntry(publicApi)
994
+ [RULE_NAMES.LAYERS_SLICES]: createRuleEntry(layersSlices),
995
+ [RULE_NAMES.ABSOLUTE_RELATIVE]: createRuleEntry(absoluteRelative),
996
+ [RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi)
1066
997
  };
1067
- return rules2;
1068
- }
1069
- function enhanceWithImportOrder(config, importOrderConfigName) {
1070
- if (!importOrderConfigName) {
1071
- return config;
998
+ if (sortImports) {
999
+ rules2[RULE_NAMES.IMPORT_ORDER] = importOrderRuleConfigs[sortImports];
1072
1000
  }
1073
- const importOrderConfig = importOrder[importOrderConfigName];
1074
- return (0, import_eslint_flat_config_utils.mergeConfigs)(
1075
- importOrderConfig,
1076
- config
1077
- // the last one is to set the configuration name as 'PLUGIN_NAME'
1078
- );
1001
+ return rules2;
1079
1002
  }
1080
1003
 
1081
1004
  // src/index.ts
1082
- var src_default = createPlugin;
1005
+ var index_default = createPlugin;
package/dist/index.d.cts CHANGED
@@ -50,12 +50,10 @@ interface PublicApiOptions {
50
50
  */
51
51
  ignoreInFilesPatterns: string[];
52
52
  }
53
- interface ESLintPluginFeatureSlicedRuleOptions {
53
+ interface ESLintPluginFeatureSlicedOptions {
54
54
  absoluteRelative?: false | AbsoluteRelativeOptions;
55
55
  layersSlices?: false | LayersSlicesOptions;
56
56
  publicApi?: false | PublicApiOptions;
57
- }
58
- interface ESLintPluginFeatureSlicedOptions extends ESLintPluginFeatureSlicedRuleOptions {
59
57
  sortImports?: false | ImportOrderConfigName;
60
58
  }
61
59
  declare function createPlugin(options?: ESLintPluginFeatureSlicedOptions): TypedFlatConfigItem;
package/dist/index.d.ts CHANGED
@@ -50,12 +50,10 @@ interface PublicApiOptions {
50
50
  */
51
51
  ignoreInFilesPatterns: string[];
52
52
  }
53
- interface ESLintPluginFeatureSlicedRuleOptions {
53
+ interface ESLintPluginFeatureSlicedOptions {
54
54
  absoluteRelative?: false | AbsoluteRelativeOptions;
55
55
  layersSlices?: false | LayersSlicesOptions;
56
56
  publicApi?: false | PublicApiOptions;
57
- }
58
- interface ESLintPluginFeatureSlicedOptions extends ESLintPluginFeatureSlicedRuleOptions {
59
57
  sortImports?: false | ImportOrderConfigName;
60
58
  }
61
59
  declare function createPlugin(options?: ESLintPluginFeatureSlicedOptions): TypedFlatConfigItem;
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
- // src/create-plugin.ts
2
- import { mergeConfigs } from "eslint-flat-config-utils";
3
-
4
1
  // src/config.ts
5
2
  var PLUGIN_NAME = "@conarti/feature-sliced";
3
+ var RULE_NAMES = {
4
+ LAYERS_SLICES: `${PLUGIN_NAME}/layers-slices`,
5
+ ABSOLUTE_RELATIVE: `${PLUGIN_NAME}/absolute-relative`,
6
+ PUBLIC_API: `${PLUGIN_NAME}/public-api`,
7
+ IMPORT_ORDER: `${PLUGIN_NAME}/import-order`
8
+ };
6
9
  var layers = [
7
10
  "shared",
8
11
  "entities",
@@ -27,135 +30,11 @@ var segments = [
27
30
  ];
28
31
  var pathSeparator = "/";
29
32
 
30
- // src/configs/import-order/shared.ts
31
- import pluginImport from "eslint-plugin-import-x";
32
- var plugins = {
33
- import: pluginImport
34
- };
35
- var LAYERS_REVERSED = [...layers].reverse();
36
-
37
- // src/configs/import-order/recommended.ts
38
- var recommended = {
39
- name: "@conarti/sort-imports/recommended",
40
- plugins,
41
- rules: {
42
- "import/order": [
43
- 2,
44
- {
45
- "alphabetize": {
46
- order: "asc",
47
- caseInsensitive: true
48
- },
49
- "newlines-between": "never",
50
- "pathGroups": LAYERS_REVERSED.map(
51
- (layer) => ({
52
- pattern: `**/?(*)${layer}{,/**}`,
53
- group: "internal",
54
- position: "after"
55
- })
56
- ),
57
- "distinctGroup": false,
58
- "pathGroupsExcludedImportTypes": ["builtin"],
59
- "groups": ["builtin", "external", "internal", "parent", "sibling", "index"]
60
- }
61
- ]
62
- }
63
- };
64
-
65
- // src/configs/import-order/with-newlines.ts
66
- var withNewlines = {
67
- name: "@conarti/sort-imports/with-newlines",
68
- plugins,
69
- rules: {
70
- "import/order": [
71
- 2,
72
- {
73
- "alphabetize": {
74
- order: "asc",
75
- caseInsensitive: true
76
- },
77
- "newlines-between": "always",
78
- "pathGroups": LAYERS_REVERSED.map(
79
- (layer) => ({
80
- pattern: `**/?(*)${layer}{,/**}`,
81
- group: "internal",
82
- position: "after"
83
- })
84
- ),
85
- "distinctGroup": false,
86
- "pathGroupsExcludedImportTypes": ["builtin"],
87
- "groups": ["builtin", "external", "internal", "parent", "sibling", "index"]
88
- }
89
- ]
90
- }
91
- };
92
-
93
- // src/configs/import-order/with-newlines-and-type-group.ts
94
- var withNewlinesAndTypeGroup = {
95
- name: "@conarti/sort-imports/with-newlines-and-type-group",
96
- plugins,
97
- rules: {
98
- "import/order": [
99
- 2,
100
- {
101
- "alphabetize": {
102
- order: "asc",
103
- caseInsensitive: true
104
- },
105
- "newlines-between": "always",
106
- "pathGroups": LAYERS_REVERSED.map(
107
- (layer) => ({
108
- pattern: `**/?(*)${layer}{,/**}`,
109
- group: "internal",
110
- position: "after"
111
- })
112
- ),
113
- "distinctGroup": false,
114
- "pathGroupsExcludedImportTypes": ["builtin", "type"],
115
- "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
116
- }
117
- ]
118
- }
119
- };
120
-
121
- // src/configs/import-order/with-type-group.ts
122
- var withTypeGroup = {
123
- name: "@conarti/sort-imports/with-type-group",
124
- plugins,
125
- rules: {
126
- "import/order": [
127
- 2,
128
- {
129
- "alphabetize": {
130
- order: "asc",
131
- caseInsensitive: true
132
- },
133
- "newlines-between": "never",
134
- "pathGroups": LAYERS_REVERSED.map(
135
- (layer) => ({
136
- pattern: `**/?(*)${layer}{,/**}`,
137
- group: "internal",
138
- position: "after"
139
- })
140
- ),
141
- "distinctGroup": false,
142
- "pathGroupsExcludedImportTypes": ["builtin", "type"],
143
- "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
144
- }
145
- ]
146
- }
147
- };
148
-
149
- // src/configs/import-order/index.ts
150
- var importOrder = {
151
- recommended,
152
- "with-newlines": withNewlines,
153
- "with-type-group": withTypeGroup,
154
- "with-newlines-and-type-group": withNewlinesAndTypeGroup
155
- };
156
-
157
33
  // package.json
158
- var version = "2.0.0-rc.1";
34
+ var version = "2.0.0-rc.3";
35
+
36
+ // src/rules/index.ts
37
+ import pluginImport from "eslint-plugin-import-x";
159
38
 
160
39
  // src/lib/rule/create-rule.ts
161
40
  import { RuleCreator } from "@typescript-eslint/utils/eslint-utils";
@@ -170,10 +49,10 @@ function isPathRelative(path3) {
170
49
  }
171
50
 
172
51
  // src/lib/path/join-path.ts
173
- import path2 from "node:path";
52
+ import path2 from "path";
174
53
 
175
54
  // src/lib/path/normalize-path.ts
176
- import path from "node:path";
55
+ import path from "path";
177
56
  function normalizePath(targetPath) {
178
57
  const winSepRegExp = /\\/g;
179
58
  const withNormalizedSeparators = path.normalize(targetPath).replace(winSepRegExp, pathSeparator);
@@ -431,7 +310,7 @@ function compareFeatureSlicedParts(fsPartsToCompare) {
431
310
  } = fsPartsToCompare;
432
311
  const hasUnknownLayers = target.validatedFeatureSlicedParts.hasNotLayer || currentFile.validatedFeatureSlicedParts.hasNotLayer;
433
312
  const isSameLayer = target.validatedFeatureSlicedParts.hasLayer && currentFile.validatedFeatureSlicedParts.hasLayer && target.fsdParts.layer === currentFile.fsdParts.layer;
434
- const isSameSlice = target.validatedFeatureSlicedParts.hasSlice && currentFile.validatedFeatureSlicedParts.hasSlice && target.fsdParts.slice === currentFile.fsdParts.slice;
313
+ const isSameSlice = isSameLayer && target.validatedFeatureSlicedParts.hasSlice && currentFile.validatedFeatureSlicedParts.hasSlice && target.fsdParts.slice === currentFile.fsdParts.slice;
435
314
  const isSameSegment = target.fsdParts.segment === currentFile.fsdParts.segment;
436
315
  const isSameLayerWithoutSlices = isSameLayer && !target.validatedFeatureSlicedParts.canLayerContainSlices && !currentFile.validatedFeatureSlicedParts.canLayerContainSlices;
437
316
  return {
@@ -819,7 +698,8 @@ function extractValueToRemove(pathsInfo) {
819
698
  function convertToPublicApi(pathsInfo) {
820
699
  const { normalizedTargetPath } = pathsInfo;
821
700
  const valueToRemove = extractValueToRemove(pathsInfo);
822
- const publicApiPath = normalizedTargetPath.replace(`/${valueToRemove}`, "");
701
+ let publicApiPath = normalizedTargetPath.replace(`/${valueToRemove}`, "");
702
+ publicApiPath = publicApiPath.replace(/\.\w+$/, "");
823
703
  return [publicApiPath, valueToRemove];
824
704
  }
825
705
 
@@ -993,6 +873,7 @@ var public_api_default = createEslintRule({
993
873
  // src/rules/index.ts
994
874
  var rules = {
995
875
  "absolute-relative": absolute_relative_default,
876
+ "import-order": pluginImport.rules.order,
996
877
  "layers-slices": layers_slices_default,
997
878
  "public-api": public_api_default
998
879
  };
@@ -1007,6 +888,57 @@ var plugin = {
1007
888
  rules: rules_default
1008
889
  };
1009
890
 
891
+ // src/rules/import-order/configs.ts
892
+ var LAYERS_REVERSED = [...layers].reverse();
893
+ var baseConfig = {
894
+ alphabetize: {
895
+ order: "asc",
896
+ caseInsensitive: true
897
+ },
898
+ pathGroups: LAYERS_REVERSED.map((layer) => ({
899
+ pattern: `**/?(*)${layer}{,/**}`,
900
+ group: "internal",
901
+ position: "after"
902
+ })),
903
+ distinctGroup: false,
904
+ pathGroupsExcludedImportTypes: ["builtin"],
905
+ groups: ["builtin", "external", "internal", "parent", "sibling", "index"]
906
+ };
907
+ var importOrderRuleConfigs = {
908
+ "recommended": [
909
+ "error",
910
+ {
911
+ ...baseConfig,
912
+ "newlines-between": "never"
913
+ }
914
+ ],
915
+ "with-newlines": [
916
+ "error",
917
+ {
918
+ ...baseConfig,
919
+ "newlines-between": "always"
920
+ }
921
+ ],
922
+ "with-type-group": [
923
+ "error",
924
+ {
925
+ ...baseConfig,
926
+ "newlines-between": "never",
927
+ "pathGroupsExcludedImportTypes": ["builtin", "type"],
928
+ "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
929
+ }
930
+ ],
931
+ "with-newlines-and-type-group": [
932
+ "error",
933
+ {
934
+ ...baseConfig,
935
+ "newlines-between": "always",
936
+ "pathGroupsExcludedImportTypes": ["builtin", "type"],
937
+ "groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
938
+ }
939
+ ]
940
+ };
941
+
1010
942
  // src/create-plugin.ts
1011
943
  function createPlugin(options = {}) {
1012
944
  const {
@@ -1015,45 +947,36 @@ function createPlugin(options = {}) {
1015
947
  layersSlices,
1016
948
  publicApi
1017
949
  } = options;
1018
- const rules2 = defineRules({ absoluteRelative, layersSlices, publicApi });
1019
- const config = {
950
+ const rules2 = defineRules({ absoluteRelative, layersSlices, publicApi, sortImports });
951
+ return {
1020
952
  name: PLUGIN_NAME,
1021
953
  plugins: {
1022
954
  [PLUGIN_NAME]: plugin
1023
955
  },
1024
956
  rules: rules2
1025
957
  };
1026
- return enhanceWithImportOrder(config, sortImports);
1027
958
  }
1028
959
  function defineRules(options) {
1029
960
  const {
1030
961
  absoluteRelative = {},
1031
962
  layersSlices = {},
1032
- publicApi = {}
963
+ publicApi = {},
964
+ sortImports = "recommended"
1033
965
  } = options;
1034
- const createRuleName = (rule) => `${PLUGIN_NAME}/${rule}`;
1035
966
  const createRuleEntry = (ruleOptions) => ruleOptions ? ["error", ruleOptions] : ["off"];
1036
967
  const rules2 = {
1037
- [createRuleName("layers-slices")]: createRuleEntry(layersSlices),
1038
- [createRuleName("absolute-relative")]: createRuleEntry(absoluteRelative),
1039
- [createRuleName("public-api")]: createRuleEntry(publicApi)
968
+ [RULE_NAMES.LAYERS_SLICES]: createRuleEntry(layersSlices),
969
+ [RULE_NAMES.ABSOLUTE_RELATIVE]: createRuleEntry(absoluteRelative),
970
+ [RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi)
1040
971
  };
1041
- return rules2;
1042
- }
1043
- function enhanceWithImportOrder(config, importOrderConfigName) {
1044
- if (!importOrderConfigName) {
1045
- return config;
972
+ if (sortImports) {
973
+ rules2[RULE_NAMES.IMPORT_ORDER] = importOrderRuleConfigs[sortImports];
1046
974
  }
1047
- const importOrderConfig = importOrder[importOrderConfigName];
1048
- return mergeConfigs(
1049
- importOrderConfig,
1050
- config
1051
- // the last one is to set the configuration name as 'PLUGIN_NAME'
1052
- );
975
+ return rules2;
1053
976
  }
1054
977
 
1055
978
  // src/index.ts
1056
- var src_default = createPlugin;
979
+ var index_default = createPlugin;
1057
980
  export {
1058
- src_default as default
981
+ index_default as default
1059
982
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@conarti/eslint-plugin-feature-sliced",
3
3
  "type": "module",
4
- "version": "2.0.0-rc.1",
4
+ "version": "2.0.0-rc.3",
5
5
  "description": "Feature-sliced design methodology plugin",
6
6
  "author": "Aleksandr Belous <abelous2009@gmail.com>",
7
7
  "license": "ISC",
@@ -36,7 +36,7 @@
36
36
  "stub": "tsup --format esm",
37
37
  "dev": "npx @eslint/config-inspector --config eslint.config.ts",
38
38
  "watch": "tsup --format esm,cjs --watch",
39
- "typecheck": "tsc --noEmit",
39
+ "type-check": "tsc --noEmit",
40
40
  "lint": "eslint .",
41
41
  "test": "vitest",
42
42
  "test:ui": "vitest --ui --api 9527",
@@ -56,9 +56,9 @@
56
56
  "eslint": ">=9"
57
57
  },
58
58
  "dependencies": {
59
- "@typescript-eslint/utils": "^8.8.0",
59
+ "@typescript-eslint/utils": "^8.45.0",
60
60
  "eslint-flat-config-utils": "^0.4.0",
61
- "eslint-plugin-import-x": "^4.3.1",
61
+ "eslint-plugin-import-x": "^4.16.1",
62
62
  "picomatch": "^2.3.1"
63
63
  },
64
64
  "devDependencies": {
@@ -67,7 +67,8 @@
67
67
  "@types/eslint": "^9.6.1",
68
68
  "@types/node": "^20.4.2",
69
69
  "@types/picomatch": "^2.3.0",
70
- "@typescript-eslint/parser": "^8.8.0",
70
+ "@typescript-eslint/parser": "^8.45.0",
71
+ "@typescript-eslint/rule-tester": "^8.45.0",
71
72
  "@vitest/coverage-v8": "^0.33.0",
72
73
  "@vitest/ui": "^0.33.0",
73
74
  "conventional-changelog-cli": "^2.2.2",
@@ -78,7 +79,7 @@
78
79
  "prompts": "^2.4.2",
79
80
  "rimraf": "^5.0.1",
80
81
  "semver": "^7.5.4",
81
- "tsup": "^8.3.0",
82
+ "tsup": "^8.5.0",
82
83
  "typescript": "^5.6.2",
83
84
  "vitepress": "^1.0.0-alpha.64",
84
85
  "vitest": "^0.33.0"