@feature-sliced/filesystem v3.0.1
@feature-sliced/filesystem
A set of utilities for locating and working with FSD roots in the file system.
This project is intended for developers of tooling for Feature-Sliced Design.
Installation
pnpm add @feature-sliced/filesystemnpm install --save @feature-sliced/filesystemType definitions are built in 😎.
API
resolveImport
function resolveImport(
  importedPath: string,
  importerPath: string,
  tsCompilerOptions: typescript.CompilerOptions,
  fileExists: (path: string) => boolean,
  directoryExists?: (path: string) => boolean,
): string | null;Given a file name, an imported path, and a TSConfig object, produce a path to the imported file, relative to TypeScript's baseUrl.
Example:
// /project/src/pages/home/ui/HomePage.tsx
import { Button } from "~/shared/ui";// ./tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "Bundler",
    "baseUrl": ".",
    "paths": {
      "~/*": ["./src/*"]
    }
  }
}resolveImport(
  "~/shared/ui",
  "./src/pages/home/ui/HomePage.tsx",
  { moduleResolution: "Bundler", baseUrl: ".", paths: { "~/*": ["./src/*"] } },
  fs.existsSync,
);Expected output: /project/src/shared/ui/index.ts.
layerSequence, unslicedLayers, and conventionalSegmentNames
Definitions of important names in FSD.
export const layerSequence: Array<LayerName> = [
  "shared",
  "entities",
  "features",
  "widgets",
  "pages",
  "app",
];
export const unslicedLayers = ["shared", "app"];
export const conventionalSegmentNames = ["ui", "api", "lib", "model", "config"];FSD-aware traversal
A set of traversal functions for a simple representation of a file system:
export interface File {
  type: "file";
  path: string;
}
export interface Folder {
  type: "folder";
  path: string;
  children: Array<File | Folder>;
}getLayers
export type LayerName =
  | "shared"
  | "entities"
  | "features"
  | "widgets"
  | "pages"
  | "app";
function getLayers(fsdRoot: Folder): Partial<Record<LayerName, Folder>>;Extract layers from an FSD root. Returns a mapping of layer name to folder object.
getSlices
function getSlices(
  slicedLayer: Folder,
  additionalSegmentNames: Array<string> = [],
): Record<string, Folder>;Extract slices from a sliced layer. Returns a mapping of slice name (potentially containing slashes) to folder object.
A folder is detected as a slice when it has at least one folder/file with a name of a conventional segment (ui, api, model, lib, config). If your project contains slices that don't have those segments, you can provide additional segment names.
getSegments
function getSegments(
  sliceOrUnslicedLayer: Folder,
): Record<string, Folder | File>;Extract segments from a slice or an unsliced layer. Returns a mapping of segment name to folder or file object.
getAllSlices
function getAllSlices(
  fsdRoot: Folder,
  additionalSegmentNames: Array<string> = [],
): Record<string, Folder & { layerName: string }>;Extract slices from all layers of an FSD root. Returns a mapping of slice name (potentially containing slashes) to folder object, augmented with a layerName property.
A folder is detected as a slice when it has at least one folder/file with a name of a conventional segment (ui, api, model, lib, config). If your project contains slices that don't have those segments, you can provide additional segment names.
getAllSegments
function getAllSegments(fsdRoot: Folder): Array<{
  segment: Folder | File;
  segmentName: string;
  sliceName: string | null;
  layerName: LayerName;
}>;Extract segments from all slices and layers of an FSD root. Returns a flat array of segments along with their name and location in the FSD root (layer, slice).
isSliced
!NOTE
Not to be confused withisSlice, a function that determines if a folder looks like a slice based on the segments that it contains.
export type LayerName =
  | "shared"
  | "entities"
  | "features"
  | "widgets"
  | "pages"
  | "app";
function isSliced(layerOrName: Folder | LayerName): boolean;Determine if this layer is sliced. You can pass the folder of a layer or the name (lowercase). Only layers Shared and App are not sliced, the rest are.
getIndexes
function getIndexes(fileOrFolder: File | Folder): File[];Get the index (public API) of a slice or segment. When a segment is a file, it is its own index. When a segment is a folder, it returns an array of index files within that folder. Multiple index files (e.g., index.client.js, index.server.js) are supported.
isIndex
function isIndex(fileOrFolder: File | Folder): boolean;Determine if a given file or folder is an index file (only files can be indexes, folders are accepted for convenience, but always return false).
isSlice
!NOTE
Not to be confused withisSliced, a function that determines if a layer should contain slices according to FSD.
function isSlice(
  folder: Folder,
  additionalSegmentNames: Array<string> = [],
): boolean;Determine if this folder is a slice.
Slices are defined as folders that contain at least one segment. Additional segment names can be provided if some slice in project contains only unconventional segments.
isCrossImportPublicApi
function isCrossImportPublicApi(
  file: File,
  {
    inSlice,
    forSlice,
    layerPath,
  }: { inSlice: string; forSlice: string; layerPath: string },
): boolean;Check if a given file is a cross-import public API defined in the slice inSlice for the slice forSlice on a given layer.
For example:
const file = { path: "./src/entities/user/@x/product.ts", type: "file" };
isCrossImportPublicApi(file, {
  inSlice: "user",
  forSlice: "product",
  layerPath: "./src/entities",
}); // true