or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdcollection.mdconfiguration.mdhooks.mdindex.mdinstrumentation.mdreporting.mdstorage.mdtree-summarizer.mdutilities.md
tile.json

storage.mddocs/

0

# Storage System

1

2

Storage system provides pluggable backends for coverage data with memory, filesystem, and temporary storage options. The Store system enables flexible data persistence during coverage collection and processing.

3

4

## Capabilities

5

6

### Store Factory

7

8

Factory class for creating and registering storage implementations.

9

10

```javascript { .api }

11

/**

12

* Store factory and base class

13

*/

14

class Store {

15

/**

16

* Creates a store of the specified type

17

* @param {string} type - Store type ('memory', 'fslookup', 'tmp')

18

* @param {Object} opts - Store-specific options

19

* @returns {Store} Store instance

20

*/

21

static create(type: string, opts?: Object): Store;

22

23

/**

24

* Registers a new store implementation

25

* @param {Function} constructor - Store constructor function

26

*/

27

static register(constructor: Function): void;

28

}

29

```

30

31

### Store Interface

32

33

All store implementations provide a consistent interface for data persistence.

34

35

```javascript { .api }

36

interface Store {

37

/**

38

* Sets content for a key

39

* @param {string} key - Storage key

40

* @param {string} contents - Content to store

41

*/

42

set(key: string, contents: string): void;

43

44

/**

45

* Gets content for a key

46

* @param {string} key - Storage key

47

* @returns {string} Stored content

48

*/

49

get(key: string): string;

50

51

/**

52

* Returns array of all known keys

53

* @returns {string[]} Array of keys

54

*/

55

keys(): string[];

56

57

/**

58

* Checks if a key exists in storage

59

* @param {string} key - Storage key

60

* @returns {boolean} True if key exists

61

*/

62

hasKey(key: string): boolean;

63

64

/**

65

* Disposes store and reclaims temporary resources

66

*/

67

dispose(): void;

68

69

/**

70

* Gets JSON object for a key

71

* @param {string} key - Storage key

72

* @returns {Object} Parsed JSON object

73

*/

74

getObject(key: string): Object;

75

76

/**

77

* Sets JSON object for a key

78

* @param {string} key - Storage key

79

* @param {Object} object - Object to serialize and store

80

*/

81

setObject(key: string, object: Object): void;

82

}

83

```

84

85

**Usage Examples:**

86

87

```javascript

88

const { Store } = require('istanbul');

89

90

// Create different store types

91

const memoryStore = Store.create('memory');

92

const fsStore = Store.create('fslookup', {

93

dir: './coverage-data'

94

});

95

const tmpStore = Store.create('tmp');

96

97

// Basic operations

98

memoryStore.set('coverage-1', JSON.stringify(coverageData));

99

const retrieved = JSON.parse(memoryStore.get('coverage-1'));

100

101

// Object operations (automatic JSON handling)

102

memoryStore.setObject('coverage-2', coverageData);

103

const coverageObj = memoryStore.getObject('coverage-2');

104

105

// Key management

106

console.log('All keys:', memoryStore.keys());

107

console.log('Has coverage-1:', memoryStore.hasKey('coverage-1'));

108

109

// Cleanup

110

memoryStore.dispose();

111

```

112

113

### Built-in Store Types

114

115

#### Memory Store

116

117

In-memory storage for coverage data with fast access and automatic cleanup.

118

119

```javascript { .api }

120

/**

121

* In-memory store implementation

122

*/

123

class MemoryStore extends Store {

124

constructor(opts?: MemoryStoreOptions);

125

}

126

127

interface MemoryStoreOptions {

128

/** No specific options for memory store */

129

}

130

```

131

132

**Usage Examples:**

133

134

```javascript

135

// Create memory store

136

const memoryStore = Store.create('memory');

137

138

// Store coverage data from multiple files

139

memoryStore.setObject('file1.js', {

140

path: 'file1.js',

141

s: { '1': 1, '2': 0 },

142

b: { '1': [1, 0] },

143

f: { '1': 1 }

144

});

145

146

memoryStore.setObject('file2.js', {

147

path: 'file2.js',

148

s: { '1': 2, '2': 1 },

149

b: { '1': [2, 1] },

150

f: { '1': 2 }

151

});

152

153

// Retrieve and process

154

const allKeys = memoryStore.keys();

155

allKeys.forEach(key => {

156

const coverage = memoryStore.getObject(key);

157

console.log(`Coverage for ${key}:`, coverage);

158

});

159

160

// Memory stores are automatically cleaned up

161

memoryStore.dispose();

162

```

