CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-istanbul

Comprehensive JavaScript code coverage tool that computes statement, line, function and branch coverage with module loader hooks for transparent instrumentation

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

storage.mddocs/

Storage System

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.

Capabilities

Store Factory

Factory class for creating and registering storage implementations.

/**
 * Store factory and base class
 */
class Store {
    /**
     * Creates a store of the specified type
     * @param {string} type - Store type ('memory', 'fslookup', 'tmp')
     * @param {Object} opts - Store-specific options
     * @returns {Store} Store instance
     */
    static create(type: string, opts?: Object): Store;
    
    /**
     * Registers a new store implementation
     * @param {Function} constructor - Store constructor function
     */
    static register(constructor: Function): void;
}

Store Interface

All store implementations provide a consistent interface for data persistence.

interface Store {
    /**
     * Sets content for a key
     * @param {string} key - Storage key
     * @param {string} contents - Content to store
     */
    set(key: string, contents: string): void;
    
    /**
     * Gets content for a key
     * @param {string} key - Storage key
     * @returns {string} Stored content
     */
    get(key: string): string;
    
    /**
     * Returns array of all known keys
     * @returns {string[]} Array of keys
     */
    keys(): string[];
    
    /**
     * Checks if a key exists in storage
     * @param {string} key - Storage key  
     * @returns {boolean} True if key exists
     */
    hasKey(key: string): boolean;
    
    /**
     * Disposes store and reclaims temporary resources
     */
    dispose(): void;
    
    /**
     * Gets JSON object for a key
     * @param {string} key - Storage key
     * @returns {Object} Parsed JSON object
     */
    getObject(key: string): Object;
    
    /**
     * Sets JSON object for a key
     * @param {string} key - Storage key
     * @param {Object} object - Object to serialize and store
     */
    setObject(key: string, object: Object): void;
}

Usage Examples:

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

// Create different store types
const memoryStore = Store.create('memory');
const fsStore = Store.create('fslookup', { 
    dir: './coverage-data' 
});
const tmpStore = Store.create('tmp');

// Basic operations
memoryStore.set('coverage-1', JSON.stringify(coverageData));
const retrieved = JSON.parse(memoryStore.get('coverage-1'));

// Object operations (automatic JSON handling)
memoryStore.setObject('coverage-2', coverageData);
const coverageObj = memoryStore.getObject('coverage-2');

// Key management
console.log('All keys:', memoryStore.keys());
console.log('Has coverage-1:', memoryStore.hasKey('coverage-1'));

// Cleanup
memoryStore.dispose();

Built-in Store Types

Memory Store

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

/**
 * In-memory store implementation
 */
class MemoryStore extends Store {
    constructor(opts?: MemoryStoreOptions);
}

interface MemoryStoreOptions {
    /** No specific options for memory store */
}

Usage Examples:

// Create memory store
const memoryStore = Store.create('memory');

// Store coverage data from multiple files
memoryStore.setObject('file1.js', {
    path: 'file1.js',
    s: { '1': 1, '2': 0 },
    b: { '1': [1, 0] },
    f: { '1': 1 }
});

memoryStore.setObject('file2.js', {
    path: 'file2.js', 
    s: { '1': 2, '2': 1 },
    b: { '1': [2, 1] },
    f: { '1': 2 }
});

// Retrieve and process
const allKeys = memoryStore.keys();
allKeys.forEach(key => {
    const coverage = memoryStore.getObject(key);
    console.log(`Coverage for ${key}:`, coverage);
});

// Memory stores are automatically cleaned up
memoryStore.dispose();

Filesystem Lookup Store

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

/**
 * Filesystem-based store implementation
 */
class FsLookupStore extends Store {
    constructor(opts: FsStoreOptions);
}

interface FsStoreOptions {
    /** Directory to store files */
    dir: string;
    
    /** Whether to create directory if it doesn't exist */
    create?: boolean;
}

Usage Examples:

const path = require('path');

// Create filesystem store
const fsStore = Store.create('fslookup', {
    dir: path.resolve('./coverage-store'),
    create: true
});

// Store coverage data (persisted to disk)
fsStore.setObject('src/app.js', {
    path: 'src/app.js',
    s: { '1': 5, '2': 3, '3': 1 },
    b: { '1': [5, 2], '2': [3, 0] },
    f: { '1': 5, '2': 3 }
});

// Data persists across program restarts
const storedCoverage = fsStore.getObject('src/app.js');
console.log('Persisted coverage:', storedCoverage);

// Cleanup removes temporary files
fsStore.dispose();

Temporary Store

Temporary directory storage with automatic cleanup for intermediate processing.

/**
 * Temporary directory store implementation
 */
class TmpStore extends Store {
    constructor(opts?: TmpStoreOptions);
}

interface TmpStoreOptions {
    /** Prefix for temporary directory name */
    prefix?: string;
}

Usage Examples:

const os = require('os');

// Create temporary store
const tmpStore = Store.create('tmp', {
    prefix: 'istanbul-coverage-'
});

// Store data in temporary location
tmpStore.set('intermediate-data', JSON.stringify({
    processed: true,
    timestamp: Date.now()
}));

// Temporary directory location
console.log('Temp store keys:', tmpStore.keys());

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

Store Usage Patterns

