or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md
tile.json

index.mddocs/

0

# Level

1

2

Level is a universal database abstraction layer that automatically selects the appropriate implementation based on the runtime environment. It provides a consistent API for creating lexicographically sorted key-value databases that work seamlessly across Node.js (using LevelDB) and browsers (using IndexedDB).

3

4

## Package Information

5

6

- **Package Name**: level

7

- **Package Type**: npm

8

- **Language**: JavaScript with TypeScript definitions

9

- **Installation**: `npm install level`

10

11

## Core Imports

12

13

```javascript

14

const { Level } = require('level');

15

```

16

17

For ES modules:

18

19

```javascript

20

import { Level } from 'level';

21

```

22

23

TypeScript with generics:

24

25

```typescript

26

import { Level } from 'level';

27

```

28

29

## Basic Usage

30

31

```javascript

32

const { Level } = require('level');

33

34

// Create a database

35

const db = new Level('example', { valueEncoding: 'json' });

36

37

// Add an entry with key 'a' and value 1

38

await db.put('a', 1);

39

40

// Add multiple entries

41

await db.batch([{ type: 'put', key: 'b', value: 2 }]);

42

43

// Get value of key 'a': 1

44

const value = await db.get('a');

45

46

// Iterate entries with keys that are greater than 'a'

47

for await (const [key, value] of db.iterator({ gt: 'a' })) {

48

console.log(value); // 2

49

}

50

```

51

52

TypeScript usage with generic type parameters:

53

54

```typescript

55

import { Level } from 'level';

56

57

// Specify types of keys and values (any, in the case of json).

58

// The generic type parameters default to Level<string, string>.

59

const db = new Level<string, any>('./db', { valueEncoding: 'json' });

60

61

// All relevant methods then use those types

62

await db.put('a', { x: 123 });

63

64

// Specify different types when overriding encoding per operation

65

await db.get<string, string>('a', { valueEncoding: 'utf8' });

66

67

// It works the same for sublevels

68

const abc = db.sublevel('abc');

69

const xyz = db.sublevel<string, any>('xyz', { valueEncoding: 'json' });

70

```

71

72

## Architecture

73

74

Level implements a unified interface that automatically chooses the appropriate backend:

75

76

- **Node.js Runtime**: Uses `classic-level` which provides LevelDB-based persistent storage

77

- **Browser Runtime**: Uses `browser-level` which provides IndexedDB-based storage

78

- **Unified API**: Both implementations extend `abstract-level` providing consistent methods

79

- **Type Safety**: Full TypeScript support with generic type parameters for keys and values

80

- **Encoding Support**: Multiple encoding options including JSON, UTF-8, and binary formats

81

82

The Level class extends `AbstractLevel<string | Buffer | Uint8Array, KDefault, VDefault>` and provides all the functionality from the abstract-level specification.

83

84

## Capabilities

85

86

### Database Constructor

87

88

Creates a new database instance or opens an existing one.

89

90

```typescript { .api }

91

/**

92

* Database constructor.

93

* @param location Directory path (relative or absolute) where LevelDB will store its

94

* files, or in browsers, the name of the IDBDatabase to be opened.

95

* @param options Options, of which some will be forwarded to open.

96

*/

97

constructor(location: string, options?: DatabaseOptions<KDefault, VDefault>);

98

99

type DatabaseOptions<K, V> = {

100

// Encoding options

101

keyEncoding?: string;

102

valueEncoding?: string;

103

104

// Database-specific options (varies by implementation)

105

createIfMissing?: boolean;

106

errorIfExists?: boolean;

107

compression?: boolean;

108

cacheSize?: number;

109

110

// Additional options from classic-level and browser-level

111

[key: string]: any;

112

};

113

```

114

115

### Database Properties

116

117

Access to database metadata and configuration.

118

119

```typescript { .api }

120

/**

121

* Location that was passed to the constructor.

122

*/

123

get location(): string;

124

```

125

126

### Database Lifecycle

127

128

Control database opening and closing.

129

130

