or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index-management.mdindex.mdlisting.mdreading.mdremoval.mdutilities.mdverification.mdwriting.md
tile.json

writing.mddocs/

Writing Operations

Functionality for storing data in the cache with automatic integrity hash generation, metadata support, and streaming capabilities.

Capabilities

Store Data

Stores data in the cache with a human-readable key, automatically generating a content integrity hash.

/**
 * Stores data in cache with key
 * @param {string} cache - Path to cache directory
 * @param {string} key - Cache key for the data
 * @param {Buffer|string} data - Data to store
 * @param {object} opts - Options object
 * @param {string[]} [opts.algorithms=['sha512']] - Hash algorithms to use
 * @param {object} [opts.metadata] - User-defined metadata to store with entry
 * @param {boolean|object} [opts.memoize] - Enable memoization of stored data
 * @param {number} [opts.size] - Expected data size for verification
 * @param {number} [opts.time] - Custom timestamp (default: Date.now())
 * @returns {Promise<string>} Promise resolving to content integrity hash
 */
function put(cache, key, data, opts = {});

Usage Examples:

const cacache = require('cacache');

// Basic storage
const integrity = await cacache.put('./cache', 'my-key', 'Hello World');
console.log('Stored with integrity:', integrity);

// With metadata
const integrity = await cacache.put('./cache', 'user-data', userData, {
  metadata: {
    version: '1.0',
    source: 'api',
    timestamp: Date.now()
  }
});

// With custom algorithms
const integrity = await cacache.put('./cache', 'secure-data', sensitiveData, {
  algorithms: ['sha256', 'sha512']
});

// With memoization
const integrity = await cacache.put('./cache', 'frequent-data', data, {
  memoize: true
});

// With size verification
const integrity = await cacache.put('./cache', 'verified-data', data, {
  size: data.length
});

Store Data Stream

Returns a writable stream for storing data in the cache, useful for large files or streaming data sources.

/**
 * Returns writable stream for storing data
 * @param {string} cache - Path to cache directory
 * @param {string} key - Cache key for the data
 * @param {object} opts - Options object
 * @param {string[]} [opts.algorithms=['sha512']] - Hash algorithms to use
 * @param {object} [opts.metadata] - User-defined metadata to store with entry
 * @param {boolean|object} [opts.memoize] - Enable memoization of stored data
 * @param {number} [opts.size] - Expected data size for verification
 * @param {number} [opts.time] - Custom timestamp (default: Date.now())
 * @returns {WritableStream} Writable stream with events: integrity, size
 */
function put.stream(cache, key, opts = {});

The returned stream emits the following events:

  • integrity - Content integrity hash when storage completes
  • size - Final content size in bytes
  • error - Error if storage fails

Usage Examples:

const fs = require('fs');

// Stream file to cache
const writeStream = cacache.put.stream('./cache', 'large-file');
writeStream.on('integrity', (integrity) => {
  console.log('File stored with integrity:', integrity);
});
writeStream.on('size', (size) => {
  console.log('File size:', size);
});

fs.createReadStream('./input.txt').pipe(writeStream);

// Stream with metadata
const writeStream = cacache.put.stream('./cache', 'api-response', {
  metadata: {
    url: 'https://api.example.com/data',
    timestamp: Date.now()
  }
});

// Stream with promise-based completion
const writeStream = cacache.put.stream('./cache', 'streaming-data');
await new Promise((resolve, reject) => {
  writeStream.on('integrity', resolve);
  writeStream.on('error', reject);
  
  // Write data chunks
  writeStream.write('chunk 1\n');
  writeStream.write('chunk 2\n');
  writeStream.end('final chunk');
});

// Stream HTTP response to cache
const https = require('https');

https.get('https://example.com/data', (response) => {
  const writeStream = cacache.put.stream('./cache', 'http-data', {
    metadata: {
      statusCode: response.statusCode,
      headers: response.headers,
      url: 'https://example.com/data'
    }
  });
  
  response.pipe(writeStream);
  
  writeStream.on('integrity', (integrity) => {
    console.log('HTTP response cached with integrity:', integrity);
  });
});

Advanced Usage Patterns

Conditional Storage

Check if content already exists before storing to avoid duplicate writes:

// Check if we already have this content
const existingIntegrity = 'sha512-abc123...'; // from previous operation
const hasContent = await cacache.get.hasContent('./cache', existingIntegrity);

if (!hasContent) {
  const integrity = await cacache.put('./cache', 'my-key', newData);
  console.log('Stored new content:', integrity);
} else {
  console.log('Content already exists, skipping storage');
}

Atomic Updates

Update cache entries atomically by writing to a new key first:

// Store updated data with temporary key
const tempKey = `${originalKey}.tmp.${Date.now()}`;
const integrity = await cacache.put('./cache', tempKey, newData, {
  metadata: { ...originalMetadata, updated: Date.now() }
});

// Remove old entry and update key atomically
await cacache.rm.entry('./cache', originalKey);
await cacache.put('./cache', originalKey, newData, {
  metadata: { ...originalMetadata, updated: Date.now() }
});
await cacache.rm.entry('./cache', tempKey);

Batch Operations

Store multiple related items efficiently:

// Store multiple files concurrently
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
const results = await Promise.all(
  files.map(async (filename) => {
    const data = await fs.readFile(filename);
    const integrity = await cacache.put('./cache', filename, data, {
      metadata: {
        originalPath: filename,
        mtime: (await fs.stat(filename)).mtime
      }
    });
    return { filename, integrity };
  })
);

console.log('Stored files:', results);

Custom Memoization

Use custom memoization objects for fine-grained control:

// Create custom memoization cache
const customMemo = new Map();

// Store with custom memoization
const integrity = await cacache.put('./cache', 'memo-data', data, {
  memoize: customMemo
});

// Check memoization
const memoKey = `key:./cache:memo-data`;
if (customMemo.has(memoKey)) {
  console.log('Data is memoized');
}

Error Handling

Writing operations may encounter various errors:

try {
  const integrity = await cacache.put('./cache', 'my-key', data);
  console.log('Success:', integrity);
} catch (error) {
  switch (error.code) {
    case 'ENOSPC':
      console.error('Insufficient disk space');
      break;
    case 'EACCES':
      console.error('Permission denied');
      break;
    case 'EMFILE':
      console.error('Too many open files');
      break;
    default:
      console.error('Unexpected error:', error);
  }
}

Performance Considerations

Streaming vs Bulk Storage

  • Use put() for small data (< 1MB) that fits in memory
  • Use put.stream() for large files or streaming data sources
  • Streaming avoids loading entire content into memory

Hash Algorithm Selection

// Single algorithm (fastest)
await cacache.put('./cache', 'key', data, {
  algorithms: ['sha512']
});

// Multiple algorithms (more secure, slower)
await cacache.put('./cache', 'key', data, {
  algorithms: ['sha256', 'sha512', 'sha1']
});

Memoization Trade-offs

  • Enable memoization for frequently accessed data
  • Disable for large, rarely accessed content to save memory
  • Use custom memoization objects for fine-grained control