or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md
tile.json

index.mddocs/

0

# Klaw

1

2

Klaw is a Node.js file system walker that provides a Readable stream interface for recursively traversing directories and their contents. It enables developers to walk through file systems asynchronously, emitting objects containing file paths and fs.Stats for each discovered item (files, directories, symlinks).

3

4

## Package Information

5

6

- **Package Name**: klaw

7

- **Package Type**: npm

8

- **Language**: JavaScript

9

- **Installation**: `npm install klaw`

10

- **Minimum Node.js**: 14.14.0

11

12

## Core Imports

13

14

```javascript

15

const klaw = require('klaw');

16

```

17

18

For ES modules:

19

20

```javascript

21

import klaw from 'klaw';

22

```

23

24

## Basic Usage

25

26

```javascript

27

const klaw = require('klaw');

28

29

// Simple traversal collecting all paths

30

const items = [];

31

klaw('/some/directory')

32

.on('data', item => {

33

items.push(item.path);

34

console.log(item.path, item.stats.isDirectory() ? 'DIR' : 'FILE');

35

})

36

.on('end', () => console.log('Done!', items.length, 'items'));

37

38

// Using readable stream pattern

39

klaw('/some/directory')

40

.on('readable', function () {

41

let item;

42

while ((item = this.read())) {

43

// Process each item

44

console.log(item.path);

45

}

46

});

47

48

// Modern async iteration

49

for await (const item of klaw('/some/directory')) {

50

console.log(item.path, item.stats.size);

51

}

52

```

53

54

## Architecture

55

56

Klaw is built around a simple, focused architecture:

57

58

- **Walker Class**: Internal Readable stream that implements the recursive traversal logic

59

- **Factory Function**: Main exported function that creates Walker instances with configuration

60

- **Stream Interface**: Full Node.js Readable stream compatibility with object mode

61

- **Async Processing**: Non-blocking file system operations using Node.js fs callbacks

62

- **Configurable Strategy**: Pluggable traversal order, filtering, and depth control

63

64

## Capabilities

65

66

### File System Walking

67

68

Core functionality for recursively traversing directory structures and emitting file system items.

69

70

```javascript { .api }

71

/**

72

* Creates a file system walker that recursively traverses directories

73

* @param {string|URL} directory - Root directory to walk (string path or file URL)

74

* @param {WalkerOptions} [options] - Configuration options for traversal behavior

75

* @returns {Walker} Readable stream in object mode emitting file system items

76

*/

77

function klaw(directory, options);

78

79

interface WalkerOptions {

80

/** Method for processing directory contents: 'shift' (breadth-first) or 'pop' (depth-first) */

81

queueMethod?: 'shift' | 'pop';

82

/** Function to sort directory contents before processing */

83

pathSorter?: (a: string, b: string) => number;

84

/** Function to filter which paths to include in traversal */

85

filter?: (path: string) => boolean;

86

/** Maximum recursion depth (-1 for unlimited) */

87

depthLimit?: number;

88

/** Whether to follow symlinks (false) or treat as items (true) */

89

preserveSymlinks?: boolean;

90

/** Custom file system implementation (defaults to Node.js fs) */

91

fs?: FileSystemInterface;

92

/** Additional Readable stream options (objectMode is always true) */

93

[key: string]: any;

94

}

95

96

interface FileSystemInterface {

97

stat: (path: string, callback: (err: Error | null, stats: fs.Stats) => void) => void;

98

lstat: (path: string, callback: (err: Error | null, stats: fs.Stats) => void) => void;

99

readdir: (path: string, callback: (err: Error | null, files: string[]) => void) => void;

100

}

101

102

interface WalkerItem {

103

/** Full path to the file or directory */

104

path: string;

105

/** Node.js fs.Stats object containing file system metadata */

106

stats: fs.Stats;

107

}

108

```

109

110

**Stream Events:**

111

112

- **`data`**: Emitted for each file system item with WalkerItem object

113

- **`end`**: Emitted when traversal is complete

114

- **`error`**: Emitted on file system errors, receives (error, item) parameters

115

- **`readable`**: Standard Readable stream event for pull-based consumption

116

117

**Usage Examples:**

118

119

```javascript

120

const klaw = require('klaw');

121

const path = require('path');

122

123

// Basic traversal with data events

124

klaw('/home/user/documents')

125

.on('data', item => {

126

if (item.stats.isFile()) {

127

console.log('File:', item.path, 'Size:', item.stats.size);

128

}

129

})

130

.on('error', (err, item) => {

131

console.error('Error processing:', item.path, err.message);

132

})

133

.on('end', () => console.log('Traversal complete'));

134

135

// Filtering hidden files and directories

136

const filterFunc = item => {

137

const basename = path.basename(item);

138

return basename === '.' || basename[0] !== '.';

139

};

140

141

klaw('/some/directory', { filter: filterFunc })

142

.on('data', item => {

143

// Only non-hidden items reach here

144

console.log(item.path);

145

});

146

147

// Depth-limited traversal

148

klaw('/deep/directory', { depthLimit: 2 })

149

.on('data', item => {

150

console.log(item.path);

151

});

152

153

// Custom sorting (alphabetical)

154

klaw('/directory', {

155

pathSorter: (a, b) => a.localeCompare(b)

156

})

157

.on('data', item => {

158

console.log(item.path);

159

});

160

161

// File URL support

162

const { pathToFileURL } = require('url');

163

klaw(pathToFileURL('/some/directory'))

164

.on('data', item => {

165

console.log(item.path);

166

});

167

```