```typescript { .api }

131

/**

132

* Open the database. Called automatically by other methods if not already open.

133

*/

134

open(): Promise<void>;

135

open(options: OpenOptions): Promise<void>;

136

137

/**

138

* Close the database. This is an async operation.

139

*/

140

close(): Promise<void>;

141

142

/**

143

* Database status property.

144

*/

145

get status(): string;

146

147

type OpenOptions = {

148

createIfMissing?: boolean;

149

errorIfExists?: boolean;

150

[key: string]: any;

151

};

152

```

153

154

### Single Value Operations

155

156

Store, retrieve, and delete individual key-value pairs.

157

158

```typescript { .api }

159

/**

160

* Get the value of a key from the database.

161

* @param key The key to retrieve

162

* @returns Promise resolving to the value

163

*/

164

get(key: KDefault): Promise<VDefault>;

165

get<K = KDefault, V = VDefault>(key: K, options: GetOptions<K, V>): Promise<V>;

166

167

/**

168

* Check if a key exists in the database.

169

* @param key The key to check

170

* @returns Promise resolving to boolean indicating existence

171

*/

172

has(key: KDefault): Promise<boolean>;

173

has<K = KDefault>(key: K, options: HasOptions<K>): Promise<boolean>;

174

175

/**

176

* Put a key-value pair to the database.

177

* @param key The key to store

178

* @param value The value to store

179

*/

180

put(key: KDefault, value: VDefault): Promise<void>;

181

put<K = KDefault, V = VDefault>(key: K, value: V, options: PutOptions<K, V>): Promise<void>;

182

183

/**

184

* Delete a key-value pair from the database.

185

* @param key The key to delete

186

*/

187

del(key: KDefault): Promise<void>;

188

del<K = KDefault>(key: K, options: DelOptions<K>): Promise<void>;

189

190

type GetOptions<K, V> = {

191

keyEncoding?: string;

192

valueEncoding?: string;

193

[key: string]: any;

194

};

195

196

type HasOptions<K> = {

197

keyEncoding?: string;

198

[key: string]: any;

199

};

200

201

type PutOptions<K, V> = {

202

keyEncoding?: string;

203

valueEncoding?: string;

204

[key: string]: any;

205

};

206

207

type DelOptions<K> = {

208

keyEncoding?: string;

209

[key: string]: any;

210

};

211

```

212

213

### Batch Operations

214

215

Retrieve multiple values or perform multiple operations atomically.

216

217

```typescript { .api }

218

/**

219

* Get the values of multiple keys from the database.

220

* @param keys Array of keys to retrieve

221

* @returns Promise resolving to array of values

222

*/

223

getMany(keys: KDefault[]): Promise<VDefault[]>;

224

getMany<K = KDefault, V = VDefault>(keys: K[], options: GetManyOptions<K, V>): Promise<V[]>;

225

226

/**

227

* Check if multiple keys exist in the database.

228

* @param keys Array of keys to check

229

* @returns Promise resolving to array of booleans indicating existence

230

*/

231

hasMany(keys: KDefault[]): Promise<boolean[]>;

232

hasMany<K = KDefault>(keys: K[], options: HasManyOptions<K>): Promise<boolean[]>;

233

234

/**

235

* Perform multiple operations atomically.

236

* @param operations Array of operations to perform

237

*/

238

batch(operations: Array<BatchOperation<typeof this, KDefault, VDefault>>): Promise<void>;

239

batch<K = KDefault, V = VDefault>(operations: Array<BatchOperation<typeof this, K, V>>, options: BatchOptions<K, V>): Promise<void>;

240

241

/**

242

* Create a chained batch for building multiple operations.

243

* @returns ChainedBatch instance for adding operations

244

*/

245

batch(): ChainedBatch<typeof this, KDefault, VDefault>;

246

247

type GetManyOptions<K, V> = {

248

keyEncoding?: string;

249

valueEncoding?: string;

250

[key: string]: any;

251

};

252

253

type HasManyOptions<K> = {

254

keyEncoding?: string;

255

[key: string]: any;

256

};

257

258

type BatchOptions<K, V> = {

259

keyEncoding?: string;

260

valueEncoding?: string;

261

[key: string]: any;

262

};

263

264

type BatchOperation<TDatabase, K, V> = {

265

type: 'put' | 'del';

266

key: K;

267

value?: V; // Required for 'put', ignored for 'del'

268

};

269

270

interface ChainedBatch<TDatabase, K, V> {

271

put(key: K, value: V): ChainedBatch<TDatabase, K, V>;

272

del(key: K): ChainedBatch<TDatabase, K, V>;

273

clear(): ChainedBatch<TDatabase, K, V>;

274

write(): Promise<void>;

275

close(): Promise<void>;

276

}

277

```