163

164

#### Filesystem Lookup Store

165

166

File system-based storage for persistent coverage data with directory organization.

167

168

```javascript { .api }

169

/**

170

* Filesystem-based store implementation

171

*/

172

class FsLookupStore extends Store {

173

constructor(opts: FsStoreOptions);

174

}

175

176

interface FsStoreOptions {

177

/** Directory to store files */

178

dir: string;

179

180

/** Whether to create directory if it doesn't exist */

181

create?: boolean;

182

}

183

```

184

185

**Usage Examples:**

186

187

```javascript

188

const path = require('path');

189

190

// Create filesystem store

191

const fsStore = Store.create('fslookup', {

192

dir: path.resolve('./coverage-store'),

193

create: true

194

});

195

196

// Store coverage data (persisted to disk)

197

fsStore.setObject('src/app.js', {

198

path: 'src/app.js',

199

s: { '1': 5, '2': 3, '3': 1 },

200

b: { '1': [5, 2], '2': [3, 0] },

201

f: { '1': 5, '2': 3 }

202

});

203

204

// Data persists across program restarts

205

const storedCoverage = fsStore.getObject('src/app.js');

206

console.log('Persisted coverage:', storedCoverage);

207

208

// Cleanup removes temporary files

209

fsStore.dispose();

210

```

211

212

#### Temporary Store

213

214

Temporary directory storage with automatic cleanup for intermediate processing.

215

216

```javascript { .api }

217

/**

218

* Temporary directory store implementation

219

*/

220

class TmpStore extends Store {

221

constructor(opts?: TmpStoreOptions);

222

}

223

224

interface TmpStoreOptions {

225

/** Prefix for temporary directory name */

226

prefix?: string;

227

}

228

```

229

230

**Usage Examples:**

231

232

```javascript

233

const os = require('os');

234

235

// Create temporary store

236

const tmpStore = Store.create('tmp', {

237

prefix: 'istanbul-coverage-'

238

});

239

240

// Store data in temporary location

241

tmpStore.set('intermediate-data', JSON.stringify({

242

processed: true,

243

timestamp: Date.now()

244

}));

245

246

// Temporary directory location

247

console.log('Temp store keys:', tmpStore.keys());

248

249

// Automatic cleanup on dispose

250

tmpStore.dispose(); // Removes temporary directory and all files

251

```

252

253

### Store Usage Patterns

254

255

#### With Collector

256

257

Stores are commonly used with Collector for large datasets:

258

259

```javascript

260

const { Collector, Store } = require('istanbul');

261

262

// Use filesystem store for large coverage collection

263

const collector = new Collector({

264

store: Store.create('fslookup', {

265

dir: './coverage-temp',

266

create: true

267

})

268

});

269

270

// Add multiple coverage objects

271

collector.add(coverage1);

272

collector.add(coverage2);

273

collector.add(coverage3);

274

275

// Store handles persistence automatically

276

const finalCoverage = collector.getFinalCoverage();

277

278

// Cleanup

279

collector.dispose(); // Also disposes the store

280

```

281

282

#### Batch Processing

283

284

Use stores for batch processing large coverage datasets:

285

286

```javascript

287

async function processCoverageFiles(coverageFiles) {

288

const store = Store.create('tmp', { prefix: 'batch-coverage-' });

289

290

try {

291

// Store all coverage data

292

for (let i = 0; i < coverageFiles.length; i++) {

293

const coverage = require(coverageFiles[i]);

294

store.setObject(`batch-${i}`, coverage);

295

}

296

297

// Process stored data

298

const allKeys = store.keys();

299

const processedResults = allKeys.map(key => {

300

const coverage = store.getObject(key);

301

return processCoverage(coverage);

302

});

303

304

return processedResults;

305

} finally {

306

// Always cleanup

307

store.dispose();

308

}

309

}

310

```

311

312

### Custom Store Implementation

313

314

Create custom store implementations for specialized storage needs:

315

316

