or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-querying.mdcollection-operations.mddatabase-management.mddynamic-views.mdindex.mdpersistence-adapters.md

persistence-adapters.mddocs/

0

# Persistence Adapters

1

2

Storage backends for different environments including file system, localStorage, IndexedDB, and custom adapters. Adapters provide pluggable persistence for LokiJS databases across various platforms.

3

4

## Capabilities

5

6

### Adapter Interface

7

8

All persistence adapters implement a common interface for loading and saving databases.

9

10

```javascript { .api }

11

/**

12

* Standard persistence adapter interface

13

*/

14

interface PersistenceAdapter {

15

/**

16

* Load database from storage

17

* @param dbname - Database name/identifier

18

* @param callback - Completion callback (err, data)

19

*/

20

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

21

22

/**

23

* Save database to storage

24

* @param dbname - Database name/identifier

25

* @param dbref - Database reference or serialized data

26

* @param callback - Completion callback (err)

27

*/

28

saveDatabase(dbname: string, dbref: object | string, callback: (err?: Error) => void): void;

29

30

/**

31

* Delete database from storage (optional)

32

* @param dbname - Database name/identifier

33

* @param callback - Completion callback (err)

34

*/

35

deleteDatabase?(dbname: string, callback: (err?: Error) => void): void;

36

}

37

```

38

39

### Built-in Adapters

40

41

LokiJS includes several built-in adapters for common environments.

42

43

#### LokiMemoryAdapter

44

45

In-memory adapter for temporary storage or testing purposes.

46

47

```javascript { .api }

48

/**

49

* In-memory persistence adapter

50

* @param options - Adapter options

51

*/

52

constructor LokiMemoryAdapter(options?: object);

53

54

/**

55

* Load database from memory

56

* @param dbname - Database name

57

* @param callback - Completion callback

58

*/

59

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

60

61

/**

62

* Save database to memory

63

* @param dbname - Database name

64

* @param dbref - Database data

65

* @param callback - Completion callback

66

*/

67

saveDatabase(dbname: string, dbref: string, callback: (err?: Error) => void): void;

68

```

69

70

**Usage Examples:**

71

72

```javascript

73

// Create database with memory adapter

74

const memoryAdapter = new loki.LokiMemoryAdapter();

75

const db = new loki('memory.db', {

76

adapter: memoryAdapter

77

});

78

79

// Data persists only in memory during session

80

db.saveDatabase(); // Saves to memory

81

db.loadDatabase(); // Loads from memory

82

```

83

84

#### LokiLocalStorageAdapter

85

86

Browser localStorage adapter for client-side persistence.

87

88

```javascript { .api }

89

/**

90

* LocalStorage persistence adapter (browser only)

91

*/

92

constructor LokiLocalStorageAdapter();

93

94

/**

95

* Load database from localStorage

96

* @param dbname - Database name (used as localStorage key)

97

* @param callback - Completion callback

98

*/

99

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

100

101

/**

102

* Save database to localStorage

103

* @param dbname - Database name (used as localStorage key)

104

* @param dbref - Database serialized data

105

* @param callback - Completion callback

106

*/

107

saveDatabase(dbname: string, dbref: string, callback: (err?: Error) => void): void;

108

```

109

110

**Usage Examples:**

111

112

```javascript

113

// Browser environment only

114

const localStorageAdapter = new loki.LokiLocalStorageAdapter();

115

const db = new loki('app.db', {

116

adapter: localStorageAdapter,

117

autosave: true,

118

autosaveInterval: 4000

119

});

120

121

// Data persists in browser localStorage

122

db.loadDatabase();

123

```

124

125

#### LokiFsAdapter

126

127

Node.js file system adapter for server-side file persistence.

128

129

```javascript { .api }

130

/**

131

* File system persistence adapter (Node.js only)

132

*/

133

constructor LokiFsAdapter();

134

135

/**

136

* Load database from file

137

* @param dbname - Database filename

138

* @param callback - Completion callback

139

*/

140

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

141

142

/**

143

* Save database to file

144

* @param dbname - Database filename

145

* @param dbref - Database serialized data

146

* @param callback - Completion callback

147

*/

148

saveDatabase(dbname: string, dbref: string, callback: (err?: Error) => void): void;

149

```

150

151

**Usage Examples:**

152

153

```javascript

154

// Node.js environment only

155

const fsAdapter = new loki.LokiFsAdapter();

156

const db = new loki('data/app.db', {

157

adapter: fsAdapter,

158

autosave: true,

159

autosaveInterval: 10000

160

});

161

162

// Data persists to filesystem

163

db.loadDatabase(() => {

164

console.log('Database loaded from file');

165

});

166

```

167

168

#### LokiPartitioningAdapter

169

170

Wrapper adapter that partitions large databases across multiple storage operations.

171

172