278

279

### Sublevel Operations

280

281

Create isolated database sections that share the same underlying storage but have separate key spaces.

282

283

```typescript { .api }

284

/**

285

* Create a sublevel that acts like a separate database with its own key space.

286

* @param name Sublevel name/prefix

287

* @param options Optional configuration for the sublevel

288

* @returns New Level instance scoped to the sublevel

289

*/

290

sublevel<SK = KDefault, SV = VDefault>(name: string, options?: DatabaseOptions<SK, SV>): Level<SK, SV>;

291

```

292

293

### Iterator Operations

294

295

Create iterators for traversing database entries with range queries and filtering.

296

297

```typescript { .api }

298

/**

299

* Create an iterator for key-value pairs.

300

* @param options Iterator configuration options

301

* @returns Iterator instance

302

*/

303

iterator(): Iterator<typeof this, KDefault, VDefault>;

304

iterator<K = KDefault, V = VDefault>(options: IteratorOptions<K, V>): Iterator<typeof this, K, V>;

305

306

/**

307

* Create an iterator for keys only.

308

* @param options Iterator configuration options

309

* @returns KeyIterator instance

310

*/

311

keys(): KeyIterator<typeof this, KDefault>;

312

keys<K = KDefault>(options: KeyIteratorOptions<K>): KeyIterator<typeof this, K>;

313

314

/**

315

* Create an iterator for values only.

316

* @param options Iterator configuration options

317

* @returns ValueIterator instance

318

*/

319

values(): ValueIterator<typeof this, KDefault, VDefault>;

320

values<K = KDefault, V = VDefault>(options: ValueIteratorOptions<K, V>): ValueIterator<typeof this, K, V>;

321

322

type IteratorOptions<K, V> = {

323

gt?: K; // Greater than

324

gte?: K; // Greater than or equal

325

lt?: K; // Less than

326

lte?: K; // Less than or equal

327

reverse?: boolean;

328

limit?: number;

329

keyEncoding?: string;

330

valueEncoding?: string;

331

[key: string]: any;

332

};

333

334

type KeyIteratorOptions<K> = {

335

gt?: K;

336

gte?: K;

337

lt?: K;

338

lte?: K;

339

reverse?: boolean;

340

limit?: number;

341

keyEncoding?: string;

342

[key: string]: any;

343

};

344

345

type ValueIteratorOptions<K, V> = {

346

gt?: K;

347

gte?: K;

348

lt?: K;

349

lte?: K;

350

reverse?: boolean;

351

limit?: number;

352

keyEncoding?: string;

353

valueEncoding?: string;

354

[key: string]: any;

355

};

356

357

interface Iterator<TDatabase, K, V> {

358

next(): Promise<[K, V] | undefined>;

359

all(): Promise<Array<[K, V]>>;

360

close(): Promise<void>;

361

[Symbol.asyncIterator](): AsyncIterableIterator<[K, V]>;

362

}

363

364

interface KeyIterator<TDatabase, K> {

365

next(): Promise<K | undefined>;

366

all(): Promise<K[]>;

367

close(): Promise<void>;

368

[Symbol.asyncIterator](): AsyncIterableIterator<K>;

369

}

370

371

interface ValueIterator<TDatabase, K, V> {

372

next(): Promise<V | undefined>;

373

all(): Promise<V[]>;

374

close(): Promise<void>;

375

[Symbol.asyncIterator](): AsyncIterableIterator<V>;

376

}

377

```

378

379

### Clear Operations

380

381

Delete all entries or a range of entries from the database.

382

383

```typescript { .api }

384

/**

385

* Delete all entries or a range of entries from the database.

386

* @param options Range and encoding options

387

*/

388

clear(): Promise<void>;

389

clear<K = KDefault>(options: ClearOptions<K>): Promise<void>;

390

391

type ClearOptions<K> = {

392

gt?: K; // Greater than

393

gte?: K; // Greater than or equal

394

lt?: K; // Less than

395

lte?: K; // Less than or equal

396

reverse?: boolean;

397

limit?: number;

398

keyEncoding?: string;

399

[key: string]: any;

400

};

401

```

