@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/fsEnvironment-Specific Usage
The Diskette class export varies by environment:
- Node.js: Import from
@diskette/fs/node- provides a singletondiskinstance - 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 pathnodes: TreeNode<Content>[]- Root-level nodesfiles: FileNode<Content>[]- All files in the treedirectories: 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 nodeExamples
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
