# Localdrive



<Status level="stable" />

`Localdrive` exposes a local directory through an API that closely matches [Hyperdrive](/p2p/reference/building-blocks/hyperdrive). It is the simplest way to mirror between on-disk files and distributed drives with [Mirrordrive](/p2p/reference/helpers/mirrordrive). For upstream implementation details, see the [Localdrive repository](https://github.com/holepunchto/localdrive).

## Install [#install]

```sh
npm i localdrive
```

## Quickstart [#quickstart]

```js
import Localdrive from 'localdrive'

const drive = new Localdrive('./site')

await drive.put('/index.html', Buffer.from('<h1>Hello</h1>'))
const html = await drive.get('/index.html')

console.log(html?.toString())
console.log(await drive.entry('/index.html'))
```

## API Reference [#api-reference]

### Constructor and lifecycle [#constructor-and-lifecycle]

#### `new Localdrive(root, [options])` [#new-localdriveroot-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L11)

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

| Parameter | Type                                      | Default | Description            |
| --------- | ----------------------------------------- | ------- | ---------------------- |
| `root`    | `string`                                  | —       | —                      |
| `options` | [`LocaldriveOptions`](#localdriveoptions) | `{}`    | Configuration options. |

| Option        | Default | Description                                             |
| ------------- | ------- | ------------------------------------------------------- |
| `followLinks` | `false` | If enabled then `entry(key)` will follow the `linkname` |
| `metadata`    | —       | —                                                       |
| `atomic`      | `false` | Enable atomicity for file writing (tmp file and rename) |

#### `await drive.ready()` [#await-driveready]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L22)

Resolves immediately. It exists for compatibility with drive-like APIs such as [Hyperdrive](/p2p/reference/building-blocks/hyperdrive).

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves immediately.

```js
await drive.ready()
```

#### `await drive.close()` [#await-driveclose]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L25)

Resolves immediately. Localdrive does not keep a background storage process open.

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves immediately.

```js
await drive.close()
```

#### `await drive.flush()` [#await-driveflush]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L28)

Resolves immediately. It exists so code written for batched drive APIs can treat Localdrive as a drop-in target.

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves immediately.

```js
await drive.flush()
```

### Drive properties [#drive-properties]

#### `drive.root` [#driveroot]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L12)

String with the resolved (absolute) drive path.

* Returns: `string`

#### `drive.supportsMetadata` [#drivesupportsmetadata]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L14)

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

* Returns: `boolean`

### Compatibility helpers [#compatibility-helpers]

#### `drive.batch()` [#drivebatch]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L32)

Returns the same `Localdrive` instance. This lets batch-oriented code reuse a Localdrive target without branching.

* Returns: [`Localdrive`](/p2p/reference/helpers/localdrive) — This drive instance.

```js
const batch = drive.batch()
await batch.put('/file.txt', Buffer.from('hello'))
// on Localdrive, batch === drive
```

#### `drive.checkout()` [#drivecheckout]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L36)

Returns the same `Localdrive` instance. Unlike Hyperdrive, Localdrive does not expose historical versions.

* Returns: [`Localdrive`](/p2p/reference/helpers/localdrive) — This drive instance.

```js
const snapshot = drive.checkout()
// on Localdrive, snapshot === drive
```

#### `drive.toPath(key)` [#drivetopathkey]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L40)

Resolves a drive path such as `'/images/logo.png'` to its local filesystem path under `drive.root`.

| Parameter | Type     | Description                                            |
| --------- | -------- | ------------------------------------------------------ |
| `key`     | `string` | Drive key to convert (for example `/images/logo.png`). |

* Returns: `string` — Absolute filesystem path for the given key.

```js
const drive = new Localdrive('/srv/data')
drive.toPath('/images/logo.png') // => '/srv/data/images/logo.png'
```

### Reading and writing entries [#reading-and-writing-entries]

#### `await drive.entry(name, [options])` [#await-driveentryname-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L46)

Resolves with the entry stored at `key`, or `null` if no entry exists.

| Parameter | Type                            | Description                                     |
| --------- | ------------------------------- | ----------------------------------------------- |
| `name`    | `string`                        | Drive key to look up (for example `/file.txt`). |
| `options` | [`EntryOptions`](#entryoptions) | Entry lookup options.                           |

* Returns: [`Promise<object\|null>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — the entry at `name` path in the drive.

| Option   | Default | Description                             |
| -------- | ------- | --------------------------------------- |
| `follow` | `false` | Follow symlinks when resolving the key. |

#### `await drive.get(key, [options])` [#await-drivegetkey-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L139)

Reads the file at `key` and resolves with its contents as a `Buffer`, or `null` if no file exists (also `null` for symbolic links).

| Parameter | Type                        | Description                                              |
| --------- | --------------------------- | -------------------------------------------------------- |
| `key`     | `string`                    | Drive key of the file to read (for example `/blob.txt`). |
| `options` | [`GetOptions`](#getoptions) | `options` are the same as in `drive.entry` method.       |

* Returns: [`Promise<Buffer\|null>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — the blob at `key` path in the drive.

```js
const buffer = await drive.get('/blob.txt')
console.log(buffer.toString()) // => 'example'
```

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

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L151)

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

| Parameter | Type                                                                | Description                                                      |
| --------- | ------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `key`     | `string`                                                            | Drive key of the file to write (for example `/images/logo.png`). |
| `buffer`  | [`Buffer\|string`](https://nodejs.org/api/buffer.html#class-buffer) | Data to write.                                                   |
| `options` | [`WriteStreamOptions`](#writestreamoptions)                         | —                                                                |

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves when the file has been fully written and closed.

```js
await drive.put('/blob.txt', Buffer.from('example'))
await drive.put('/images/logo.png', Buffer.from('..'), { executable: false })
```

#### `await drive.del(key)` [#await-drivedelkey]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L166)

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

| Parameter | Type     | Description                                                           |
| --------- | -------- | --------------------------------------------------------------------- |
| `key`     | `string` | Drive key of the file to delete (for example `/images/old-logo.png`). |

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves when the file and any empty parent directories have been removed.

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

#### `await drive.symlink(key, linkname)` [#await-drivesymlinkkey-linkname]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L191)

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

| Parameter  | Type     | Description                                  |
| ---------- | -------- | -------------------------------------------- |
| `key`      | `string` | Drive key where the symlink will be created. |
| `linkname` | `string` | Target path the symlink should point to.     |

* Returns: [`Promise<void>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Resolves when the symlink entry has been created.

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

#### `await drive.exists(name)` [#await-driveexistsname]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L291)

Resolves to `true` when `drive.entry(key)` resolves to a non-null entry, otherwise `false`.

| Parameter | Type     | Description                                   |
| --------- | -------- | --------------------------------------------- |
| `name`    | `string` | Drive key to check (for example `/file.txt`). |

* Returns: [`Promise<boolean>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — Whether an entry exists at the given path.

```js
const found = await drive.exists('/blob.txt')
console.log(found) // => true or false
```

#### `drive.compare(entryA, entryB)` [#drivecompareentrya-entryb]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L214)

Compares two drive entries by modification time.

| Parameter | Type     | Description                                                   |
| --------- | -------- | ------------------------------------------------------------- |
| `entryA`  | `object` | First entry (must have an `mtime` property in milliseconds).  |
| `entryB`  | `object` | Second entry (must have an `mtime` property in milliseconds). |

* Returns: `number` — `1` if `entryA` is newer, `-1` if `entryB` is newer, and `0` if they are equal.

```js
const entryA = await drive.entry('/file-a.txt')
const entryB = await drive.entry('/file-b.txt')
const result = drive.compare(entryA, entryB)
// result: 0 (same), 1 (a is newer), or -1 (b is newer)
```

### Listing and mirroring [#listing-and-mirroring]

#### `drive.list([folder], [options])` [#drivelistfolder-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L219)

Returns a stream of entries for files under `folder` (defaults to the whole drive).

| Parameter | Type                          | Default | Description                                             |
| --------- | ----------------------------- | ------- | ------------------------------------------------------- |
| `folder`  | `string`                      | —       | Unix-style path prefix to list (for example `/images`). |
| `options` | [`ListOptions`](#listoptions) | `{}`    | Listing options.                                        |

* Returns: `AsyncIterable<object>` — a stream of all entries in the drive inside of specified `folder`.

#### `drive.readdir([folder])` [#drivereaddirfolder]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L256)

Returns an async iterator that yields the immediate child names (not
full paths) under `folder`. Only non-empty sub-directories and files with
a valid entry are included.

| Parameter | Type     | Description                                             |
| --------- | -------- | ------------------------------------------------------- |
| `folder`  | `string` | Unix-style path prefix to read (for example `/images`). |

* Returns: `AsyncIterable<string>` — a stream of all subpaths of entries in drive stored at paths prefixed by `folder`.

```js
for await (const name of drive.readdir('/images')) {
  console.log(name) // => 'logo.png', 'banner.jpg', ...
}
```

#### `drive.mirror(out, [options])` [#drivemirrorout-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L295)

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

| Parameter | Type                              | Description                                            |
| --------- | --------------------------------- | ------------------------------------------------------ |
| `out`     | `object`                          | Destination drive (must implement the same drive API). |
| `options` | [`MirrorOptions`](#mirroroptions) | Options forwarded to `MirrorDrive`.                    |

* Returns: [`MirrorDrive`](/p2p/reference/helpers/mirrordrive) — A MirrorDrive instance that runs the mirror operation.

```js
const src = new Localdrive('./source')
const dst = new Localdrive('./destination')
const mirror = src.mirror(dst)
await mirror.done()
```

### Stream APIs [#stream-apis]

#### `drive.createReadStream(key, [options])` [#drivecreatereadstreamkey-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L299)

Returns a readable stream of the file stored at `key`.

| Parameter | Type                                      | Description                                                |
| --------- | ----------------------------------------- | ---------------------------------------------------------- |
| `key`     | `string`                                  | Drive key of the file to stream (for example `/blob.txt`). |
| `options` | [`ReadStreamOptions`](#readstreamoptions) | Range options.                                             |

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

#### `drive.createWriteStream(key, [options])` [#drivecreatewritestreamkey-options]

[src](https://github.com/holepunchto/localdrive/blob/v2.2.1/index.js#L306)

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

| Parameter | Type                                        | Description                                               |
| --------- | ------------------------------------------- | --------------------------------------------------------- |
| `key`     | `string`                                    | Drive key of the file to write (for example `/blob.txt`). |
| `options` | [`WriteStreamOptions`](#writestreamoptions) | Write options.                                            |

* Returns: `FileWriteStream` — Writable stream targeting the given key.

## Types [#types]

### LocaldriveOptions [#localdriveoptions]

Options for creating a Localdrive instance.

| Property              | Type                                                                                                  | Default | Description                                                   |
| --------------------- | ----------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |
| `followLinks`         | `boolean`                                                                                             | `false` | If enabled, `entry(key)` follows the `linkname` for symlinks. |
| `followExternalLinks` | `boolean`                                                                                             | `false` | If enabled, symlinks pointing outside the root are followed.  |
| `metadata`            | [`object\|Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) | —       | Hook functions called when metadata is read/written/deleted.  |
| `metadata.get`        | `function`                                                                                            | —       | Called with `(key)` to retrieve metadata for a file.          |
| `metadata.put`        | `function`                                                                                            | —       | Called with `(key, value)` to store metadata for a file.      |
| `metadata.del`        | `function`                                                                                            | —       | Called with `(key)` to delete metadata for a file.            |
| `atomic`              | `boolean`                                                                                             | `false` | Enable atomic file writes (write to a tmp file then rename).  |

### EntryOptions [#entryoptions]

Options for `drive.entry()`.

| Property | Type      | Default | Description                                                         |
| -------- | --------- | ------- | ------------------------------------------------------------------- |
| `follow` | `boolean` | `false` | Follow symlinks (up to 15 levels, then throws `Recursive symlink`). |

### GetOptions [#getoptions]

Options for `drive.get()`.

| Property | Type      | Default | Description                             |
| -------- | --------- | ------- | --------------------------------------- |
| `follow` | `boolean` | `false` | Follow symlinks when resolving the key. |

### WriteStreamOptions [#writestreamoptions]

Options for `drive.put()` and `drive.createWriteStream()`.

| Property     | Type      | Default | Description                                            |
| ------------ | --------- | ------- | ------------------------------------------------------ |
| `executable` | `boolean` | `false` | Mark the written file as executable (chmod 0o755).     |
| `metadata`   | `*`       | —       | Arbitrary metadata value stored via the metadata hook. |

### ListOptions [#listoptions]

Options for `drive.list()`.

| Property | Type                                                                                                                        | Default | Description                                                                                                               |
| -------- | --------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| `ignore` | [`string\|Array<string>\|function`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) | —       | File/folder paths to exclude. May be a path string, an array of path strings, or a predicate function `(key) => boolean`. |

### ReadStreamOptions [#readstreamoptions]

Options for `drive.createReadStream()`.

| Property | Type     | Default | Description                                                               |
| -------- | -------- | ------- | ------------------------------------------------------------------------- |
| `start`  | `number` | `0`     | Byte offset to start reading from (inclusive).                            |
| `end`    | `number` | —       | Byte offset to stop reading at (inclusive). Ignored when `length` is set. |
| `length` | `number` | —       | Number of bytes to read. Overrides `end`.                                 |

### MirrorOptions [#mirroroptions]

Options for `drive.mirror()`.

| Property | Type       | Default | Description                                                                                  |
| -------- | ---------- | ------- | -------------------------------------------------------------------------------------------- |
| `dryRun` | `boolean`  | `false` | List differences without writing any changes.                                                |
| `prune`  | `boolean`  | `true`  | Remove files in the destination that are not in the source.                                  |
| `filter` | `function` | —       | Predicate `(key) => boolean` to include only matching entries.                               |
| `batch`  | `boolean`  | `false` | Use batched writes on a [Hyperdrive](/p2p/reference/building-blocks/hyperdrive) destination. |

## See also [#see-also]

* [Create a full peer-to-peer filesystem with Hyperdrive](/p2p/how-to/stream-and-share-media/create-a-full-peer-to-peer-filesystem-with-hyperdrive)—shows Localdrive mirroring in a full writer/reader flow.
* [Hyperdrive](/p2p/reference/building-blocks/hyperdrive)—the distributed filesystem API Localdrive is designed to interoperate with.
* [Mirrordrive](/p2p/reference/helpers/mirrordrive)—the sync engine that copies between Localdrive and Hyperdrive.
* [Drives](/p2p/reference/tools/drives)—CLI tool that mirrors between local directories and Hyperdrives using the same drive-like interface.
* [Upstream Localdrive repository](https://github.com/holepunchto/localdrive)—source, releases, and implementation details.