```javascript { .api }

173

/**

174

* Partitioning adapter wrapper

175

* @param adapter - Underlying adapter to wrap

176

* @param options - Partitioning options

177

*/

178

constructor LokiPartitioningAdapter(adapter: PersistenceAdapter, options?: PartitioningOptions);

179

180

interface PartitioningOptions {

181

/** Partition key function */

182

paging?: boolean;

183

/** Partition size in bytes */

184

pageSize?: number;

185

/** Page delimiter */

186

delimiter?: string;

187

}

188

189

/**

190

* Load partitioned database

191

* @param dbname - Database name

192

* @param callback - Completion callback

193

*/

194

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

195

196

/**

197

* Save partitioned database

198

* @param dbname - Database name

199

* @param dbref - Database data

200

* @param callback - Completion callback

201

*/

202

saveDatabase(dbname: string, dbref: string, callback: (err?: Error) => void): void;

203

```

204

205

**Usage Examples:**

206

207

```javascript

208

// Wrap file system adapter with partitioning

209

const fsAdapter = new loki.LokiFsAdapter();

210

const partitioningAdapter = new loki.LokiPartitioningAdapter(fsAdapter, {

211

paging: true,

212

pageSize: 25 * 1024 * 1024 // 25MB partitions

213

});

214

215

const db = new loki('large-app.db', {

216

adapter: partitioningAdapter

217

});

218

219

// Large databases are automatically split across multiple files

220

db.saveDatabase();

221

```

222

223

### External Adapters

224

225

Additional adapters are available as separate files for specialized storage needs.

226

227

#### LokiIndexedAdapter

228

229

IndexedDB adapter for advanced browser storage with better performance and storage limits.

230

231

```javascript { .api }

232

/**

233

* IndexedDB persistence adapter (browser only)

234

* @param appname - Application name for IndexedDB

235

* @param options - Adapter options

236

*/

237

constructor LokiIndexedAdapter(appname: string, options?: IndexedAdapterOptions);

238

239

interface IndexedAdapterOptions {

240

/** Serialize method */

241

serializeMethod?: string;

242

/** Inflate method */

243

inflate?: Function;

244

/** Deflate method */

245

deflate?: Function;

246

}

247

248

/**

249

* Load database from IndexedDB

250

* @param dbname - Database name

251

* @param callback - Completion callback

252

*/

253

loadDatabase(dbname: string, callback: (err?: Error, data?: string) => void): void;

254

255

/**

256

* Save database to IndexedDB

257

* @param dbname - Database name

258

* @param dbstring - Serialized database data

259

* @param callback - Completion callback

260

*/

261

saveDatabase(dbname: string, dbstring: string, callback: (err?: Error) => void): void;

262

263

/**

264

* Delete database from IndexedDB

265

* @param dbname - Database name

266

* @param callback - Completion callback

267

*/

268

deleteDatabase(dbname: string, callback: (err?: Error) => void): void;

269

270

/**

271

* Get list of databases in IndexedDB

272

* @param callback - Completion callback with database list

273

*/

274

getDatabaseList(callback: (err?: Error, databases?: string[]) => void): void;

275

```

276

277

**Usage Examples:**

278

279

```javascript

280

// Include the indexed adapter script

281

const indexedAdapter = new LokiIndexedAdapter('MyApp');

282

const db = new loki('app.db', {

283

adapter: indexedAdapter

284

});

285

286

// Provides better performance than localStorage

287

db.loadDatabase(() => {

288

console.log('Loaded from IndexedDB');

289

});

290

291

// List all databases

292

indexedAdapter.getDatabaseList((err, databases) => {

293

console.log('Available databases:', databases);

294

});

295

```

296

297

### Custom Adapter Development

298

299

Create custom adapters by implementing the PersistenceAdapter interface.

300

301

```javascript { .api }

302

/**

303

* Custom adapter implementation example

304

*/

305

function CustomAdapter(options) {

306

this.options = options || {};

307

}

308

309

CustomAdapter.prototype.loadDatabase = function(dbname, callback) {

310

// Implement custom load logic

311

// Call callback(error, data) when complete

312

};

313

314

CustomAdapter.prototype.saveDatabase = function(dbname, dbref, callback) {

315

// Implement custom save logic

316

// Call callback(error) when complete

317

};

318

319

// Optional delete method

320

CustomAdapter.prototype.deleteDatabase = function(dbname, callback) {

321

// Implement custom delete logic

322

// Call callback(error) when complete

323

};

324

```

325

326

**Usage Examples:**

327

328

