CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ipld--car

Content Addressable aRchive format reader and writer for IPLD data structures.

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

reading.mddocs/

CAR Reading

Core functionality for reading CAR archives with full in-memory access to blocks and metadata. CarReader loads the entire archive into memory for random access, making it suitable for smaller CAR files or when frequent block lookups are needed.

Capabilities

CarReader Class

Provides blockstore-like access to a CAR archive with full random access capabilities.

/**
 * Provides blockstore-like access to a CAR archive
 * Loads entire archive into memory for random access
 */
class CarReader {
  /** CAR version number (1 or 2) */
  readonly version: number;
  
  /** Get the list of root CIDs defined in the CAR header */
  getRoots(): Promise<CID[]>;
  
  /** Check whether a given CID exists within the CAR */
  has(key: CID): Promise<boolean>;
  
  /** Fetch a Block from the CAR by CID, returns undefined if not found */
  get(key: CID): Promise<Block | undefined>;
  
  /** Returns async iterator over all Blocks in the CAR */
  blocks(): AsyncGenerator<Block>;
  
  /** Returns async iterator over all CIDs in the CAR */
  cids(): AsyncGenerator<CID>;
  
  /** Create CarReader from Uint8Array, decodes entire CAR into memory */
  static fromBytes(bytes: Uint8Array): Promise<CarReader>;
  
  /** Create CarReader from async iterable stream, decodes entire CAR into memory */
  static fromIterable(asyncIterable: AsyncIterable<Uint8Array>): Promise<CarReader>;
}

Usage Examples:

import { CarReader } from "@ipld/car/reader";
import fs from 'fs';

// From bytes
const carBytes = fs.readFileSync('archive.car');
const reader = await CarReader.fromBytes(carBytes);

// From stream
const stream = fs.createReadStream('archive.car');
const reader2 = await CarReader.fromIterable(stream);

// Access data
const roots = await reader.getRoots();
console.log(`CAR has ${roots.length} roots`);

// Check if CID exists
const exists = await reader.has(roots[0]);
if (exists) {
  const block = await reader.get(roots[0]);
  console.log(`Block size: ${block.bytes.length}`);
}

// Iterate through all blocks
for await (const block of reader.blocks()) {
  console.log(`Block CID: ${block.cid}, Size: ${block.bytes.length}`);
}

// Iterate through CIDs only (more efficient if you don't need block data)
for await (const cid of reader.cids()) {
  console.log(`CID: ${cid}`);
}

Raw Block Reading (Node.js Only)

Direct file-based block reading using file descriptors for efficient access to indexed blocks.

/**
 * Read a block directly from a file descriptor (Node.js only)
 * Used with CarIndexer to read blocks by their index information
 * @param fd - File descriptor (number or FileHandle)
 * @param blockIndex - Index information pointing to block location
 * @returns Block data
 */
static readRaw(
  fd: fs.promises.FileHandle | number, 
  blockIndex: BlockIndex
): Promise<Block>;

Usage Example:

import fs from 'fs';
import { CarReader } from "@ipld/car/reader";
import { CarIndexer } from "@ipld/car/indexer";

// Open file and create indexer
const fd = await fs.promises.open('large-archive.car', 'r');
const stream = fs.createReadStream('large-archive.car');
const indexer = await CarIndexer.fromIterable(stream);

// Read specific blocks using raw access
for await (const blockIndex of indexer) {
  const block = await CarReader.readRaw(fd, blockIndex);
  console.log(`Block ${block.cid}: ${block.bytes.length} bytes`);
  
  // Process only specific blocks
  if (someCondition(block.cid)) {
    processBlock(block);
  }
}

await fd.close();

Error Handling

Common errors when reading CAR files:

  • TypeError: Thrown when invalid input types are provided
  • Error: Thrown for malformed CAR data, invalid headers, or unexpected end of data
  • Unsupported CAR versions: Only versions 1 and 2 are supported
try {
  const reader = await CarReader.fromBytes(invalidBytes);
} catch (error) {
  if (error.message.includes('Invalid CAR')) {
    console.log('Malformed CAR file');
  } else if (error.message.includes('version')) {
    console.log('Unsupported CAR version');
  }
}

Platform Differences

Browser Environment

  • Uses CarReader from lib/reader-browser.js
  • Memory-based operations only
  • No file descriptor support

Node.js Environment

  • Uses CarReader from lib/reader.js (extends browser version)
  • Adds readRaw() static method for file descriptor access
  • Supports both memory and file-based operations

docs

buffer-writing.md

index.md

indexed-reading.md

indexing.md

iteration.md

reading.md

writing.md

tile.json