```javascript

317

class DatabaseStore extends Store {

318

constructor(opts) {

319

super();

320

this.db = opts.database;

321

this.table = opts.table || 'coverage_data';

322

}

323

324

set(key, contents) {

325

this.db.query(

326

`INSERT OR REPLACE INTO ${this.table} (key, contents) VALUES (?, ?)`,

327

[key, contents]

328

);

329

}

330

331

get(key) {

332

const result = this.db.query(

333

`SELECT contents FROM ${this.table} WHERE key = ?`,

334

[key]

335

);

336

return result.length > 0 ? result[0].contents : null;

337

}

338

339

keys() {

340

const results = this.db.query(`SELECT key FROM ${this.table}`);

341

return results.map(row => row.key);

342

}

343

344

hasKey(key) {

345

const result = this.db.query(

346

`SELECT 1 FROM ${this.table} WHERE key = ? LIMIT 1`,

347

[key]

348

);

349

return result.length > 0;

350

}

351

352

dispose() {

353

// Clean up database resources

354

if (this.db) {

355

this.db.close();

356

}

357

}

358

}

359

360

// Register custom store

361

Store.register(DatabaseStore);

362

363

// Use custom store

364

const dbStore = Store.create('DatabaseStore', {

365

database: myDatabase,

366

table: 'istanbul_coverage'

367

});

368

```

369

370

### Error Handling

371

372

Handle storage errors appropriately:

373

374

```javascript

375

const store = Store.create('fslookup', { dir: './coverage-data' });

376

377

try {

378

store.setObject('test-coverage', coverageData);

379

} catch (error) {

380

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

381

console.error('Storage directory does not exist');

382

} else if (error.code === 'EACCES') {

383

console.error('Permission denied writing to storage');

384

} else {

385

console.error('Storage error:', error.message);

386

}

387

}

388

389

// Safe retrieval

390

function safeCoverageGet(store, key) {

391

try {

392

if (store.hasKey(key)) {

393

return store.getObject(key);

394

}

395

return null;

396

} catch (error) {

397

console.warn(`Failed to retrieve coverage for ${key}:`, error.message);

398

return null;

399

}

400

}

401

```

402

403

### Performance Considerations

404

405

Choose appropriate store types based on usage patterns:

406

407

```javascript

408

// For small datasets or short-lived processes

409

const quickStore = Store.create('memory');

410

411

// For large datasets that need persistence

412

const persistentStore = Store.create('fslookup', {

413

dir: './coverage-cache'

414

});

415

416

// For intermediate processing with automatic cleanup

417

const tempStore = Store.create('tmp');

418

419

// Monitor store performance

420

function benchmarkStore(store, operations = 1000) {

421

const start = Date.now();

422

423

for (let i = 0; i < operations; i++) {

424

store.set(`key-${i}`, `value-${i}`);

425

}

426

427

for (let i = 0; i < operations; i++) {

428

store.get(`key-${i}`);

429

}

430

431

const elapsed = Date.now() - start;

432

console.log(`${operations} operations took ${elapsed}ms`);

433

434

store.dispose();

435

}

436

```

437

438

### Store Lifecycle Management

439

440

Proper lifecycle management for stores:

441

442

```javascript

443

class CoverageProcessor {

444

constructor(storeType = 'memory', storeOpts = {}) {

445

this.store = Store.create(storeType, storeOpts);

446

this.disposed = false;

447

}

448

449

addCoverage(key, coverage) {

450

if (this.disposed) {

451

throw new Error('Cannot use disposed store');

452

}

453

this.store.setObject(key, coverage);

454

}

455

456

getCoverage(key) {

457

if (this.disposed) {

458

throw new Error('Cannot use disposed store');

459

}

460

return this.store.getObject(key);

461

}

462

463

getAllCoverage() {

464

if (this.disposed) {

465

throw new Error('Cannot use disposed store');

466

}

467

468

const coverage = {};

469

this.store.keys().forEach(key => {

470

coverage[key] = this.store.getObject(key);

471

});

472

return coverage;

473

}

474

475

dispose() {

476

if (!this.disposed) {

477

this.store.dispose();

478

this.disposed = true;

479

}

480

}

481

}

482

483

// Usage with proper cleanup

484

const processor = new CoverageProcessor('tmp');

485

try {

486

processor.addCoverage('file1.js', coverage1);

487

processor.addCoverage('file2.js', coverage2);

488

489

const allCoverage = processor.getAllCoverage();

490

// Process coverage...

491

492

} finally {

493

processor.dispose(); // Always cleanup

494

}

495

```