With Collector

Stores are commonly used with Collector for large datasets:

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

// Use filesystem store for large coverage collection
const collector = new Collector({
    store: Store.create('fslookup', { 
        dir: './coverage-temp',
        create: true 
    })
});

// Add multiple coverage objects
collector.add(coverage1);
collector.add(coverage2);
collector.add(coverage3);

// Store handles persistence automatically
const finalCoverage = collector.getFinalCoverage();

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

Batch Processing

Use stores for batch processing large coverage datasets:

async function processCoverageFiles(coverageFiles) {
    const store = Store.create('tmp', { prefix: 'batch-coverage-' });
    
    try {
        // Store all coverage data
        for (let i = 0; i < coverageFiles.length; i++) {
            const coverage = require(coverageFiles[i]);
            store.setObject(`batch-${i}`, coverage);
        }
        
        // Process stored data
        const allKeys = store.keys();
        const processedResults = allKeys.map(key => {
            const coverage = store.getObject(key);
            return processCoverage(coverage);
        });
        
        return processedResults;
    } finally {
        // Always cleanup
        store.dispose();
    }
}

Custom Store Implementation

Create custom store implementations for specialized storage needs:

class DatabaseStore extends Store {
    constructor(opts) {
        super();
        this.db = opts.database;
        this.table = opts.table || 'coverage_data';
    }
    
    set(key, contents) {
        this.db.query(
            `INSERT OR REPLACE INTO ${this.table} (key, contents) VALUES (?, ?)`,
            [key, contents]
        );
    }
    
    get(key) {
        const result = this.db.query(
            `SELECT contents FROM ${this.table} WHERE key = ?`,
            [key]
        );
        return result.length > 0 ? result[0].contents : null;
    }
    
    keys() {
        const results = this.db.query(`SELECT key FROM ${this.table}`);
        return results.map(row => row.key);
    }
    
    hasKey(key) {
        const result = this.db.query(
            `SELECT 1 FROM ${this.table} WHERE key = ? LIMIT 1`,
            [key]
        );
        return result.length > 0;
    }
    
    dispose() {
        // Clean up database resources
        if (this.db) {
            this.db.close();
        }
    }
}

// Register custom store
Store.register(DatabaseStore);

// Use custom store
const dbStore = Store.create('DatabaseStore', {
    database: myDatabase,
    table: 'istanbul_coverage'
});

Error Handling

Handle storage errors appropriately:

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

try {
    store.setObject('test-coverage', coverageData);
} catch (error) {
    if (error.code === 'ENOENT') {
        console.error('Storage directory does not exist');
    } else if (error.code === 'EACCES') {
        console.error('Permission denied writing to storage');
    } else {
        console.error('Storage error:', error.message);
    }
}

// Safe retrieval
function safeCoverageGet(store, key) {
    try {
        if (store.hasKey(key)) {
            return store.getObject(key);
        }
        return null;
    } catch (error) {
        console.warn(`Failed to retrieve coverage for ${key}:`, error.message);
        return null;
    }
}

Performance Considerations

Choose appropriate store types based on usage patterns:

// For small datasets or short-lived processes
const quickStore = Store.create('memory');

// For large datasets that need persistence
const persistentStore = Store.create('fslookup', {
    dir: './coverage-cache'
});

// For intermediate processing with automatic cleanup
const tempStore = Store.create('tmp');

// Monitor store performance
function benchmarkStore(store, operations = 1000) {
    const start = Date.now();
    
    for (let i = 0; i < operations; i++) {
        store.set(`key-${i}`, `value-${i}`);
    }
    
    for (let i = 0; i < operations; i++) {
        store.get(`key-${i}`);
    }
    
    const elapsed = Date.now() - start;
    console.log(`${operations} operations took ${elapsed}ms`);
    
    store.dispose();
}

Store Lifecycle Management

Proper lifecycle management for stores:

class CoverageProcessor {
    constructor(storeType = 'memory', storeOpts = {}) {
        this.store = Store.create(storeType, storeOpts);
        this.disposed = false;
    }
    
    addCoverage(key, coverage) {
        if (this.disposed) {
            throw new Error('Cannot use disposed store');
        }
        this.store.setObject(key, coverage);
    }
    
    getCoverage(key) {
        if (this.disposed) {
            throw new Error('Cannot use disposed store');
        }
        return this.store.getObject(key);
    }
    
    getAllCoverage() {
        if (this.disposed) {
            throw new Error('Cannot use disposed store');
        }
        
        const coverage = {};
        this.store.keys().forEach(key => {
            coverage[key] = this.store.getObject(key);
        });
        return coverage;
    }
    
    dispose() {
        if (!this.disposed) {
            this.store.dispose();
            this.disposed = true;
        }
    }
}

// Usage with proper cleanup
const processor = new CoverageProcessor('tmp');
try {
    processor.addCoverage('file1.js', coverage1);
    processor.addCoverage('file2.js', coverage2);
    
    const allCoverage = processor.getAllCoverage();
    // Process coverage...
    
} finally {
    processor.dispose(); // Always cleanup
}

docs

cli.md

collection.md

configuration.md

hooks.md

index.md

instrumentation.md

reporting.md

storage.md

tree-summarizer.md

utilities.md

tile.json