@conarti/eslint-plugin-feature-sliced 1.0.5 → 2.0.0-rc.2
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 +43 -38
- package/dist/index.cjs +1004 -0
- package/dist/index.d.cts +61 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +978 -21
- package/package.json +39 -40
- package/dist/config.js +0 -27
- package/dist/configs/import-order/index.js +0 -20
- package/dist/configs/import-order/recommended.js +0 -28
- package/dist/configs/import-order/with-newlines-and-type-group.js +0 -28
- package/dist/configs/import-order/with-newlines.js +0 -28
- package/dist/configs/import-order/with-type-group.js +0 -28
- package/dist/configs/recommended.js +0 -11
- package/dist/configs/rules.js +0 -11
- package/dist/lib/feature-sliced/extract-feature-sliced-parts.js +0 -18
- package/dist/lib/feature-sliced/extract-layer.js +0 -21
- package/dist/lib/feature-sliced/extract-paths-info.js +0 -59
- package/dist/lib/feature-sliced/extract-segment.js +0 -18
- package/dist/lib/feature-sliced/extract-slice.js +0 -10
- package/dist/lib/feature-sliced/index.js +0 -10
- package/dist/lib/feature-sliced/layers.js +0 -16
- package/dist/lib/feature-sliced/validate-extracted-feature-sliced-parts.js +0 -29
- package/dist/lib/path/convert-to-absolute.js +0 -18
- package/dist/lib/path/index.js +0 -9
- package/dist/lib/path/is-path-relative.js +0 -7
- package/dist/lib/path/join-path.js +0 -12
- package/dist/lib/path/normalize-path.js +0 -19
- package/dist/lib/rule/create-rule.js +0 -7
- package/dist/lib/rule/extract-current-file-path.js +0 -11
- package/dist/lib/rule/extract-cwd.js +0 -13
- package/dist/lib/rule/extract-node-path.js +0 -13
- package/dist/lib/rule/extract-paths.js +0 -21
- package/dist/lib/rule/extract-rule-options.js +0 -7
- package/dist/lib/rule/get-source-range-without-quotes.js +0 -7
- package/dist/lib/rule/has-path.js +0 -11
- package/dist/lib/rule/index.js +0 -27
- package/dist/lib/rule/is-ignored-current-file.js +0 -12
- package/dist/lib/rule/is-ignored-target.js +0 -12
- package/dist/lib/rule/is-ignored.js +0 -12
- package/dist/lib/rule/is-node-type.js +0 -16
- package/dist/lib/rule/models.js +0 -2
- package/dist/lib/shared/get-by-reg-exp.js +0 -12
- package/dist/lib/shared/index.js +0 -11
- package/dist/lib/shared/is-null.js +0 -7
- package/dist/lib/shared/is-object.js +0 -7
- package/dist/lib/shared/is-undefined.js +0 -7
- package/dist/rules/absolute-relative/config.js +0 -2
- package/dist/rules/absolute-relative/index.js +0 -51
- package/dist/rules/absolute-relative/model/errors.js +0 -17
- package/dist/rules/absolute-relative/model/index.js +0 -5
- package/dist/rules/absolute-relative/model/should-be-absolute.js +0 -16
- package/dist/rules/absolute-relative/model/should-be-relative.js +0 -21
- package/dist/rules/absolute-relative/model/validate-and-report.js +0 -24
- package/dist/rules/layers-slices/config.js +0 -2
- package/dist/rules/layers-slices/index.js +0 -55
- package/dist/rules/layers-slices/model/errors.js +0 -22
- package/dist/rules/layers-slices/model/index.js +0 -5
- package/dist/rules/layers-slices/model/is-not-suitable-for-validation.js +0 -17
- package/dist/rules/layers-slices/model/specifiers/extract-import-specifiers.js +0 -8
- package/dist/rules/layers-slices/model/specifiers/has-errors-at-all-specifiers.js +0 -9
- package/dist/rules/layers-slices/model/specifiers/index.js +0 -7
- package/dist/rules/layers-slices/model/specifiers/validate-specifiers.js +0 -8
- package/dist/rules/layers-slices/model/validate-and-report.js +0 -46
- package/dist/rules/layers-slices/model/validate-node/index.js +0 -16
- package/dist/rules/layers-slices/model/validate-node/valid-by-layer-order.js +0 -10
- package/dist/rules/layers-slices/model/validate-node/valid-by-type-import.js +0 -9
- package/dist/rules/public-api/config.js +0 -2
- package/dist/rules/public-api/index.js +0 -65
- package/dist/rules/public-api/model/convert-to-public-api.js +0 -24
- package/dist/rules/public-api/model/errors.js +0 -34
- package/dist/rules/public-api/model/index.js +0 -5
- package/dist/rules/public-api/model/is-index-file.js +0 -7
- package/dist/rules/public-api/model/is-layer-public-api.js +0 -23
- package/dist/rules/public-api/model/is-segments-public-api.js +0 -11
- package/dist/rules/public-api/model/is-slice-public-api.js +0 -7
- package/dist/rules/public-api/model/should-be-from-public-api.js +0 -21
- package/dist/rules/public-api/model/validate-and-report-program.js +0 -15
- package/dist/rules/public-api/model/validate-and-report.js +0 -18
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1004 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
default: () => src_default
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
|
|
37
|
+
// src/config.ts
|
|
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
|
+
};
|
|
45
|
+
var layers = [
|
|
46
|
+
"shared",
|
|
47
|
+
"entities",
|
|
48
|
+
"features",
|
|
49
|
+
"widgets",
|
|
50
|
+
"pages",
|
|
51
|
+
"processes",
|
|
52
|
+
"app"
|
|
53
|
+
];
|
|
54
|
+
var layersWithoutSlices = [
|
|
55
|
+
"shared",
|
|
56
|
+
"app"
|
|
57
|
+
];
|
|
58
|
+
var layersWithSlices = layers.filter((layer) => !layersWithoutSlices.includes(layer));
|
|
59
|
+
var segments = [
|
|
60
|
+
"ui",
|
|
61
|
+
"model",
|
|
62
|
+
"lib",
|
|
63
|
+
"api",
|
|
64
|
+
"config",
|
|
65
|
+
"assets"
|
|
66
|
+
];
|
|
67
|
+
var pathSeparator = "/";
|
|
68
|
+
|
|
69
|
+
// package.json
|
|
70
|
+
var version = "2.0.0-rc.1";
|
|
71
|
+
|
|
72
|
+
// src/rules/index.ts
|
|
73
|
+
var import_eslint_plugin_import_x = __toESM(require("eslint-plugin-import-x"), 1);
|
|
74
|
+
|
|
75
|
+
// src/lib/rule/create-rule.ts
|
|
76
|
+
var import_eslint_utils = require("@typescript-eslint/utils/eslint-utils");
|
|
77
|
+
var blobUrl = "https://github.com/conarti/eslint-plugin-feature-sliced/blob/master/src/rules";
|
|
78
|
+
var createEslintRule = (0, import_eslint_utils.RuleCreator)(
|
|
79
|
+
(ruleName) => `${blobUrl}/${ruleName}/index.test.ts`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// src/lib/path/is-path-relative.ts
|
|
83
|
+
function isPathRelative(path3) {
|
|
84
|
+
return path3.startsWith(".");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/lib/path/join-path.ts
|
|
88
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
89
|
+
|
|
90
|
+
// src/lib/path/normalize-path.ts
|
|
91
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
92
|
+
function normalizePath(targetPath) {
|
|
93
|
+
const winSepRegExp = /\\/g;
|
|
94
|
+
const withNormalizedSeparators = import_node_path.default.normalize(targetPath).replace(winSepRegExp, pathSeparator);
|
|
95
|
+
if (targetPath.startsWith("./")) {
|
|
96
|
+
return `./${withNormalizedSeparators}`;
|
|
97
|
+
}
|
|
98
|
+
return withNormalizedSeparators;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/lib/path/join-path.ts
|
|
102
|
+
function joinPath(from, to) {
|
|
103
|
+
return normalizePath(import_node_path2.default.join(normalizePath(from), normalizePath(to)));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/lib/path/convert-to-absolute.ts
|
|
107
|
+
function convertToAbsolute(base, target) {
|
|
108
|
+
if (target === "") {
|
|
109
|
+
return base;
|
|
110
|
+
}
|
|
111
|
+
if (base === "") {
|
|
112
|
+
return target;
|
|
113
|
+
}
|
|
114
|
+
if (!isPathRelative(target)) {
|
|
115
|
+
return target;
|
|
116
|
+
}
|
|
117
|
+
return joinPath(base, `../${target}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/lib/rule/extract-current-file-path.ts
|
|
121
|
+
function extractCurrentFilePath(context) {
|
|
122
|
+
const currentFilePath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
|
|
123
|
+
return normalizePath(currentFilePath);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/lib/shared/get-by-reg-exp.ts
|
|
127
|
+
function getByRegExp(target, regExp, fromEnd = false) {
|
|
128
|
+
const results = target.match(regExp) || [];
|
|
129
|
+
if (fromEnd) {
|
|
130
|
+
const lastResult = results[results.length - 1];
|
|
131
|
+
return lastResult || null;
|
|
132
|
+
}
|
|
133
|
+
return results[0] || null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/lib/shared/is-null.ts
|
|
137
|
+
function isNull(target) {
|
|
138
|
+
return target === null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/lib/shared/is-object.ts
|
|
142
|
+
function isObject(target) {
|
|
143
|
+
return (typeof target === "object" || typeof target === "function") && target !== null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/lib/shared/is-undefined.ts
|
|
147
|
+
function isUndefined(target) {
|
|
148
|
+
return target === void 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/lib/rule/extract-cwd.ts
|
|
152
|
+
function extractCwd(context) {
|
|
153
|
+
const cwd = context.getCwd?.();
|
|
154
|
+
if (isUndefined(cwd)) {
|
|
155
|
+
return void 0;
|
|
156
|
+
}
|
|
157
|
+
return normalizePath(cwd);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/lib/rule/extract-node-path.ts
|
|
161
|
+
function extractNodePath(node) {
|
|
162
|
+
const targetPath = node.source.value;
|
|
163
|
+
const normalizedTargetPath = normalizePath(targetPath);
|
|
164
|
+
return {
|
|
165
|
+
targetPath,
|
|
166
|
+
normalizedTargetPath
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/lib/rule/extract-paths.ts
|
|
171
|
+
function extractPaths(node, context) {
|
|
172
|
+
const normalizedCurrentFilePath = extractCurrentFilePath(context);
|
|
173
|
+
const {
|
|
174
|
+
targetPath,
|
|
175
|
+
normalizedTargetPath
|
|
176
|
+
} = extractNodePath(node);
|
|
177
|
+
const absoluteTargetPath = convertToAbsolute(normalizedCurrentFilePath, normalizedTargetPath);
|
|
178
|
+
const cwd = extractCwd(context);
|
|
179
|
+
return {
|
|
180
|
+
targetPath,
|
|
181
|
+
normalizedTargetPath,
|
|
182
|
+
normalizedCurrentFilePath,
|
|
183
|
+
absoluteTargetPath,
|
|
184
|
+
normalizedCwd: cwd
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/lib/rule/extract-rule-options.ts
|
|
189
|
+
function extractRuleOptions(optionsWithDefault) {
|
|
190
|
+
return optionsWithDefault[0];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/lib/rule/get-source-range-without-quotes.ts
|
|
194
|
+
function getSourceRangeWithoutQuotes([rangeStart, rangeEnd]) {
|
|
195
|
+
return [rangeStart + 1, rangeEnd - 1];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/lib/rule/has-path.ts
|
|
199
|
+
function hasPath(node) {
|
|
200
|
+
if (isObject(node) && "source" in node) {
|
|
201
|
+
return node.source !== null;
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// src/lib/rule/is-ignored.ts
|
|
207
|
+
var import_picomatch = __toESM(require("picomatch"), 1);
|
|
208
|
+
function isIgnored(path3, patterns) {
|
|
209
|
+
const match = (0, import_picomatch.default)(patterns);
|
|
210
|
+
return match(path3);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/lib/rule/is-ignored-current-file.ts
|
|
214
|
+
function isIgnoredCurrentFile(context, optionsWithDefault) {
|
|
215
|
+
const ruleOptions = extractRuleOptions(optionsWithDefault);
|
|
216
|
+
const normalizedCurrentFilePath = extractCurrentFilePath(context);
|
|
217
|
+
return isIgnored(normalizedCurrentFilePath, ruleOptions.ignoreInFilesPatterns);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/lib/rule/is-ignored-target.ts
|
|
221
|
+
function isIgnoredTarget(node, optionsWithDefault) {
|
|
222
|
+
const { targetPath } = extractNodePath(node);
|
|
223
|
+
const userDefinedRuleOptions = extractRuleOptions(optionsWithDefault);
|
|
224
|
+
return isIgnored(targetPath, userDefinedRuleOptions.ignorePatterns);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/lib/rule/is-node-type.ts
|
|
228
|
+
var import_utils = require("@typescript-eslint/utils");
|
|
229
|
+
function isNodeType(node) {
|
|
230
|
+
const isImport = import_utils.ASTUtils.isNodeOfTypes([import_utils.AST_NODE_TYPES.ImportSpecifier, import_utils.AST_NODE_TYPES.ImportDeclaration])(node);
|
|
231
|
+
const isExport = import_utils.ASTUtils.isNodeOfTypes([import_utils.AST_NODE_TYPES.ExportAllDeclaration, import_utils.AST_NODE_TYPES.ExportNamedDeclaration])(node);
|
|
232
|
+
if (isImport) {
|
|
233
|
+
return node.importKind === "type";
|
|
234
|
+
}
|
|
235
|
+
if (isExport) {
|
|
236
|
+
return node.exportKind === "type";
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/lib/feature-sliced/extract-layer.ts
|
|
242
|
+
function prepareToExtract(targetPath, cwd) {
|
|
243
|
+
const lowerCasedTargetPath = targetPath.toLowerCase();
|
|
244
|
+
if (cwd === void 0) {
|
|
245
|
+
return lowerCasedTargetPath;
|
|
246
|
+
}
|
|
247
|
+
const lowerCasedCwd = cwd.toLowerCase();
|
|
248
|
+
const pathWithoutCwd = lowerCasedTargetPath.replace(lowerCasedCwd, "");
|
|
249
|
+
return pathWithoutCwd;
|
|
250
|
+
}
|
|
251
|
+
function extractLayer(targetPath, cwd) {
|
|
252
|
+
const layersRegExpPattern = `(${layers.join("|")})(?![\\w\\.-])`;
|
|
253
|
+
const layersRegExp = new RegExp(layersRegExpPattern, "gi");
|
|
254
|
+
const pathForExtract = prepareToExtract(targetPath, cwd);
|
|
255
|
+
return getByRegExp(pathForExtract, layersRegExp);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/lib/feature-sliced/extract-segment.ts
|
|
259
|
+
var layersUnion = layersWithSlices.join("|");
|
|
260
|
+
var segmentsUnion = segments.join("|");
|
|
261
|
+
var fsdPartsRegExp = new RegExp(
|
|
262
|
+
`(?<=(?<layer>${layersUnion}))\\/(?<slice>([\\w-]*\\/)+?)(?<segment>(${segmentsUnion})(\\.\\w+)?)(\\/(?<segmentFiles>.*))?`
|
|
263
|
+
);
|
|
264
|
+
function extractSegment(targetPath) {
|
|
265
|
+
const fsdParts = targetPath.match(fsdPartsRegExp);
|
|
266
|
+
if (fsdParts === null) {
|
|
267
|
+
return [null, null];
|
|
268
|
+
}
|
|
269
|
+
const {
|
|
270
|
+
segment = null,
|
|
271
|
+
segmentFiles = null
|
|
272
|
+
} = fsdParts.groups || {};
|
|
273
|
+
const fileExtensionRegExp = /\.[^/.]+$/;
|
|
274
|
+
const segmentWithoutFileExtension = segment?.replace(fileExtensionRegExp, "") || null;
|
|
275
|
+
return [segmentWithoutFileExtension, segmentFiles];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/lib/feature-sliced/extract-slice.ts
|
|
279
|
+
function extractSlice(targetPath) {
|
|
280
|
+
const targetPathWithoutCurrentFileName = targetPath.replace(/\/\w+\.\w+$/, "");
|
|
281
|
+
return getByRegExp(targetPathWithoutCurrentFileName, new RegExp(`(?<=(${layersWithSlices.join("|")})\\/)(\\w|-)+`, "gi"));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/lib/feature-sliced/extract-feature-sliced-parts.ts
|
|
285
|
+
function extractFeatureSlicedParts(targetPath, cwd) {
|
|
286
|
+
const layer = extractLayer(targetPath, cwd);
|
|
287
|
+
const slice = extractSlice(targetPath);
|
|
288
|
+
const [segment, segmentFiles] = extractSegment(targetPath);
|
|
289
|
+
return {
|
|
290
|
+
layer,
|
|
291
|
+
slice,
|
|
292
|
+
segment,
|
|
293
|
+
segmentFiles
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/lib/feature-sliced/layers.ts
|
|
298
|
+
function isLayer(layer) {
|
|
299
|
+
return typeof layer === "string" && layers.includes(layer);
|
|
300
|
+
}
|
|
301
|
+
function getLayerWeight(layer) {
|
|
302
|
+
return layers.indexOf(layer);
|
|
303
|
+
}
|
|
304
|
+
function canLayerContainSlices(layer) {
|
|
305
|
+
return !layersWithoutSlices.includes(layer);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/lib/feature-sliced/validate-extracted-feature-sliced-parts.ts
|
|
309
|
+
function validateExtractedFeatureSlicedParts(extractedFeatureSlicedParts) {
|
|
310
|
+
const {
|
|
311
|
+
layer,
|
|
312
|
+
slice,
|
|
313
|
+
segment,
|
|
314
|
+
segmentFiles
|
|
315
|
+
} = extractedFeatureSlicedParts;
|
|
316
|
+
const hasLayer = isLayer(layer);
|
|
317
|
+
const hasNotLayer = !hasLayer;
|
|
318
|
+
const hasSlice = !isNull(slice);
|
|
319
|
+
const hasNotSlice = !hasSlice;
|
|
320
|
+
const hasSegment = !isNull(segment);
|
|
321
|
+
const hasNotSegment = !hasSegment;
|
|
322
|
+
const hasSegmentFiles = !isNull(segmentFiles);
|
|
323
|
+
const hasNotSegmentFiles = !hasSegmentFiles;
|
|
324
|
+
const canContainSlices = hasLayer && canLayerContainSlices(layer);
|
|
325
|
+
return {
|
|
326
|
+
hasLayer,
|
|
327
|
+
hasNotLayer,
|
|
328
|
+
hasSlice,
|
|
329
|
+
hasNotSlice,
|
|
330
|
+
hasSegment,
|
|
331
|
+
hasNotSegment,
|
|
332
|
+
hasSegmentFiles,
|
|
333
|
+
hasNotSegmentFiles,
|
|
334
|
+
canLayerContainSlices: canContainSlices
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/lib/feature-sliced/extract-paths-info.ts
|
|
339
|
+
function compareFeatureSlicedParts(fsPartsToCompare) {
|
|
340
|
+
const {
|
|
341
|
+
target,
|
|
342
|
+
currentFile
|
|
343
|
+
} = fsPartsToCompare;
|
|
344
|
+
const hasUnknownLayers = target.validatedFeatureSlicedParts.hasNotLayer || currentFile.validatedFeatureSlicedParts.hasNotLayer;
|
|
345
|
+
const isSameLayer = target.validatedFeatureSlicedParts.hasLayer && currentFile.validatedFeatureSlicedParts.hasLayer && target.fsdParts.layer === currentFile.fsdParts.layer;
|
|
346
|
+
const isSameSlice = target.validatedFeatureSlicedParts.hasSlice && currentFile.validatedFeatureSlicedParts.hasSlice && target.fsdParts.slice === currentFile.fsdParts.slice;
|
|
347
|
+
const isSameSegment = target.fsdParts.segment === currentFile.fsdParts.segment;
|
|
348
|
+
const isSameLayerWithoutSlices = isSameLayer && !target.validatedFeatureSlicedParts.canLayerContainSlices && !currentFile.validatedFeatureSlicedParts.canLayerContainSlices;
|
|
349
|
+
return {
|
|
350
|
+
hasUnknownLayers,
|
|
351
|
+
isSameLayer,
|
|
352
|
+
isSameSlice,
|
|
353
|
+
isSameSegment,
|
|
354
|
+
isSameLayerWithoutSlices
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function extractPathsInfo(node, context) {
|
|
358
|
+
const {
|
|
359
|
+
targetPath,
|
|
360
|
+
normalizedTargetPath,
|
|
361
|
+
normalizedCurrentFilePath,
|
|
362
|
+
absoluteTargetPath,
|
|
363
|
+
normalizedCwd
|
|
364
|
+
} = extractPaths(node, context);
|
|
365
|
+
const fsdPartsOfTarget = extractFeatureSlicedParts(absoluteTargetPath, normalizedCwd);
|
|
366
|
+
const fsdPartsOfCurrentFile = extractFeatureSlicedParts(normalizedCurrentFilePath, normalizedCwd);
|
|
367
|
+
const validatedFeatureSlicedPartsOfTarget = validateExtractedFeatureSlicedParts(fsdPartsOfTarget);
|
|
368
|
+
const validatedFeatureSlicedPartsOfCurrentFile = validateExtractedFeatureSlicedParts(fsdPartsOfCurrentFile);
|
|
369
|
+
const {
|
|
370
|
+
hasUnknownLayers,
|
|
371
|
+
isSameLayer,
|
|
372
|
+
isSameSlice,
|
|
373
|
+
isSameSegment,
|
|
374
|
+
isSameLayerWithoutSlices
|
|
375
|
+
} = compareFeatureSlicedParts({
|
|
376
|
+
target: {
|
|
377
|
+
validatedFeatureSlicedParts: validatedFeatureSlicedPartsOfTarget,
|
|
378
|
+
fsdParts: fsdPartsOfTarget
|
|
379
|
+
},
|
|
380
|
+
currentFile: {
|
|
381
|
+
validatedFeatureSlicedParts: validatedFeatureSlicedPartsOfCurrentFile,
|
|
382
|
+
fsdParts: fsdPartsOfCurrentFile
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
return {
|
|
386
|
+
targetPath,
|
|
387
|
+
normalizedTargetPath,
|
|
388
|
+
normalizedCurrentFilePath,
|
|
389
|
+
absoluteTargetPath,
|
|
390
|
+
fsdPartsOfTarget,
|
|
391
|
+
fsdPartsOfCurrentFile,
|
|
392
|
+
isSameLayer,
|
|
393
|
+
isSameSlice,
|
|
394
|
+
isSameSegment,
|
|
395
|
+
isSameLayerWithoutSlices,
|
|
396
|
+
hasUnknownLayers,
|
|
397
|
+
validatedFeatureSlicedPartsOfTarget,
|
|
398
|
+
validatedFeatureSlicedPartsOfCurrentFile
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/rules/absolute-relative/model/errors.ts
|
|
403
|
+
function reportShouldBeRelative(node, context) {
|
|
404
|
+
context.report({
|
|
405
|
+
node: node.source,
|
|
406
|
+
messageId: "must-be-relative-path" /* MUST_BE_RELATIVE_PATH */
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function reportShouldBeAbsolute(node, context) {
|
|
410
|
+
context.report({
|
|
411
|
+
node: node.source,
|
|
412
|
+
messageId: "must-be-absolute-path" /* MUST_BE_ABSOLUTE_PATH */
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/rules/absolute-relative/model/should-be-absolute.ts
|
|
417
|
+
function shouldBeAbsolute(pathsInfo) {
|
|
418
|
+
const {
|
|
419
|
+
normalizedTargetPath,
|
|
420
|
+
fsdPartsOfTarget,
|
|
421
|
+
fsdPartsOfCurrentFile,
|
|
422
|
+
hasUnknownLayers
|
|
423
|
+
} = pathsInfo;
|
|
424
|
+
const isAbsolute = !isPathRelative(normalizedTargetPath);
|
|
425
|
+
if (isAbsolute) {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
if (hasUnknownLayers) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
return fsdPartsOfCurrentFile.layer !== fsdPartsOfTarget.layer;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// src/rules/absolute-relative/model/should-be-relative.ts
|
|
435
|
+
function shouldBeRelative(pathsInfo) {
|
|
436
|
+
const {
|
|
437
|
+
validatedFeatureSlicedPartsOfCurrentFile,
|
|
438
|
+
normalizedTargetPath,
|
|
439
|
+
isSameLayerWithoutSlices,
|
|
440
|
+
isSameLayer,
|
|
441
|
+
isSameSlice
|
|
442
|
+
} = pathsInfo;
|
|
443
|
+
const isRelative = isPathRelative(normalizedTargetPath);
|
|
444
|
+
if (isRelative) {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
const isImportToLayerPublicApi = validatedFeatureSlicedPartsOfCurrentFile.hasNotSlice && isSameLayer;
|
|
448
|
+
if (isImportToLayerPublicApi) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
if (isSameLayerWithoutSlices) {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
const isSameLayerAndSlice = isSameLayer && isSameSlice;
|
|
455
|
+
return isSameLayerAndSlice;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/rules/absolute-relative/model/validate-and-report.ts
|
|
459
|
+
function validateAndReport(node, context, optionsWithDefault, options = { needCheckForAbsolute: true }) {
|
|
460
|
+
if (!hasPath(node)) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (isIgnoredCurrentFile(context, optionsWithDefault)) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const pathsInfo = extractPathsInfo(node, context);
|
|
467
|
+
if (shouldBeRelative(pathsInfo)) {
|
|
468
|
+
reportShouldBeRelative(node, context);
|
|
469
|
+
}
|
|
470
|
+
if (options.needCheckForAbsolute && shouldBeAbsolute(pathsInfo)) {
|
|
471
|
+
reportShouldBeAbsolute(node, context);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/rules/absolute-relative/index.ts
|
|
476
|
+
var absolute_relative_default = createEslintRule({
|
|
477
|
+
name: "absolute-relative",
|
|
478
|
+
meta: {
|
|
479
|
+
type: "problem",
|
|
480
|
+
docs: {
|
|
481
|
+
description: "Checks for absolute and relative paths"
|
|
482
|
+
},
|
|
483
|
+
messages: {
|
|
484
|
+
["must-be-relative-path" /* MUST_BE_RELATIVE_PATH */]: "There must be relative paths",
|
|
485
|
+
["must-be-absolute-path" /* MUST_BE_ABSOLUTE_PATH */]: "There must be absolute paths"
|
|
486
|
+
},
|
|
487
|
+
schema: [
|
|
488
|
+
{
|
|
489
|
+
type: "object",
|
|
490
|
+
properties: {
|
|
491
|
+
ignoreInFilesPatterns: {
|
|
492
|
+
type: "array",
|
|
493
|
+
items: {
|
|
494
|
+
type: "string"
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
]
|
|
500
|
+
},
|
|
501
|
+
defaultOptions: [
|
|
502
|
+
{
|
|
503
|
+
ignoreInFilesPatterns: []
|
|
504
|
+
}
|
|
505
|
+
],
|
|
506
|
+
create(context, optionsWithDefault) {
|
|
507
|
+
return {
|
|
508
|
+
ImportDeclaration(node) {
|
|
509
|
+
validateAndReport(node, context, optionsWithDefault);
|
|
510
|
+
},
|
|
511
|
+
ImportExpression(node) {
|
|
512
|
+
validateAndReport(node, context, optionsWithDefault);
|
|
513
|
+
},
|
|
514
|
+
ExportAllDeclaration(node) {
|
|
515
|
+
validateAndReport(node, context, optionsWithDefault, { needCheckForAbsolute: false });
|
|
516
|
+
},
|
|
517
|
+
ExportNamedDeclaration(node) {
|
|
518
|
+
validateAndReport(node, context, optionsWithDefault, { needCheckForAbsolute: false });
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
// src/rules/layers-slices/model/validate-and-report.ts
|
|
525
|
+
var import_utils4 = require("@typescript-eslint/utils");
|
|
526
|
+
|
|
527
|
+
// src/rules/layers-slices/model/errors.ts
|
|
528
|
+
var import_utils2 = require("@typescript-eslint/utils");
|
|
529
|
+
function reportCanNotImportLayer(context, node, pathsInfo) {
|
|
530
|
+
function getReportPosition(validatedNode) {
|
|
531
|
+
const isSpecifier = validatedNode.type === import_utils2.AST_NODE_TYPES.ImportSpecifier;
|
|
532
|
+
if (isSpecifier) {
|
|
533
|
+
return validatedNode;
|
|
534
|
+
}
|
|
535
|
+
return validatedNode.source;
|
|
536
|
+
}
|
|
537
|
+
context.report({
|
|
538
|
+
node: getReportPosition(node),
|
|
539
|
+
messageId: "can-not-import" /* CAN_NOT_IMPORT */,
|
|
540
|
+
data: {
|
|
541
|
+
importLayer: pathsInfo.fsdPartsOfTarget.layer,
|
|
542
|
+
currentFileLayer: pathsInfo.fsdPartsOfCurrentFile.layer
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// src/rules/layers-slices/model/is-not-suitable-for-validation.ts
|
|
548
|
+
function isNotSuitableForValidation(pathsInfo) {
|
|
549
|
+
const {
|
|
550
|
+
isSameSlice,
|
|
551
|
+
isSameLayerWithoutSlices,
|
|
552
|
+
hasUnknownLayers
|
|
553
|
+
} = pathsInfo;
|
|
554
|
+
if (hasUnknownLayers) {
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
if (isSameSlice) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
if (isSameLayerWithoutSlices) {
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// src/rules/layers-slices/model/specifiers/has-errors-at-all-specifiers.ts
|
|
567
|
+
function hasErrorsAtAllSpecifiers(specifiers, invalidSpecifiers) {
|
|
568
|
+
const allSpecifiersCount = specifiers.length;
|
|
569
|
+
const invalidSpecifiersCount = invalidSpecifiers.length;
|
|
570
|
+
return invalidSpecifiersCount === allSpecifiersCount;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/rules/layers-slices/model/validate-node/valid-by-type-import.ts
|
|
574
|
+
function validByTypeImport(node, allowTypeImports) {
|
|
575
|
+
const isType = isNodeType(node);
|
|
576
|
+
return allowTypeImports && isType;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/rules/layers-slices/model/specifiers/validate-specifiers.ts
|
|
580
|
+
function validateSpecifiers(specifiers, allowTypeImports) {
|
|
581
|
+
return specifiers.filter((specifier) => !validByTypeImport(specifier, allowTypeImports));
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// src/rules/layers-slices/model/specifiers/extract-import-specifiers.ts
|
|
585
|
+
var import_utils3 = require("@typescript-eslint/utils");
|
|
586
|
+
function extractImportSpecifiers(node) {
|
|
587
|
+
return node.specifiers.filter((specifier) => specifier.type === import_utils3.AST_NODE_TYPES.ImportSpecifier);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// src/rules/layers-slices/model/validate-node/valid-by-layer-order.ts
|
|
591
|
+
function validByLayerOrder(fsdPartsOfTarget, fsdPartsOfCurrentFile) {
|
|
592
|
+
const importLayerOrder = getLayerWeight(
|
|
593
|
+
fsdPartsOfTarget.layer
|
|
594
|
+
/* ts doesn't understand that the check was done on hasUnknownLayers */
|
|
595
|
+
);
|
|
596
|
+
const currentFileLayerOrder = getLayerWeight(
|
|
597
|
+
fsdPartsOfCurrentFile.layer
|
|
598
|
+
/* ts doesn't understand that the check was done on hasUnknownLayers */
|
|
599
|
+
);
|
|
600
|
+
return currentFileLayerOrder > importLayerOrder;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// src/rules/layers-slices/model/validate-node/index.ts
|
|
604
|
+
function validateNode(node, pathsInfo, allowTypeImports) {
|
|
605
|
+
const {
|
|
606
|
+
fsdPartsOfTarget,
|
|
607
|
+
fsdPartsOfCurrentFile
|
|
608
|
+
} = pathsInfo;
|
|
609
|
+
if (validByTypeImport(node, allowTypeImports)) {
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
if (validByLayerOrder(fsdPartsOfTarget, fsdPartsOfCurrentFile)) {
|
|
613
|
+
return true;
|
|
614
|
+
}
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// src/rules/layers-slices/model/validate-and-report.ts
|
|
619
|
+
function validate(node, pathsInfo, allowTypeImports) {
|
|
620
|
+
if (validateNode(node, pathsInfo, allowTypeImports)) {
|
|
621
|
+
return [];
|
|
622
|
+
}
|
|
623
|
+
const isImportExpression = import_utils4.ASTUtils.isNodeOfType(import_utils4.AST_NODE_TYPES.ImportExpression)(node);
|
|
624
|
+
if (isImportExpression) {
|
|
625
|
+
return [node];
|
|
626
|
+
}
|
|
627
|
+
const specifiers = extractImportSpecifiers(node);
|
|
628
|
+
const invalidSpecifiers = validateSpecifiers(specifiers, allowTypeImports);
|
|
629
|
+
if (hasErrorsAtAllSpecifiers(specifiers, invalidSpecifiers)) {
|
|
630
|
+
return [node];
|
|
631
|
+
}
|
|
632
|
+
return invalidSpecifiers;
|
|
633
|
+
}
|
|
634
|
+
function reportValidationErrors(nodes, context, pathsInfo) {
|
|
635
|
+
nodes.forEach((node) => reportCanNotImportLayer(context, node, pathsInfo));
|
|
636
|
+
}
|
|
637
|
+
function validateAndReport2(node, context, optionsWithDefault) {
|
|
638
|
+
if (!hasPath(node)) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const isIgnoredForValidation = isIgnoredTarget(node, optionsWithDefault) || isIgnoredCurrentFile(context, optionsWithDefault);
|
|
642
|
+
if (isIgnoredForValidation) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
const pathsInfo = extractPathsInfo(node, context);
|
|
646
|
+
if (isNotSuitableForValidation(pathsInfo)) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
const { allowTypeImports } = extractRuleOptions(optionsWithDefault);
|
|
650
|
+
const nodesToReport = validate(node, pathsInfo, allowTypeImports);
|
|
651
|
+
reportValidationErrors(nodesToReport, context, pathsInfo);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/rules/layers-slices/index.ts
|
|
655
|
+
var layers_slices_default = createEslintRule({
|
|
656
|
+
name: "layers-slices",
|
|
657
|
+
meta: {
|
|
658
|
+
type: "problem",
|
|
659
|
+
docs: {
|
|
660
|
+
description: "Checks layer imports"
|
|
661
|
+
},
|
|
662
|
+
messages: {
|
|
663
|
+
["can-not-import" /* CAN_NOT_IMPORT */]: 'You cannot import layer "{{ importLayer }}" into "{{ currentFileLayer }}" (shared -> entities -> features -> widgets -> pages -> processes -> app)'
|
|
664
|
+
},
|
|
665
|
+
schema: [
|
|
666
|
+
{
|
|
667
|
+
type: "object",
|
|
668
|
+
properties: {
|
|
669
|
+
allowTypeImports: {
|
|
670
|
+
type: "boolean"
|
|
671
|
+
},
|
|
672
|
+
ignorePatterns: {
|
|
673
|
+
type: "array",
|
|
674
|
+
items: {
|
|
675
|
+
type: "string"
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
ignoreInFilesPatterns: {
|
|
679
|
+
type: "array",
|
|
680
|
+
items: {
|
|
681
|
+
type: "string"
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
]
|
|
687
|
+
},
|
|
688
|
+
defaultOptions: [
|
|
689
|
+
{
|
|
690
|
+
allowTypeImports: true,
|
|
691
|
+
ignorePatterns: [],
|
|
692
|
+
ignoreInFilesPatterns: []
|
|
693
|
+
}
|
|
694
|
+
],
|
|
695
|
+
create(context, optionsWithDefault) {
|
|
696
|
+
return {
|
|
697
|
+
ImportDeclaration(node) {
|
|
698
|
+
validateAndReport2(node, context, optionsWithDefault);
|
|
699
|
+
},
|
|
700
|
+
ImportExpression(node) {
|
|
701
|
+
validateAndReport2(node, context, optionsWithDefault);
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
// src/rules/public-api/model/convert-to-public-api.ts
|
|
708
|
+
function addSlashToStart(targetPath) {
|
|
709
|
+
if (isNull(targetPath)) {
|
|
710
|
+
return "";
|
|
711
|
+
}
|
|
712
|
+
return `/${targetPath}`;
|
|
713
|
+
}
|
|
714
|
+
function extractValueToRemove(pathsInfo) {
|
|
715
|
+
const {
|
|
716
|
+
isSameSlice,
|
|
717
|
+
fsdPartsOfTarget
|
|
718
|
+
} = pathsInfo;
|
|
719
|
+
if (isSameSlice) {
|
|
720
|
+
return fsdPartsOfTarget.segmentFiles;
|
|
721
|
+
}
|
|
722
|
+
return `${fsdPartsOfTarget.segment}${addSlashToStart(fsdPartsOfTarget.segmentFiles)}`;
|
|
723
|
+
}
|
|
724
|
+
function convertToPublicApi(pathsInfo) {
|
|
725
|
+
const { normalizedTargetPath } = pathsInfo;
|
|
726
|
+
const valueToRemove = extractValueToRemove(pathsInfo);
|
|
727
|
+
const publicApiPath = normalizedTargetPath.replace(`/${valueToRemove}`, "");
|
|
728
|
+
return [publicApiPath, valueToRemove];
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/rules/public-api/model/errors.ts
|
|
732
|
+
function reportShouldBeFromPublicApi(node, context) {
|
|
733
|
+
const pathsInfo = extractPathsInfo(node, context);
|
|
734
|
+
const [fixedPath, valueToRemove] = convertToPublicApi(pathsInfo);
|
|
735
|
+
context.report({
|
|
736
|
+
node: node.source,
|
|
737
|
+
messageId: "should-be-from-public-api" /* SHOULD_BE_FROM_PUBLIC_API */,
|
|
738
|
+
data: {
|
|
739
|
+
fixedPath
|
|
740
|
+
},
|
|
741
|
+
suggest: [
|
|
742
|
+
{
|
|
743
|
+
messageId: "remove-suggestion" /* REMOVE_SUGGESTION */,
|
|
744
|
+
data: {
|
|
745
|
+
valueToRemove
|
|
746
|
+
},
|
|
747
|
+
fix: (fixer) => fixer.replaceTextRange(getSourceRangeWithoutQuotes(node.source.range), fixedPath)
|
|
748
|
+
}
|
|
749
|
+
]
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
function reportLayersPublicApiNotAllowed(node, context) {
|
|
753
|
+
context.report({
|
|
754
|
+
node,
|
|
755
|
+
messageId: "layers-public-api-not-allowed" /* LAYERS_PUBLIC_API_NOT_ALLOWED */
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// src/rules/public-api/model/is-index-file.ts
|
|
760
|
+
function isIndexFile(segmentFiles) {
|
|
761
|
+
return /^index\.\w+/i.test(segmentFiles);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/rules/public-api/model/is-segments-public-api.ts
|
|
765
|
+
function isSegmentsPublicApi(pathsInfo) {
|
|
766
|
+
const {
|
|
767
|
+
fsdPartsOfTarget,
|
|
768
|
+
validatedFeatureSlicedPartsOfTarget,
|
|
769
|
+
isSameSegment
|
|
770
|
+
} = pathsInfo;
|
|
771
|
+
const isSegmentPublicApi = validatedFeatureSlicedPartsOfTarget.hasNotSegmentFiles || isIndexFile(
|
|
772
|
+
fsdPartsOfTarget.segmentFiles
|
|
773
|
+
/* 'hasNotSegmentFiles' is already validate it, ts doesn't understand */
|
|
774
|
+
);
|
|
775
|
+
return isSameSegment || isSegmentPublicApi;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// src/rules/public-api/model/is-slice-public-api.ts
|
|
779
|
+
function isSlicePublicApi(pathsInfo) {
|
|
780
|
+
return pathsInfo.validatedFeatureSlicedPartsOfTarget.hasNotSegment;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// src/rules/public-api/model/should-be-from-public-api.ts
|
|
784
|
+
function shouldBeFromSlicePublicApi(pathsInfo) {
|
|
785
|
+
const isFromAnotherSlice = !pathsInfo.isSameSlice;
|
|
786
|
+
return isFromAnotherSlice && !isSlicePublicApi(pathsInfo);
|
|
787
|
+
}
|
|
788
|
+
function shouldBeFromSegmentsPublicApi(pathsInfo, validateOptions) {
|
|
789
|
+
const needValidateSegments = validateOptions.level === "segments" /* SEGMENTS */;
|
|
790
|
+
return needValidateSegments && !isSegmentsPublicApi(pathsInfo);
|
|
791
|
+
}
|
|
792
|
+
function shouldBeFromPublicApi(node, context, optionsWithDefault) {
|
|
793
|
+
const pathsInfo = extractPathsInfo(node, context);
|
|
794
|
+
const ruleOptions = extractRuleOptions(optionsWithDefault);
|
|
795
|
+
return shouldBeFromSlicePublicApi(pathsInfo) || shouldBeFromSegmentsPublicApi(pathsInfo, ruleOptions);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// src/rules/public-api/model/validate-and-report.ts
|
|
799
|
+
function validateAndReport3(node, context, optionsWithDefault) {
|
|
800
|
+
if (!hasPath(node)) {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
if (isIgnoredCurrentFile(context, optionsWithDefault)) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
if (shouldBeFromPublicApi(node, context, optionsWithDefault)) {
|
|
807
|
+
reportShouldBeFromPublicApi(node, context);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/rules/public-api/model/is-layer-public-api.ts
|
|
812
|
+
var import_picomatch2 = __toESM(require("picomatch"), 1);
|
|
813
|
+
function isLayerPublicApi(context) {
|
|
814
|
+
const normalizedCurrentFilePath = extractCurrentFilePath(context);
|
|
815
|
+
const cwd = extractCwd(context);
|
|
816
|
+
const layer = extractLayer(normalizedCurrentFilePath, cwd);
|
|
817
|
+
if (isNull(layer)) {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
const matcher = (0, import_picomatch2.default)([
|
|
821
|
+
`**/${layer}/index.*`
|
|
822
|
+
]);
|
|
823
|
+
return matcher(normalizedCurrentFilePath);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/rules/public-api/model/validate-and-report-program.ts
|
|
827
|
+
function validateAndReportProgram(node, context, optionsWithDefault) {
|
|
828
|
+
if (isIgnoredCurrentFile(context, optionsWithDefault)) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (isLayerPublicApi(context)) {
|
|
832
|
+
reportLayersPublicApiNotAllowed(node, context);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// src/rules/public-api/index.ts
|
|
837
|
+
var public_api_default = createEslintRule({
|
|
838
|
+
name: "public-api",
|
|
839
|
+
meta: {
|
|
840
|
+
type: "problem",
|
|
841
|
+
docs: {
|
|
842
|
+
description: "Check for module imports from public api"
|
|
843
|
+
},
|
|
844
|
+
hasSuggestions: true,
|
|
845
|
+
messages: {
|
|
846
|
+
["should-be-from-public-api" /* SHOULD_BE_FROM_PUBLIC_API */]: 'Absolute imports are only allowed from public api ("{{ fixedPath }}")',
|
|
847
|
+
["remove-suggestion" /* REMOVE_SUGGESTION */]: 'Remove the "{{ valueToRemove }}"',
|
|
848
|
+
["layers-public-api-not-allowed" /* LAYERS_PUBLIC_API_NOT_ALLOWED */]: "The layer public API is not allowed. It harms both architecturally and practically (code splitting)"
|
|
849
|
+
},
|
|
850
|
+
schema: [
|
|
851
|
+
{
|
|
852
|
+
type: "object",
|
|
853
|
+
properties: {
|
|
854
|
+
level: {
|
|
855
|
+
type: "string",
|
|
856
|
+
enum: [
|
|
857
|
+
"segments" /* SEGMENTS */,
|
|
858
|
+
"slices" /* SLICES */
|
|
859
|
+
]
|
|
860
|
+
},
|
|
861
|
+
ignoreInFilesPatterns: {
|
|
862
|
+
type: "array",
|
|
863
|
+
items: {
|
|
864
|
+
type: "string"
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
]
|
|
870
|
+
},
|
|
871
|
+
defaultOptions: [
|
|
872
|
+
{
|
|
873
|
+
level: "slices" /* SLICES */,
|
|
874
|
+
ignoreInFilesPatterns: []
|
|
875
|
+
}
|
|
876
|
+
],
|
|
877
|
+
create(context, optionsWithDefault) {
|
|
878
|
+
return {
|
|
879
|
+
ImportDeclaration(node) {
|
|
880
|
+
validateAndReport3(node, context, optionsWithDefault);
|
|
881
|
+
},
|
|
882
|
+
ImportExpression(node) {
|
|
883
|
+
validateAndReport3(node, context, optionsWithDefault);
|
|
884
|
+
},
|
|
885
|
+
ExportAllDeclaration(node) {
|
|
886
|
+
validateAndReport3(node, context, optionsWithDefault);
|
|
887
|
+
},
|
|
888
|
+
ExportNamedDeclaration(node) {
|
|
889
|
+
validateAndReport3(node, context, optionsWithDefault);
|
|
890
|
+
},
|
|
891
|
+
Program(node) {
|
|
892
|
+
validateAndReportProgram(node, context, optionsWithDefault);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
// src/rules/index.ts
|
|
899
|
+
var rules = {
|
|
900
|
+
"absolute-relative": absolute_relative_default,
|
|
901
|
+
"import-order": import_eslint_plugin_import_x.default.rules.order,
|
|
902
|
+
"layers-slices": layers_slices_default,
|
|
903
|
+
"public-api": public_api_default
|
|
904
|
+
};
|
|
905
|
+
var rules_default = rules;
|
|
906
|
+
|
|
907
|
+
// src/plugin.ts
|
|
908
|
+
var plugin = {
|
|
909
|
+
meta: {
|
|
910
|
+
name: PLUGIN_NAME,
|
|
911
|
+
version
|
|
912
|
+
},
|
|
913
|
+
rules: rules_default
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// src/rules/import-order/configs.ts
|
|
917
|
+
var LAYERS_REVERSED = [...layers].reverse();
|
|
918
|
+
var baseConfig = {
|
|
919
|
+
alphabetize: {
|
|
920
|
+
order: "asc",
|
|
921
|
+
caseInsensitive: true
|
|
922
|
+
},
|
|
923
|
+
pathGroups: LAYERS_REVERSED.map((layer) => ({
|
|
924
|
+
pattern: `**/?(*)${layer}{,/**}`,
|
|
925
|
+
group: "internal",
|
|
926
|
+
position: "after"
|
|
927
|
+
})),
|
|
928
|
+
distinctGroup: false,
|
|
929
|
+
pathGroupsExcludedImportTypes: ["builtin"],
|
|
930
|
+
groups: ["builtin", "external", "internal", "parent", "sibling", "index"]
|
|
931
|
+
};
|
|
932
|
+
var importOrderRuleConfigs = {
|
|
933
|
+
"recommended": [
|
|
934
|
+
"error",
|
|
935
|
+
{
|
|
936
|
+
...baseConfig,
|
|
937
|
+
"newlines-between": "never"
|
|
938
|
+
}
|
|
939
|
+
],
|
|
940
|
+
"with-newlines": [
|
|
941
|
+
"error",
|
|
942
|
+
{
|
|
943
|
+
...baseConfig,
|
|
944
|
+
"newlines-between": "always"
|
|
945
|
+
}
|
|
946
|
+
],
|
|
947
|
+
"with-type-group": [
|
|
948
|
+
"error",
|
|
949
|
+
{
|
|
950
|
+
...baseConfig,
|
|
951
|
+
"newlines-between": "never",
|
|
952
|
+
"pathGroupsExcludedImportTypes": ["builtin", "type"],
|
|
953
|
+
"groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
|
|
954
|
+
}
|
|
955
|
+
],
|
|
956
|
+
"with-newlines-and-type-group": [
|
|
957
|
+
"error",
|
|
958
|
+
{
|
|
959
|
+
...baseConfig,
|
|
960
|
+
"newlines-between": "always",
|
|
961
|
+
"pathGroupsExcludedImportTypes": ["builtin", "type"],
|
|
962
|
+
"groups": ["builtin", "external", "internal", "type", "parent", "sibling", "index"]
|
|
963
|
+
}
|
|
964
|
+
]
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
// src/create-plugin.ts
|
|
968
|
+
function createPlugin(options = {}) {
|
|
969
|
+
const {
|
|
970
|
+
sortImports = "recommended",
|
|
971
|
+
absoluteRelative,
|
|
972
|
+
layersSlices,
|
|
973
|
+
publicApi
|
|
974
|
+
} = options;
|
|
975
|
+
const rules2 = defineRules({ absoluteRelative, layersSlices, publicApi, sortImports });
|
|
976
|
+
return {
|
|
977
|
+
name: PLUGIN_NAME,
|
|
978
|
+
plugins: {
|
|
979
|
+
[PLUGIN_NAME]: plugin
|
|
980
|
+
},
|
|
981
|
+
rules: rules2
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
function defineRules(options) {
|
|
985
|
+
const {
|
|
986
|
+
absoluteRelative = {},
|
|
987
|
+
layersSlices = {},
|
|
988
|
+
publicApi = {},
|
|
989
|
+
sortImports = "recommended"
|
|
990
|
+
} = options;
|
|
991
|
+
const createRuleEntry = (ruleOptions) => ruleOptions ? ["error", ruleOptions] : ["off"];
|
|
992
|
+
const rules2 = {
|
|
993
|
+
[RULE_NAMES.LAYERS_SLICES]: createRuleEntry(layersSlices),
|
|
994
|
+
[RULE_NAMES.ABSOLUTE_RELATIVE]: createRuleEntry(absoluteRelative),
|
|
995
|
+
[RULE_NAMES.PUBLIC_API]: createRuleEntry(publicApi)
|
|
996
|
+
};
|
|
997
|
+
if (sortImports) {
|
|
998
|
+
rules2[RULE_NAMES.IMPORT_ORDER] = importOrderRuleConfigs[sortImports];
|
|
999
|
+
}
|
|
1000
|
+
return rules2;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// src/index.ts
|
|
1004
|
+
var src_default = createPlugin;
|