@feature-sliced/filesystem
Version:
A set of utilities for locating and working with FSD roots in the file system.
233 lines (227 loc) • 7.62 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
conventionalSegmentNames: () => conventionalSegmentNames,
crossReferenceToken: () => crossReferenceToken,
getAllSegments: () => getAllSegments,
getAllSlices: () => getAllSlices,
getIndexes: () => getIndexes,
getLayers: () => getLayers,
getSegments: () => getSegments,
getSlices: () => getSlices,
isCrossImportPublicApi: () => isCrossImportPublicApi,
isIndex: () => isIndex,
isSlice: () => isSlice,
isSliced: () => isSliced,
layerSequence: () => layerSequence,
resolveImport: () => resolveImport,
unslicedLayers: () => unslicedLayers
});
module.exports = __toCommonJS(index_exports);
// src/fsd-aware-traverse.ts
var import_node_path = require("path");
// src/definitions.ts
var layerSequence = [
"shared",
"entities",
"features",
"widgets",
"pages",
"app"
];
var unslicedLayers = ["shared", "app"];
var conventionalSegmentNames = ["ui", "api", "lib", "model", "config"];
var crossReferenceToken = "@x";
// src/fsd-aware-traverse.ts
function getLayers(fsdRoot) {
return Object.fromEntries(
fsdRoot.children.filter(
(child) => child.type === "folder" && layerSequence.includes((0, import_node_path.basename)(child.path))
).map((child) => [(0, import_node_path.basename)(child.path), child])
);
}
function getSlices(slicedLayer, additionalSegmentNames = []) {
const slices = {};
function traverse(folder, pathPrefix = "") {
if (isSlice(folder, additionalSegmentNames)) {
slices[(0, import_node_path.join)(pathPrefix, (0, import_node_path.basename)(folder.path))] = folder;
} else {
folder.children.forEach((child) => {
if (child.type === "folder") {
traverse(child, (0, import_node_path.join)(pathPrefix, (0, import_node_path.basename)(folder.path)));
}
});
}
}
for (const child of slicedLayer.children) {
if (child.type === "folder") {
traverse(child);
}
}
return slices;
}
function getSegments(sliceOrUnslicedLayer) {
return Object.fromEntries(
sliceOrUnslicedLayer.children.filter((child) => !isIndex(child)).map((child) => [(0, import_node_path.parse)(child.path).name, child])
);
}
function getAllSlices(fsdRoot, additionalSegmentNames = []) {
return Object.values(getLayers(fsdRoot)).filter(isSliced).reduce((slices, layer) => {
return {
...slices,
...Object.fromEntries(
Object.entries(getSlices(layer, additionalSegmentNames)).map(
([name, slice]) => [
name,
{ ...slice, layerName: (0, import_node_path.basename)(layer.path) }
]
)
)
};
}, {});
}
function getAllSegments(fsdRoot) {
return Object.entries(getLayers(fsdRoot)).flatMap(([layerName, layer]) => {
if (isSliced(layer)) {
return Object.entries(getSlices(layer)).flatMap(
([sliceName, slice]) => Object.entries(getSegments(slice)).map(([segmentName, segment]) => ({
segment,
segmentName,
sliceName,
layerName
}))
);
} else {
return Object.entries(getSegments(layer)).map(
([segmentName, segment]) => ({
segment,
segmentName,
sliceName: null,
layerName
})
);
}
});
}
function isSliced(layerOrName) {
return !unslicedLayers.includes(
(0, import_node_path.basename)(typeof layerOrName === "string" ? layerOrName : layerOrName.path)
);
}
function getIndexes(fileOrFolder) {
if (fileOrFolder.type === "file") {
return [fileOrFolder];
}
return fileOrFolder.children.filter(isIndex);
}
function isIndex(fileOrFolder) {
if (fileOrFolder.type === "file") {
const separator = ".";
const parsedFileName = (0, import_node_path.parse)(fileOrFolder.path).name;
return parsedFileName.split(separator).at(0) === "index";
}
return false;
}
function isCrossImportPublicApi(file, {
inSlice,
forSlice,
layerPath
}) {
const { dir, name } = (0, import_node_path.parse)(file.path);
if (isIndex(file)) {
return dir === (0, import_node_path.join)(layerPath, inSlice, "@x", forSlice);
}
return name === forSlice && dir === (0, import_node_path.join)(layerPath, inSlice, "@x");
}
function isSlice(folder, additionalSegmentNames = []) {
return folder.children.some(
(child) => conventionalSegmentNames.concat(additionalSegmentNames).includes((0, import_node_path.parse)(child.path).name)
);
}
// src/resolve-import.ts
var import_node_path2 = require("path");
var import_typescript = __toESM(require("typescript"), 1);
function resolveImport(importedPath, importerPath, tsCompilerOptions, fileExists, directoryExists) {
return import_typescript.default.resolveModuleName(
importedPath,
importerPath,
normalizeCompilerOptions(tsCompilerOptions),
{
...import_typescript.default.sys,
fileExists,
directoryExists
}
).resolvedModule?.resolvedFileName?.replaceAll("/", import_node_path2.sep) ?? null;
}
var imperfectKeys = {
module: import_typescript.default.ModuleKind,
moduleResolution: {
...import_typescript.default.ModuleResolutionKind,
node: import_typescript.default.ModuleResolutionKind.Node10
},
moduleDetection: import_typescript.default.ModuleDetectionKind,
newLine: import_typescript.default.NewLineKind,
target: import_typescript.default.ScriptTarget
};
function normalizeCompilerOptions(compilerOptions) {
return Object.fromEntries(
Object.entries(compilerOptions).map(([key, value]) => {
if (Object.keys(imperfectKeys).includes(key) && typeof value === "string") {
for (const [enumKey, enumValue] of Object.entries(
imperfectKeys[key]
)) {
if (enumKey.toLowerCase() === value.toLowerCase()) {
return [key, enumValue];
}
}
}
return [key, value];
})
);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
conventionalSegmentNames,
crossReferenceToken,
getAllSegments,
getAllSlices,
getIndexes,
getLayers,
getSegments,
getSlices,
isCrossImportPublicApi,
isIndex,
isSlice,
isSliced,
layerSequence,
resolveImport,
unslicedLayers
});
;