CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fs-readdir-recursive

Recursively read a directory and return an array of all file paths

90

1.11x
Overview
Eval results
Files

task.mdevals/scenario-1/

Selective Directory Scanner

Description

Build a utility that scans a project directory and returns lists of files while excluding certain directory paths. The utility should be able to recursively scan directories and provide fine-grained control over which subdirectories to include or exclude based on their paths.

Requirements

Implement a module that exports a function scanProjectFiles(rootDir, options) that:

  1. Recursively scans all files in the given rootDir
  2. Accepts an options object with an optional excludeDirs array containing directory names or paths to exclude
  3. Returns an object with two properties:
    • allFiles: array of all file paths found (excluding hidden files/directories by default)
    • filteredFiles: array of file paths with the specified directories excluded
  4. All returned paths should be relative to the rootDir
  5. By default, hidden files and directories (starting with .) should be excluded from both lists

Example Usage

const { scanProjectFiles } = require('./scanner')

// Scan a project directory
const result = scanProjectFiles('/path/to/project', {
  excludeDirs: ['node_modules', 'test', 'coverage']
})

console.log('All files:', result.allFiles)
// ['src/index.js', 'src/utils.js', 'test/test.js', 'package.json', ...]

console.log('Filtered files:', result.filteredFiles)
// ['src/index.js', 'src/utils.js', 'package.json', ...]
// (test/ files excluded)

Dependencies { .dependencies }

fs-readdir-recursive { .dependency }

Provides recursive directory reading functionality.

Test Cases

Test 1: Basic directory scanning @test

File: scanner.test.js

const { scanProjectFiles } = require('./scanner')
const path = require('path')
const fs = require('fs')
const os = require('os')

// Create a temporary test directory structure
const testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-scan-'))
fs.mkdirSync(path.join(testDir, 'src'))
fs.mkdirSync(path.join(testDir, 'test'))
fs.mkdirSync(path.join(testDir, 'build'))
fs.writeFileSync(path.join(testDir, 'src', 'index.js'), '')
fs.writeFileSync(path.join(testDir, 'src', 'util.js'), '')
fs.writeFileSync(path.join(testDir, 'test', 'test.js'), '')
fs.writeFileSync(path.join(testDir, 'build', 'output.js'), '')
fs.writeFileSync(path.join(testDir, 'README.md'), '')

const result = scanProjectFiles(testDir, { excludeDirs: ['test', 'build'] })

// allFiles should contain all non-hidden files
console.assert(result.allFiles.length === 5, 'Should find 5 files total')
console.assert(result.allFiles.includes('README.md'), 'Should include README.md')

// filteredFiles should exclude test and build directories
console.assert(result.filteredFiles.length === 3, 'Should have 3 files after filtering')
console.assert(result.filteredFiles.includes('src/index.js'), 'Should include src files')
console.assert(!result.filteredFiles.some(f => f.startsWith('test/')), 'Should exclude test directory')
console.assert(!result.filteredFiles.some(f => f.startsWith('build/')), 'Should exclude build directory')

Test 2: Nested directory exclusion @test

File: scanner.test.js

const { scanProjectFiles } = require('./scanner')
const path = require('path')
const fs = require('fs')
const os = require('os')

// Create nested directory structure
const testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-nested-'))
fs.mkdirSync(path.join(testDir, 'src'))
fs.mkdirSync(path.join(testDir, 'src', 'components'))
fs.mkdirSync(path.join(testDir, 'src', 'vendor'))
fs.writeFileSync(path.join(testDir, 'src', 'index.js'), '')
fs.writeFileSync(path.join(testDir, 'src', 'components', 'Button.js'), '')
fs.writeFileSync(path.join(testDir, 'src', 'vendor', 'lib.js'), '')

const result = scanProjectFiles(testDir, { excludeDirs: ['vendor'] })

// Should exclude any directory named 'vendor' at any depth
console.assert(!result.filteredFiles.some(f => f.includes('vendor')), 'Should exclude vendor directory')
console.assert(result.filteredFiles.includes('src/index.js'), 'Should include src/index.js')
console.assert(result.filteredFiles.includes('src/components/Button.js'), 'Should include components files')

Implementation Notes

  • Focus on using the directory scanning library effectively to handle path-based filtering
  • Ensure that directory exclusions work at any nesting level
  • The solution should handle both relative and absolute paths correctly

Install with Tessl CLI

npx tessl i tessl/npm-fs-readdir-recursive

tile.json