npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kekkai/structure-lint

v1.1.1

Published

Config-driven ESLint structure rule generator enforcing one-way folder dependency flow, with a separate CLI for docs sync/verification.

Readme

codecov

English | 繁體中文

📦 @kekkai/structure-lint

一個 config-driven 的 ESLint 結構規則產生器,用來強制專案遵守 單向資料夾依賴(One-way Dependency Flow),並提供獨立 CLI 來同步與驗證專案文件中的依賴規則說明。

🔍 What Problem Does This Solve?

在中大型前端專案中,資料夾結構往往隨著功能成長而逐漸失控:

  • 模組之間可以隨意互相 import
  • 相對路徑(../)跨層引用,難以追蹤實際依賴關係
  • 架構規則只存在於文件,無法被工具驗證
  • 文件與實際程式碼逐漸脫節

@kekkai/structure-lint 的目的不是「規範寫法」,而是 把資料夾結構與依賴方向,轉換成可被 ESLint 強制執行的規則

⚠️ ESLint v9+ Required

本套件基於 ESLint Flat Config 設計,
僅支援 ESLint v9 以上版本

如果你的專案仍使用 .eslintrc(legacy config),
請先升級至 Flat Config 架構後再使用本套件。

✨ Core Ideas

這個套件建立在三個核心概念之上:

  1. Folder-as-a-Module

    • 每個子資料夾視為一個獨立模組(例如 hooks/useShuffleCardscomponents/Card
    • 建議使用 index.ts 作為模組入口,讓引用點一致且可讀
  2. One-way Dependency Flow

    • 依賴關係以「資料夾層級」定義:每個資料夾只能依賴允許的下游資料夾
    • 不允許逆向依賴,也不允許跨層跳轉
  3. Enforceable Imports (Alias-only Cross-folder Imports)

    • 模組內部允許相對路徑(./
    • 跨資料夾引用一律使用專案 alias(例如 ~app/...),避免 ../ 形成不可控的捷徑依賴

🗂️ Example Folder Structure:

src/
├─ components/
│  └─ Card/
│     ├─ Component.tsx
│     ├─ index.ts
│     └─ types.ts
├─ containers/
│  └─ DeckDrawStage/
│     ├─ Container.tsx
│     ├─ index.ts
│     └─ types.ts
└─ main.tsx

📥 Installation

npm install -D @kekkai/structure-lint

本套件同時提供:

  • ESLint Flat Config 的設定產生器
  • 一個獨立的 CLI,用於文件同步與驗證

🚀 Quick Start

  • eslint.config.(js|ts) @kekkai/structure-lint 支援兩種使用方式,請依專案需求選擇最合適的模式:

    import { defineConfig } from 'eslint/config';
    import { createStructureLint } from '@kekkai/structure-lint';
    
    export default defineConfig([
      // Options 1. 使用 structure.config.json
      ...createStructureLint(),
    
      // Options 2. 直接在 eslint.config.ts 中定義規則
      ...createStructureLint({
        appAlias: '~app',
        lintFiles: 'src/{folder}/**/*.{ts,tsx}',
        dependencyFlow: [
          ['pages', 'layouts'],
          ['layouts', 'containers'],
          ['containers', 'components'],
          ['components', 'hooks'],
        ],
      }),
    ]);
  • CLI @kekkai/structure-lint 提供獨立的 CLI,用來將 Dependency Flow 規則同步到指定的 Markdown 文件 中。

    npx structure-lint

    💡 CLI 僅會讀取 structure.config.json。

🧩 structure.config.json

structure.config.json 用來定義專案的 資料夾依賴規則 與 文件同步設定。此檔案會同時被:

  • ESLint 設定 (createStructureLint())
  • CLI (npx structure-lint)

所讀取。

🔧 Configuration Options

{
  /**
   * appAlias
   *   type (required):
   *   - string
   *
   * 專案使用的模組 alias,用於強制跨資料夾 import 時的統一路徑格式。
   * - 所有跨 folder 的 import 必須 使用此 alias
   * - 用來取代不安全、不可控的 `../` 相對路徑
   */
  "appAlias": "~app",

  /**
   * lintFiles
   *   type (required):
   *   - string | string[]
   *
   * 指定 ESLint 要套用結構規則的檔案路徑。
   * - 必須包含 `{folder}` 佔位符
   * - `{folder}` 會在執行時自動替換為 dependencyFlow 中的每個資料夾名稱
   */
  "lintFiles": "src/{folder}/**/*.{ts,tsx}",

  /**
   * moduleLayout
   *   type (optional)
   *   - 'folder' | 'flat'
   *
   * 用來指定各層(layer)中模組的組織方式,
   * 並影響相對路徑(relative import)的限制規則產生方式。
   *
   * - 'folder'(預設):
   *   每個模組以資料夾為單位存在
   *   (例如 components/Card/*),
   *   跨模組只能透過模組入口(index.ts)引用。
   *
   * - 'flat':
   *   模組直接以檔案形式存在於該層底下
   *   (例如 components/Card.tsx)。
   *
   * 預設值:'folder'
   */
  "moduleLayout": "folder",

  /**
   * dependencyFlow
   *   type (required):
   *   - [
   *       string, // from folder
   *       string, // to folder
   *       {
   *         description?: string; // 僅用於文件輸出(Mermaid flowchart 註解),不影響 ESLint 規則
   *         selfOnly?: boolean;   // true 表示 from folder 只能直接依賴 to folder,不可再往下延伸依賴鏈
   *       }?
   *     ][]
   *
   * 定義資料夾之間的 單向依賴關係。
   */
  "dependencyFlow": [
    ["pages", "containers"],
    ["containers", "contexts", { description: "Only Provider" }],
    ["containers", "components"],
    ["components", "hooks"],
    ["hooks", "contexts", { description: "Only Context", selfOnly: true }],
  ],

  /**
   * docs
   *   type (optional)
   *   - {
   *       file: string;      // 要寫入的 Markdown 檔案路徑
   *       markerTag: string; // 用來標記自動產生區塊的識別字
   *       content?: string;  // 自定義文件說明內容
   *     }
   *
   * 設定 CLI 用來 同步 dependencyFlow 至 Markdown 文件。
   */
  "docs": {
    "file": "README.md",
    "markerTag": "DEPENDENCY_RULE"
  },

  /**
   * overrideRules
   *   type (optional)
   *   - {
   *       [key: string]:       // key 必須是 dependencyFlow 中出現過的資料夾名稱
   *         EslintRulesConfig; // value 為 ESLint rules 設定物件
   *     }
   *
   * 為特定資料夾覆寫或補充 ESLint 規則。
   */
  "overrideRules": {
    "contexts": {
      "react-refresh/only-export-components": "off
    }
  },

  /**
   * packageImportRules
   *   type (optional)
   *   - {
   *       name: string;           // npm 套件名稱
   *       importNames?: string[]; // 僅限制指定的 named imports。若省略,則限制整個套件
   *       allowedInFolders: F[];  // 允許使用該套件的資料夾清單
   *     }[]
   *
   * 限制 特定套件或特定 import 成員 只能在指定資料夾中使用。
   */
  "packageImportRules": [
    {
      "name": "react",
      "importNames": ["createContext"],
      "allowedInFolders": ["contexts"]
    },
    {
      "name": "react",
      "importNames": ["useContext"],
      "allowedInFolders": ["hooks"]
    }
  ]
}

dependencyFlow 設定對應的 mermaid flowchart 如下:

flowchart TD
  pages --> containers
  containers --> | Only Provider | contexts
  containers --> components
  components --> hooks
  hooks --> | Only Context | contexts

以範例中 markerTag 的設定,CLI 會尋找以下區塊並覆寫內容:

<!-- DEPENDENCY_RULE:START -->
<!-- DEPENDENCY_RULE:END -->

🔁 Circular Dependencies (Optional)

@kekkai/structure-lint 會嚴格限制 跨層 的單向依賴方向,但仍刻意允許 同一層內的模組彼此引用 作為設計取捨。

因此,在相同 layer 之內,仍然可能發生循環依賴(circular dependencies)。 這在模組規模較小時通常是可接受的,但隨著專案成長,可能會逐漸帶來風險。

如果你的團隊希望進一步偵測這類情況,可以選擇性地啟用以下規則:

⚠️ TypeScript 專案必須正確設定 resolver,否則可能無法偵測到循環依賴。 建議搭配使用 eslint-import-resolver-typescript

import imports from 'eslint-plugin-import';
import { defineConfig } from 'eslint/config';
import { createStructureLint } from '@kekkai/structure-lint';

export default defineConfig([
  {
    plugins: {
      import: imports,
    },
    settings: {
      'import/parsers': {
        // Project file extensions handled by the TypeScript parser
        '@typescript-eslint/parser': ['.ts', '.tsx'],
      },
      'import/resolver': {
        typescript: true,
        node: {
          // Project file extensions used for module resolution
          extensions: ['.ts', '.tsx'],
        },
      },
    },
    rules: {
      'import/no-cycle': 'error',
    },
  },
  ...createStructureLint(),
]);

🧠 Philosophy

@kekkai/structure-lint 將資料夾結構視為架構本身。

由你定義依賴規則,
由 ESLint 強制執行,
並確保文件與實際架構保持同步。

適合重視可讀性、可維護性長期結構一致性的團隊。