# localdrive

> File system interoperable with Hyperdrive

Latest version **2.2.1** (published 2026-03-06) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install localdrive
pnpm add localdrive
yarn add localdrive
bun add localdrive
```

## Health

**Score 45/100 (D)** — status: stable.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

## Facts

| | |
|---|---|
| Version | 2.2.1 |
| Published | 2026-03-06 |
| First published | 2022-09-02 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 7 |
| Unpacked size | 31.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 38 |
| Author | Lucas Barrena |
| Maintainers | mafintosh |

## Links

- npm: https://www.npmjs.com/package/localdrive
- Repository: https://github.com/holepunchto/localdrive
- Issues: https://github.com/holepunchto/localdrive/issues
- npm.io page: https://npm.io/package/localdrive

## Dependencies (7)

- [b4a](https://npm.io/package/b4a.md) ^1.6.1
- [bare-fs](https://npm.io/package/bare-fs.md) ^4.0.1
- [streamx](https://npm.io/package/streamx.md) ^2.12.5
- [mutexify](https://npm.io/package/mutexify.md) ^1.4.0
- [bare-path](https://npm.io/package/bare-path.md) ^3.0.0
- [mirror-drive](https://npm.io/package/mirror-drive.md) ^1.2.0
- [unix-path-resolve](https://npm.io/package/unix-path-resolve.md) ^1.0.2

## Recent versions

- 2.2.1 (latest) — 2026-03-06
- 2.2.0 — 2025-04-16
- 2.1.0 — 2025-01-31
- 2.0.0 — 2024-12-31
- 1.12.2 — 2024-12-20
- 1.12.1 — 2024-10-15
- 1.12.0 — 2024-08-26
- 1.11.4 — 2024-02-09
- 1.11.3 — 2024-02-02
- 1.11.2 — 2024-02-02
- 1.11.1 — 2023-10-19
- 1.11.0 — 2023-08-17
- 1.10.0 — 2023-08-17
- 1.9.1 — 2023-08-09
- 1.9.0 — 2023-07-21
- … 16 more at https://npm.io/package/localdrive/versions

## README

# localdrive

File system API that is similar to Hyperdrive

```
npm i localdrive
```

## Usage

```js
const Localdrive = require('localdrive')

const drive = new Localdrive('./my-project')

await drive.put('/blob.txt', Buffer.from('example'))
await drive.put('/images/logo.png', Buffer.from('..'))
await drive.put('/images/old-logo.png', Buffer.from('..'))

const buffer = await drive.get('/blob.txt')
console.log(buffer) // => <Buffer ..> "example"

const entry = await drive.entry('/blob.txt')
console.log(entry) // => { key, value: { executable, linkname, blob, metadata } }

await drive.del('/images/old-logo.png')

await drive.symlink('/images/logo.shortcut', '/images/logo.png')

for await (const file of drive.list('/images')) {
  console.log('list', file) // => { key, value }
}

const rs = drive.createReadStream('/blob.txt')
for await (const chunk of rs) {
  console.log('rs', chunk) // => <Buffer ..>
}

const ws = drive.createWriteStream('/blob.txt')
ws.write('new example')
ws.end()
ws.once('close', () => console.log('file saved'))
```

## API

#### `const drive = new Localdrive(root, [options])`

Creates a drive based on a `root` directory. `root` can be relative or absolute.

Available `options`:

```js
{
  followLinks: false, // If enabled then `entry(key)` will follow the `linkname`
  metadata: { // Hook functions are called accordingly
    get (key) {},
    put (key) {},
    del (key) {}
  },
  atomic: false, // Enable atomicity for file writing (tmp file and rename)
  roots: {} // For mapping key prefixes to different roots
}
```

The metadata hook `del()` could be called with non-existing metadata keys.

#### `drive.root`

String with the resolved (absolute) drive path.

#### `drive.supportsMetadata`

Boolean that indicates if the drive handles or not metadata. Default `false`.

If you pass `opts.metadata` hooks then `supportsMetadata` becomes true.

#### `await drive.put(key, buffer, [options])`

Creates a file at `key` path in the drive. `options` are the same as in `createWriteStream`.

#### `const buffer = await drive.get(key, [options])`

Returns the blob at `key` path in the drive. If no blob exists, returns null.

It also returns null for symbolic links.

`options` are the same as in `drive.entry` method.

#### `const entry = await drive.entry(key, [options])`

Returns the entry at `key` path in the drive. It looks like this:

```js
{
  key: String,
  value: {
    executable: Boolean,
    linkname: null,
    blob: {
      byteOffset: Number,
      blockOffset: Number,
      blockLength: Number,
      byteLength: Number
    },
    metadata: null
  },
  mtime: Number
}
```

Available `options`:

```js
{
  follow: false // Follow symlinks, 16 max or throws an error
}
```

#### `await drive.del(key)`

Deletes the file at `key` path from the drive.

#### `await drive.symlink(key, linkname)`

Creates an entry in drive at `key` path that points to the entry at `linkname`.

If a blob entry currently exists at `key` path then it will get overwritten and `drive.get(key)` will return null, while `drive.entry(key)` will return the entry with symlink information.

#### `const comparison = drive.compare(entryA, entryB)`

Returns `0` if entries are the same, `1` if `entryA` is older, and `-1` if `entryB` is older.

#### `const iterator = drive.list([folder], [options])`

Returns a stream of all entries in the drive inside of specified `folder`.

Available `options`:

```js
{
  ignore: String || Array // Ignore file and folders by name.
}
```

#### `const iterator = drive.readdir([folder])`

Returns a stream of all subpaths of entries in drive stored at paths prefixed by `folder`.

#### `const mirror = drive.mirror(out, [options])`

Efficiently mirror this drive into another. Returns a [`MirrorDrive`](https://github.com/holepunchto/mirror-drive#api) instance constructed with `options`.

Call `await mirror.done()` to wait for the mirroring to finish.

#### `const rs = drive.createReadStream(key, [options])`

Returns a stream to read out the blob stored in the drive at `key` path.

Available `options`:

```js
{
  start: Number,
  end: Number,
  length: Number
}
```

`start` and `end` are inclusive.\
`length` overrides `end`, they're not meant to be used together.

#### `const ws = drive.createWriteStream(key, [options])`

Stream a blob into the drive at `key` path.

Available `options`:

```js
{
  executable: Boolean
}
```

## Examples

### Metadata hooks

Metadata backed by `Map`:

```js
const meta = new Map()
const metadata = {
  get: (key) => (meta.has(key) ? meta.get(key) : null),
  put: (key, value) => meta.set(key, value),
  del: (key) => meta.delete(key)
}

const drive = new Localdrive('./my-app', { metadata })

// ...
```

Note: `metadata.del()` will also be called when metadata is `null`:

```js
await drive.put('/file.txt', Buffer.from('a')) // Default metadata is null
```

## License

Apache-2.0

---
_Source: https://npm.io/package/localdrive · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
