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

directory-lint

v2.0.3

Published

Directory Lint

Downloads

140

Readme

Directory Lint

A powerful TypeScript library for validating and generating directory structures based on schema definitions. Ensure your project follows the correct file and folder organization with ease.

npm version License: MIT

✨ Features

  • 🔍 Schema-based Validation - Define your directory structure using intuitive schemas
  • 🏗️ Automatic Generation - Create directory structures from schemas with content templates
  • 📝 Pattern Matching - Support for wildcards and regex patterns
  • 🔧 Flexible Backend - Pluggable backend system (File System or custom)
  • 📦 Zero Dependencies - Lightweight with minimal footprint
  • 🎯 TypeScript First - Full TypeScript support with comprehensive types
  • Custom Validation - Validate file content with custom functions

📦 Installation

npm install directory-lint

🚀 Quick Start

Validating a Directory Structure

import { DirectoryLint, type ValidateSchema } from "directory-lint";

const schema: ValidateSchema = {
  "src": {
    type: "directory",
    required: true,
    children: {
      "index.ts": {
        type: "file",
        required: true
      },
      "components": {
        type: "directory",
        required: true
      }
    }
  },
  "package.json": {
    type: "file",
    required: true
  }
};

const linter = new DirectoryLint();

const result = await linter.validate("./my-project", schema, {
  ignore: ["node_modules", "dist", ".git"]
});

console.log("Validation result:", result);

Generating a Directory Structure

import { DirectoryLint, type GenerateSchema } from "directory-lint";

const schema: GenerateSchema = {
  "src": {
    type: "directory",
    children: {
      "index.ts": {
        type: "file",
        content: "export * from './components';\n"
      },
      "utils": {
        type: "directory",
        children: {
          "helper.ts": {
            type: "file",
            content: `// Generated on ${new Date().toISOString()}\n`
          }
        }
      }
    }
  }
};

const linter = new DirectoryLint();

const result = await linter.generate("./new-project", schema, {
  overwrite: true,
  recursive: true
});

console.log("✅ Directory structure generated!");
console.log("Generated paths:", result.paths);

📚 Schema Definition

Schema Types

Directory Lint uses two distinct schema types:

  • GenerateSchema - For creating directory structures
  • ValidateSchema - For validating existing directory structures

Validate Schema Structure

type ValidateSchema = Record<string, ValidateNode>;

type ValidateNode = ValidateFileSchema | ValidateDirectorySchema;

interface ValidateFileSchema {
  type: "file";
  validate?: (content: any) => boolean;
  required?: boolean;  // Default: true
}

interface ValidateDirectorySchema {
  type: "directory";
  children?: ValidateSchema;
  required?: boolean;  // Default: true
}

Generate Schema Structure

type GenerateSchema = Record<string, GenerateNode>;

type GenerateNode = GenerateFileSchema | GenerateDirectorySchema;

interface GenerateFileSchema {
  type: "file";
  content?: any;  // File content (string, Buffer, etc.)
}

interface GenerateDirectorySchema {
  type: "directory";
  children?: GenerateSchema;
}

Pattern Matching

Directory Lint supports flexible pattern matching in validation schemas:

1. Exact Match

{
  "config.json": {
    type: "file",
    required: true
  }
}

2. Wildcard Pattern

{
  "*.test.ts": {
    type: "file",
    required: false
  }
}

3. Regex Pattern

{
  "/^component-.+\\.tsx$/": {
    type: "file",
    required: false
  }
}

Note: Regex patterns are not supported in GenerateSchema and will throw a RegexNotSupported error.

💡 Examples

Basic Generation

import { DirectoryLint, type GenerateSchema } from "directory-lint";

const schema: GenerateSchema = {
  "basic_file": {
    type: "file",
  },
  "basic_folder": {
    type: "directory",
    children: {
      "sub_dir_file": {
        type: "file",
        content: "Hello, World!"
      }
    }
  }
}

const linter = new DirectoryLint();
await linter.generate("./generated", schema, { overwrite: true });

Basic Validation with Custom Validation

import { DirectoryLint, type ValidateSchema } from "directory-lint";

const schema: ValidateSchema = {
  "generated": {
    type: "directory",
    required: true,
    children: {
      "content.txt": {
        type: "file",
        required: true
      },
      "*.txt": {
        type: "file",
        validate: (content: string): boolean => {
          return content.length > 1;
        }
      }
    }
  }
}

const linter = new DirectoryLint();
const result = await linter.validate("./", schema, { 
  ignore: ["node_modules"] 
});

Project Template Generation

import { DirectoryLint, type GenerateSchema } from "directory-lint";

const projectSchema: GenerateSchema = {
  "src": {
    type: "directory",
    children: {
      "index.ts": {
        type: "file",
        content: "console.log('Hello, TypeScript!');"
      },
      "types": {
        type: "directory",
        children: {
          "index.d.ts": {
            type: "file",
            content: "export {};"
          }
        }
      }
    }
  },
  "package.json": {
    type: "file",
    content: JSON.stringify({
      name: "my-project",
      version: "1.0.0",
      main: "src/index.ts"
    }, null, 2)
  },
  "tsconfig.json": {
    type: "file",
    content: JSON.stringify({
      compilerOptions: {
        target: "ES2020",
        module: "commonjs",
        strict: true
      }
    }, null, 2)
  }
};