402

403

### Resource Management

404

405

Attach and detach resources that should be managed with the database lifecycle.

406

407

```typescript { .api }

408

/**

409

* Attach a resource to be managed by the database lifecycle.

410

* @param resource Resource to attach (must have close method)

411

*/

412

attachResource(resource: any): void;

413

414

/**

415

* Detach a previously attached resource.

416

* @param resource Resource to detach

417

*/

418

detachResource(resource: any): void;

419

```

420

421

### Feature Detection

422

423

Access to database capabilities and supported features.

424

425

```typescript { .api }

426

/**

427

* Database features and capabilities.

428

*/

429

get supports(): {

430

[key: string]: boolean;

431

};

432

```

433

434

### Encoding Utilities

435

436

Utility methods for working with encodings.

437

438

```typescript { .api }

439

/**

440

* Get or normalize key encoding.

441

* @param encoding Encoding name or options

442

* @returns Normalized encoding

443

*/

444

keyEncoding(): any;

445

keyEncoding(encoding: string | any): any;

446

447

/**

448

* Get or normalize value encoding.

449

* @param encoding Encoding name or options

450

* @returns Normalized encoding

451

*/

452

valueEncoding(): any;

453

valueEncoding(encoding: string | any): any;

454

```

455

456

### Advanced Operations

457

458

Advanced database operations and deferred execution.

459

460

```typescript { .api }

461

/**

462

* Defer function execution until database is in the correct state.

463

* @param fn Function to defer

464

* @param options Defer options

465

*/

466

defer(fn: () => void): void;

467

defer(fn: () => void, options: DeferOptions): void;

468

469

type DeferOptions = {

470

[key: string]: any;

471

};

472

```

473

474

### Event System

475

476

The Level class extends EventEmitter and emits various events during database operations.

477

478

```typescript { .api }

479

/**

480

* Add event listener for database events.

481

* @param event Event name

482

* @param listener Event handler function

483

*/

484

on(event: 'open' | 'opening' | 'close' | 'closing' | 'put' | 'del' | 'batch' | 'clear', listener: (...args: any[]) => void): this;

485

486

/**

487

* Remove event listener.

488

* @param event Event name

489

* @param listener Event handler function

490

*/

491

off(event: 'open' | 'opening' | 'close' | 'closing' | 'put' | 'del' | 'batch' | 'clear', listener: (...args: any[]) => void): this;

492

493

/**

494

* Add one-time event listener.

495

* @param event Event name

496

* @param listener Event handler function

497

*/

498

once(event: 'open' | 'opening' | 'close' | 'closing' | 'put' | 'del' | 'batch' | 'clear', listener: (...args: any[]) => void): this;

499

500

/**

501

* Emit an event.

502

* @param event Event name

503

* @param args Event arguments

504

*/

505

emit(event: string, ...args: any[]): boolean;

506

```

507

508

## Usage Examples

509

510

### JSON Encoding

511

512

```javascript

513

const db = new Level('my-db', { valueEncoding: 'json' });

514

515

await db.put('user:1', { name: 'Alice', age: 30 });

516

const user = await db.get('user:1'); // { name: 'Alice', age: 30 }

517

```

518

519

### Batch Operations

520

521

```javascript

522

// Atomic batch operations

523

await db.batch([

524

{ type: 'put', key: 'user:1', value: { name: 'Alice' } },

525

{ type: 'put', key: 'user:2', value: { name: 'Bob' } },

526

{ type: 'del', key: 'user:3' }

527

]);

528

529

// Chained batch operations

530

const batch = db.batch();

531

batch.put('key1', 'value1');

532

batch.put('key2', 'value2');

533

batch.del('key3');

534

await batch.write();

535

```

536

537

### Range Queries

538

539