168

169

### Stream Processing Integration

170

171

Since klaw returns a standard Node.js Readable stream, it integrates seamlessly with stream processing libraries.

172

173

**Example with through2 for advanced filtering:**

174

175

```javascript

176

const klaw = require('klaw');

177

const through2 = require('through2');

178

const path = require('path');

179

180

// Filter to only include .js files

181

const jsFilesOnly = through2.obj(function (item, enc, next) {

182

if (!item.stats.isDirectory() && path.extname(item.path) === '.js') {

183

this.push(item);

184

}

185

next();

186

});

187

188

klaw('/project/src')

189

.pipe(jsFilesOnly)

190

.on('data', item => {

191

console.log('JavaScript file:', item.path);

192

});

193

194

// Aggregate file sizes by extension

195

let totalSizes = {};

196

const aggregateByExtension = through2.obj(function (item, enc, next) {

197

if (item.stats.isFile()) {

198

const ext = path.extname(item.path) || 'no-extension';

199

totalSizes[ext] = (totalSizes[ext] || 0) + item.stats.size;

200

}

201

this.push(item);

202

next();

203

});

204

205

klaw('/project')

206

.pipe(aggregateByExtension)

207

.on('end', () => {

208

console.log('File sizes by extension:', totalSizes);

209

});

210

```

211

212

### Error Handling

213

214

Klaw provides comprehensive error handling for file system operations.

215

216

```javascript { .api }

217

// Error event signature

218

walker.on('error', (error: Error, item: WalkerItem) => void);

219

```

220

221

**Error Handling Examples:**

222

223

```javascript

224

const klaw = require('klaw');

225

226

klaw('/some/directory')

227

.on('data', item => {

228

console.log(item.path);

229

})

230

.on('error', (err, item) => {

231

// Handle individual file/directory errors

232

console.error(`Error accessing ${item.path}:`, err.message);

233

234

// Common error types:

235

// - ENOENT: File or directory doesn't exist

236

// - EACCES: Permission denied

237

// - ENOTDIR: Expected directory but found file

238

})

239

.on('end', () => {

240

console.log('Traversal completed despite errors');

241

});

242

243

// Propagating errors through streams

244

const through2 = require('through2');

245

246

const transform = through2.obj(function (item, enc, next) {

247

// Process items

248

this.push(item);

249

next();

250

});

251

252

klaw('/directory')

253

.on('error', err => transform.emit('error', err)) // Forward errors

254

.pipe(transform)

255

.on('error', err => {

256

console.error('Stream error:', err.message);

257

});

258

```

259

260

### Advanced Configuration

261

262

Klaw supports advanced configuration options for customizing traversal behavior.

263

264

**Queue Method Configuration:**

265

266

```javascript

267

// Breadth-first traversal (default)

268

klaw('/directory', { queueMethod: 'shift' })

269

.on('data', item => console.log(item.path));

270

271

// Depth-first traversal

272

klaw('/directory', { queueMethod: 'pop' })

273

.on('data', item => console.log(item.path));

274

```

275

276

**Symlink Handling:**

277

278

```javascript

279

// Default: follow symlinks and traverse target

280

klaw('/directory', { preserveSymlinks: false })

281

.on('data', item => {

282

// item.path shows target path for symlinks

283

console.log(item.path);

284

});

285

286

// Treat symlinks as items themselves

287

klaw('/directory', { preserveSymlinks: true })

288

.on('data', item => {

289

if (item.stats.isSymbolicLink()) {

290

console.log('Symlink:', item.path);

291

}

292

});

293

```

294

295

**Custom File System:**

296

297

```javascript

298

// Using mock-fs for testing

299

const mockFs = require('mock-fs');

300

301

klaw('/virtual/directory', { fs: mockFs })

302

.on('data', item => {

303

console.log('Virtual file:', item.path);

304

});

305

```

306

307

## Types

308

309

```javascript { .api }

310

/**

311

* Walker class extends Node.js Readable stream

312

* Internal class, not directly exported

313

*/

314

class Walker extends Readable {

315

constructor(directory: string | URL, options?: WalkerOptions);

316

317

/** Standard Readable stream methods */

318

read(size?: number): WalkerItem | null;

319

pipe<T extends NodeJS.WritableStream>(destination: T, options?: object): T;

320

321

/** Event emitter methods for stream events */

322

on(event: 'data', listener: (item: WalkerItem) => void): this;

323

on(event: 'end', listener: () => void): this;

324

on(event: 'error', listener: (error: Error, item: WalkerItem) => void): this;

325

on(event: 'readable', listener: () => void): this;

326

}

327

```