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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@diskette/fs

v0.17.0

Published

A TypeScript library that provides convenient, high-level filesystem operations with an emphasis on implementing intuitive APIs.

Readme

@diskette/fs

A TypeScript library that provides convenient, high-level filesystem operations with an emphasis on implementing intuitive APIs.

Installation

npm install @diskette/fs

Environment-Specific Usage

The Diskette class export varies by environment:

  • Node.js: Import from @diskette/fs/node - provides a singleton disk instance
  • Browser/Testing: Import from @diskette/fs/memory - provides in-memory filesystem
  • Main export: Import from @diskette/fs - exports types and core classes
// Node.js
import { disk } from '@diskette/fs/node'

// Browser/Testing
import { Diskette } from '@diskette/fs/memory'

// Types and utilities
import { Directory, Path, TreeNode } from '@diskette/fs'
import { isFileNode, isDirectoryNode } from '@diskette/fs/is'

Core API

Diskette Class

The main class for filesystem operations.

File Operations

read<T>(filePath: string, options?: { type?: T }): Promise<FileContent<T>>

Read file contents with support for different content types.

// Read as text (default). Typed as `string`
const text = await disk.read('/path/to/file.txt')

// Read as JSON. Typed as `JsonValue`
const data = await disk.read('/path/to/data.json', { type: 'json' })

// Read as bytes. Typed as `Uint8Array`
const bytes = await disk.read('/path/to/image.png', { type: 'bytes' })

// Read as base64. Typed as `string`
const base64 = await disk.read('/path/to/file.pdf', { type: 'base64' })
write(filePath: string, contents: string | ArrayBuffer | ArrayBufferView): Promise<void>

Write content to a file.

await disk.write('/path/to/file.txt', 'Hello, world!')
await disk.write('/path/to/data.json', JSON.stringify({ key: 'value' }))
copy(source: string, destination: string): Promise<void>

Copy files or directories recursively.

await disk.copy('/source/file.txt', '/dest/file.txt')
await disk.copy('/source/directory', '/dest/directory')
move(source: string, destination: string): Promise<void>

Move files or directories.

await disk.move('/old/path.txt', '/new/path.txt')
delete(path: string): Promise<boolean>

Delete files or directories recursively.

const success = await disk.delete('/path/to/remove')

Directory Operations

directory<Content>(dirPath: string, options?: ContentOptions<Content>): Promise<Directory<Content>>

Get a Directory instance for advanced tree operations.

const dir = await disk.directory('/project')

// Get all files
const files = dir.files

// Get all directories
const directories = dir.directories

// Find specific files
const readmeFile = dir.find((node) => node.name === 'README.md')
const jsFiles = dir.filter((node) => node.ext === '.js')
walk<Content>(dirPath: string, options?: ContentOptions<Content>): AsyncIterable<[string, TreeNode<Content>]>

Asynchronously walk through directory tree.

for await (const [fullPath, node] of disk.walk('/project')) {
  console.log(`${node.type}: ${fullPath}`)

  if (node.type === 'file') {
    console.log(`Size: ${node.size} bytes`)
  }
}
find(path: string, predicate?: (node: TreeNode<string>, fullPath: string) => boolean): Promise<TreeNode<string> | undefined>

Find a specific node in the directory tree.

// Find by exact path
const node = await disk.find('/project/src/index.ts')

// Find with custom predicate
const largeFile = await disk.find(
  '/project',
  (node) => node.type === 'file' && node.size > 1000000,
)

Utility Methods

isFile(filePath: string | URL): Promise<boolean>

Check if path is a file.

isDirectory(filePath: string | URL): Promise<boolean>

Check if path is a directory.

Directory Class

Collection-like interface for working with directory trees.

Properties

  • path: string - The directory path
  • nodes: TreeNode<Content>[] - Root-level nodes
  • files: FileNode<Content>[] - All files in the tree
  • directories: DirectoryNode<Content>[] - All directories in the tree

Methods

find<T>(predicate: Predicate<Content, T>): T | undefined

Find the first node matching the predicate.

const packageJson = dir.find(
  (node) => node.type === 'file' && node.name === 'package.json',
)
get(path: string, options?: { ext?: string[] }): TreeNode<Content> | undefined

Get node by path, optionally filtering by extension.

const node = dir.get('src/index.ts')
const jsFile = dir.get('src/main', { ext: ['.js', '.ts'] })
has(path: string, options?: { ext?: string[] }): boolean

Check if node exists at path.

filter<T>(predicate: Predicate<Content, T>): T[]

Filter all nodes by predicate.

const typeScriptFiles = dir.filter(
  (node) => node.type === 'file' && node.ext === '.ts',
)
select<T, U>(predicate: Predicate<Content, T>, mapper: (node: T) => U): U[]

Filter and map in a single traversal.

const fileSizes = dir.select(
  (node) => node.type === 'file',
  (node) => ({ name: node.name, size: node.size }),
)

Memory Filesystem

For browser environments and testing, a memory-based implementation can be used:

import { Diskette } from '@diskette/fs/memory'

const memFs = new Diskette()

// Mount a tree structure
await memFs.mount({
  'package.json': '{"name": "my-project"}',
  src: {
    'index.ts': 'export * from "./lib"',
    lib: {
      'utils.ts': 'export const add = (a, b) => a + b',
    },
  },
})

// Or mount from TreeNode array
await memFs.mount([
  {
    type: 'file',
    name: 'README.md',
    path: 'README.md',
    content: '# My Project',
    // ... other file properties
  },
])

Content Transformation

Transform file contents during directory operations:

const dir = await disk.directory('/project', {
  content: async (fileNode) => {
    if (fileNode.ext === '.json') {
      return JSON.parse(fileNode.content)
    }
    return fileNode.content.toUpperCase()
  },
})

Type Guards and Assertions

import { isFileNode, isDirectoryNode, assertFileNode } from '@diskette/fs/is'

for (const node of dir) {
  if (isFileNode(node)) {
    console.log(`File: ${node.name} (${node.size} bytes)`)
  } else if (isDirectoryNode(node)) {
    console.log(`Directory: ${node.name} (${node.children.length} items)`)
  }
}

// Assertions
assertFileNode(node) // Throws if not a file node

Examples

Basic File Operations

import { disk } from '@diskette/fs/node'

// Read and write files
const config = await disk.read('config.json', { type: 'json' })
await disk.write('output.txt', 'Generated content')

// Copy project template
await disk.copy('templates/react-app', 'my-new-app')

Directory Analysis

const projectDir = await disk.directory('./src')

// Find all TypeScript files
const tsFiles = projectDir.filter(
  (node) => node.type === 'file' && node.ext === '.ts',
)

// Calculate total size
const totalSize = projectDir.files.reduce((sum, file) => sum + file.size, 0)

// Find large files
const largeFiles = projectDir.filter(
  (node) => node.type === 'file' && node.size > 100000,
)

Content Processing

// Process markdown files
const docsDir = await disk.directory('./docs', {
  content: async (fileNode) => {
    if (fileNode.ext === '.md') {
      // Transform markdown to HTML or extract metadata
      return processMarkdown(fileNode.content)
    }
    return fileNode.content
  },
  include: (entry) => entry.name.endsWith('.md'), // or `['**/*.md]`
})

License

MIT