```javascript

540

// Iterate over a range of keys

541

for await (const [key, value] of db.iterator({ gte: 'user:1', lt: 'user:9' })) {

542

console.log(`${key}: ${JSON.stringify(value)}`);

543

}

544

545

// Get all keys starting with 'user:'

546

const userKeys = await db.keys({ gte: 'user:', lt: 'user;\xFF' }).all();

547

548

// Get values in reverse order

549

const recentValues = await db.values({ reverse: true, limit: 10 }).all();

550

```

551

552

### TypeScript with Generics

553

554

```typescript

555

interface User {

556

name: string;

557

email: string;

558

age: number;

559

}

560

561

// Create typed database

562

const userDb = new Level<string, User>('users', { valueEncoding: 'json' });

563

564

// Type-safe operations

565

await userDb.put('alice', { name: 'Alice', email: 'alice@example.com', age: 30 });

566

const alice: User = await userDb.get('alice');

567

568

// Override types for specific operations

569

const rawData = await userDb.get<string, string>('alice', { valueEncoding: 'utf8' });

570

```

571

572

### Sublevel Usage

573

574

```javascript

575

const db = new Level('my-db', { valueEncoding: 'json' });

576

577

// Create sublevels for different data types

578

const users = db.sublevel('users');

579

const posts = db.sublevel('posts');

580

581

// Each sublevel acts like a separate database

582

await users.put('alice', { name: 'Alice', age: 30 });

583

await posts.put('post1', { title: 'Hello World', author: 'alice' });

584

585

// TypeScript with sublevel typing

586

const typedUsers = db.sublevel<string, User>('users', { valueEncoding: 'json' });

587

```

588

589

### Key Existence Checking

590

591

```javascript

592

// Check if a single key exists

593

const exists = await db.has('user:1');

594

console.log(exists); // true or false

595

596

// Check multiple keys at once

597

const keysExist = await db.hasMany(['user:1', 'user:2', 'user:3']);

598

console.log(keysExist); // [true, false, true]

599

```

600

601

### Clear Operations

602

603

```javascript

604

// Clear all entries

605

await db.clear();

606

607

// Clear a range of entries

608

await db.clear({ gte: 'user:', lt: 'user;\xFF' });

609

610

// Clear with limit

611

await db.clear({ limit: 100 });

612

```

613

614

### Event Handling

615

616

```javascript

617

const db = new Level('my-db', { valueEncoding: 'json' });

618

619

// Listen for database events

620

db.on('open', () => console.log('Database opened'));

621

db.on('put', (key, value) => console.log(`Put ${key}: ${JSON.stringify(value)}`));

622

db.on('del', (key) => console.log(`Deleted ${key}`));

623

624

// One-time listeners

625

db.once('close', () => console.log('Database closed'));

626

627

// Operations will emit events

628

await db.put('test', { data: 'example' }); // Emits 'put' event

629

await db.del('test'); // Emits 'del' event

630

await db.close(); // Emits 'close' event

631

```

632

633

### Resource Management

634

635

```javascript

636

const db = new Level('my-db');

637

638

// Create a resource that needs cleanup

639

const customResource = {

640

close: async () => console.log('Custom resource closed')

641

};

642

643

// Attach resource to database lifecycle

644

db.attachResource(customResource);

645

646

// When database closes, attached resources are also closed

647

await db.close(); // Also closes customResource

648

```

649

650

## Error Handling

651

652

Level operations may throw various errors:

653

654

- **NotFoundError**: Thrown by `get()` when a key doesn't exist

655

- **OpenError**: Thrown when database cannot be opened

656

- **WriteError**: Thrown when write operations fail

657

- **IteratorError**: Thrown during iterator operations

658

659

```javascript

660

try {

661

const value = await db.get('nonexistent-key');

662

} catch (error) {

663

if (error.code === 'LEVEL_NOT_FOUND') {

664

console.log('Key not found');

665

}

666

}

667

```

668

669

## Environment Compatibility

670

671

- **Node.js**: 18+ with native LevelDB bindings

672

- **Browsers**: Modern browsers with IndexedDB support (Chrome, Firefox, Safari, Edge)

673

- **Electron**: 30+ with both Node.js and browser contexts

674

- **Platform Support**: Linux, macOS, Windows, including ARM platforms

675

- **Key/Value Types**: string, Buffer, Uint8Array for keys; any serializable type for values