```javascript

329

// REST API adapter example

330

function RestAdapter(baseUrl) {

331

this.baseUrl = baseUrl;

332

}

333

334

RestAdapter.prototype.loadDatabase = function(dbname, callback) {

335

fetch(`${this.baseUrl}/databases/${dbname}`)

336

.then(response => response.text())

337

.then(data => callback(null, data))

338

.catch(err => callback(err));

339

};

340

341

RestAdapter.prototype.saveDatabase = function(dbname, dbref, callback) {

342

fetch(`${this.baseUrl}/databases/${dbname}`, {

343

method: 'POST',

344

body: dbref,

345

headers: { 'Content-Type': 'application/json' }

346

})

347

.then(() => callback())

348

.catch(err => callback(err));

349

};

350

351

// Use custom adapter

352

const restAdapter = new RestAdapter('https://api.example.com');

353

const db = new loki('remote.db', {

354

adapter: restAdapter

355

});

356

```

357

358

### Adapter Configuration

359

360

Configure database to use specific adapters with options.

361

362

```javascript { .api }

363

/**

364

* Database adapter configuration

365

*/

366

interface DatabaseOptions {

367

/** Persistence adapter instance */

368

adapter?: PersistenceAdapter;

369

/** Persistence method name (deprecated, use adapter) */

370

persistenceMethod?: string;

371

/** Adapter-specific options */

372

adapterOptions?: object;

373

}

374

```

375

376

**Usage Examples:**

377

378

```javascript

379

// Configure adapter at database creation

380

const db = new loki('app.db', {

381

adapter: new loki.LokiFsAdapter(),

382

autosave: true,

383

autosaveInterval: 5000

384

});

385

386

// Change adapter after creation

387

db.persistenceAdapter = new loki.LokiMemoryAdapter();

388

389

// Check current adapter

390

console.log('Using adapter:', db.persistenceAdapter.constructor.name);

391

```

392

393

### Error Handling

394

395

Proper error handling with persistence operations.

396

397

```javascript

398

// Load with error handling

399

db.loadDatabase((err) => {

400

if (err) {

401

console.error('Failed to load database:', err.message);

402

403

// Handle specific error types

404

if (err.name === 'SyntaxError') {

405

console.log('Database file corrupted, starting fresh');

406

db.collections = [];

407

} else if (err.code === 'ENOENT') {

408

console.log('Database file not found, will create new');

409

}

410

} else {

411

console.log('Database loaded successfully');

412

}

413

});

414

415

// Save with error handling

416

db.saveDatabase((err) => {

417

if (err) {

418

console.error('Failed to save database:', err.message);

419

420

// Retry logic

421

setTimeout(() => {

422

db.saveDatabase();

423

}, 5000);

424

} else {

425

console.log('Database saved successfully');

426

}

427

});

428

```

429

430

## Environment-Specific Usage

431

432

### Browser Environment

433

434

```javascript

435

// Detect and use appropriate browser adapter

436

let adapter;

437

if (typeof indexedDB !== 'undefined') {

438

// Use IndexedDB for better performance

439

adapter = new LokiIndexedAdapter('MyApp');

440

} else if (typeof localStorage !== 'undefined') {

441

// Fallback to localStorage

442

adapter = new loki.LokiLocalStorageAdapter();

443

} else {

444

// Use memory adapter as last resort

445

adapter = new loki.LokiMemoryAdapter();

446

}

447

448

const db = new loki('browser.db', { adapter });

449

```

450

451

### Node.js Environment

452

453

```javascript

454

// Node.js with file system persistence

455

const path = require('path');

456

const dataDir = path.join(__dirname, 'data');

457

458

const db = new loki(path.join(dataDir, 'app.db'), {

459

adapter: new loki.LokiFsAdapter(),

460

autosave: true,

461

autosaveInterval: 30000 // Save every 30 seconds

462

});

463

```

464

465

### Electron/Hybrid Apps

466

467

```javascript

468

// Detect environment and choose adapter

469

let adapter;

470

if (typeof window !== 'undefined' && window.require) {

471

// Electron renderer process - use file system

472

adapter = new loki.LokiFsAdapter();

473

} else if (typeof indexedDB !== 'undefined') {

474

// Browser environment - use IndexedDB

475

adapter = new LokiIndexedAdapter('ElectronApp');

476

} else {

477

// Node.js main process - use file system

478

adapter = new loki.LokiFsAdapter();

479

}

480

481

const db = new loki('hybrid.db', { adapter });

482

```

483

484

## Properties

485

486

```javascript { .api }

487

// Built-in adapter availability

488

loki.LokiMemoryAdapter: typeof LokiMemoryAdapter;

489

loki.LokiLocalStorageAdapter: typeof LokiLocalStorageAdapter;

490

loki.LokiFsAdapter: typeof LokiFsAdapter;

491

loki.LokiPartitioningAdapter: typeof LokiPartitioningAdapter;

492

493

// Adapter registry

494

loki.persistenceAdapters: {

495

fs: typeof LokiFsAdapter;

496

localStorage: typeof LokiLocalStorageAdapter;

497

};

498

```