@feature-sliced/filesystem

中文文档
3.1.1发布于 2026/08/26ISCTypeScriptESM + CJS近 30 天下载 73.1万

A set of utilities for locating and working with FSD roots in the file system.

原始使用文档
文档目录5 节
  1. Installation
  2. API
  3. resolveImport
  4. layerSequence , unslicedLayers , and conventionalSegmentNam…
  5. FSD-aware traversal

@feature-sliced/filesystem

npm version minzipped package size

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/filesystem
npm install --save @feature-sliced/filesystem

Type 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>;
}

All traversal functions recognize prefixes on layer folders (an underscore or a digit followed by an underscore, e.g. _app or 6_shared). Layer names are always reported without the prefix, while the returned Folder objects keep the physical, prefixed path.

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. Prefixed layers (e.g. 6_shared, _app) are mapped to their canonical names (shared, app). When both a prefixed and a non-prefixed variant of the same layer exist, the prefixed one wins.

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. The layerName is the canonical (prefix-stripped) layer name.

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 with isSlice, 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 with isSliced, 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

版本与发布记录

@feature-sliced/filesystem 共发布 16 个版本,首次发布于 2024/01/25;过去 12 个月发布了 2 个版本。

版本发布日期距今
3.1.1latest2026/08/262 个月前
3.1.02026/04/176 个月前
3.0.12025/04/191.6 年前
3.0.02025/03/191.7 年前
2.4.02024/10/022 年前
2.3.02024/09/282 年前

关于 @feature-sliced/filesystem 的常见问题

@feature-sliced/filesystem 是什么?

A set of utilities for locating and working with FSD roots in the file system.

如何安装 @feature-sliced/filesystem?

在项目目录运行 npm install @feature-sliced/filesystem,或使用 pnpm add / yarn add / bun add。

@feature-sliced/filesystem 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@feature-sliced/filesystem 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@feature-sliced/filesystem 可以商用吗?

@feature-sliced/filesystem 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@feature-sliced/filesystem 的下载量有多少?

根据 npm 官方下载统计,@feature-sliced/filesystem 在 2026/10/15 – 2026/11/13 这 30 天内被下载 731,075 次,日均约 24,369 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@feature-sliced/filesystem 还在维护吗?

最新版本 3.1.1 发布于 2026/08/26(2 个月前);至今共发布 16 个版本,其中过去 12 个月发布了 2 个;首次发布于 2024/01/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。