const linter = new DirectoryLint();
await linter.generate("./my-new-project", projectSchema, {
  recursive: true,
  overwrite: false
});

CI/CD Validation

import { DirectoryLint, type ValidateSchema } from "directory-lint";

const ciSchema: ValidateSchema = {
  "src": {
    type: "directory",
    required: true,
    children: {
      "index.ts": {
        type: "file",
        required: true
      }
    }
  },
  "package.json": {
    type: "file",
    required: true,
    validate: (content: any) => {
      try {
        const pkg = JSON.parse(content);
        return pkg.name && pkg.version;
      } catch {
        return false;
      }
    }
  },
  "*.config.js": {
    type: "file",
    required: false
  }
};

const linter = new DirectoryLint();

try {
  const result = await linter.validate(".", ciSchema, {
    ignore: ["node_modules", "dist", ".git"]
  });
  console.log("✅ Structure validation passed!");
} catch (error) {
  console.error("❌ Structure validation failed:", error.message);
  process.exit(1);
}

🔌 Custom Backend

Create custom backends for different storage systems:

import { LintBackend, LintItem } from "directory-lint";

const CustomBackend: LintBackend = {
  getAllItems(path: string): LintItem[] {
    // Return items in the directory
    return [
      { name: "file.txt", type: "file" },
      { name: "folder", type: "directory" }
    ];
  },

  writeFile(path: string, content: any): void {
    // Write file content
    console.log(`Writing to ${path}:`, content);
  },

  readFile(path: string): any {
    // Read file content
    return "file content";
  },

  makeDirectory(path: string, recursive?: boolean): void {
    // Create directory
    console.log(`Creating directory ${path}, recursive: ${recursive}`);
  },

  exists(path: string): boolean {
    // Check if path exists
    return true;
  }
};

const linter = new DirectoryLint(CustomBackend);

📖 API Reference

DirectoryLint

Constructor

constructor(backend?: LintBackend)

Creates a new DirectoryLint instance with an optional custom backend. Defaults to FileSystemBackend.

Methods

generate(cwd: string, schema: GenerateSchema, options?: GenerateOptions): Promise<GenerateResult>

Generates a directory structure based on a schema.

Parameters:

  • cwd: Current working directory (base path)
  • schema: Generation schema definition
  • options: Optional generation options

Options:

  • overwrite?: boolean - Overwrite existing files (default: false)
  • recursive?: boolean - Create parent directories if they don't exist (default: false)

Returns:

interface GenerateResult {
  cwd: string;
  paths: Record<string, {
    type: "file" | "directory";
    path: string;
    children?: Record<string, ...>;
  }>;
}

Throws:

  • RegexNotSupported - If regex patterns are used in the schema
validate(cwd: string, schema: ValidateSchema, options?: ValidateOptions): Promise<ValidateResult>

Validates a directory structure against a schema.

Parameters:

  • cwd: Current working directory (base path)
  • schema: Validation schema definition
  • options: Optional validation options

Options:

  • ignore: string[] - Array of file/directory names to ignore during validation

Returns:

interface ValidateResult {
  cwd: string;
  paths: Record<string, {
    type: "file" | "directory";
    name: string;
    path: string;
    children?: Record<string, ...>;
  }>;
}

Throws:

  • InvalidStructure - If required items are missing or have incorrect types
  • InvalidContent - If file content fails custom validation

Backend Interface

interface LintBackend {
  getAllItems(path: string): LintItem[];
  writeFile(path: string, content: any): void;
  readFile(path: string): any;
  makeDirectory(path: string, recursive?: boolean): void;
  exists(path: string): boolean;
}

interface LintItem {
  name: string;
  type: "file" | "directory";
}

🚨 Error Handling

Directory Lint throws specific errors for different failure scenarios:

import { InvalidStructure, InvalidContent, RegexNotSupported } from "directory-lint";

try {
  await linter.validate("./project", schema, { ignore: [] });
} catch (error) {
  if (error instanceof InvalidStructure) {
    console.error("Structure error:", error.message);
  } else if (error instanceof InvalidContent) {
    console.error("Content validation failed:", error.message);
  } else if (error instanceof RegexNotSupported) {
    console.error("Regex not allowed in generate schema:", error.message);
  }
}

🔍 Pattern Matching Details

Wildcard Patterns

Use * to match any sequence of characters:

{
  "*.ts": { type: "file" },        // Matches: file.ts, index.ts, etc.
  "test-*": { type: "directory" }  // Matches: test-unit, test-e2e, etc.
}

Regex Patterns

Use /pattern/ syntax for complex matching:

{
  "/^[a-z]+\\.config\\.(js|ts)$/": {
    type: "file"
  }
}
// Matches: vite.config.js, jest.config.ts, etc.

Exact Match

Simple string keys match exactly:

{
  "package.json": { type: "file" },
  "src": { type: "directory" }
}

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

# Clone the repository
git clone https://github.com/yourusername/directory-lint.git

# Install dependencies
npm install

# Build the project
npm run build

# Run examples
npm run example:generate
npm run example:validate

📝 License

MIT © Henry Vilani

🙏 Acknowledgments

Built with ❤️ for the developer community.