c4ts — TypeScript / JavaScript

c4ts brings C4 content identification to every JavaScript environment — browsers, Node.js, Deno, edge workers. The core package has zero dependencies and uses WebCrypto for hardware-accelerated SHA-512 hashing.

Two packages: @avalanche-io/c4 (browser + Node) and @avalanche-io/c4-node (filesystem store, scanner, workspace).

GitHub: Avalanche-io/c4ts

Install

npm install @avalanche-io/c4

# Node.js extensions (filesystem store, scanner, workspace)
npm install @avalanche-io/c4-node

Quick start

Identify content

import { identify, identifyBytes, parse } from '@avalanche-io/c4'

const id = await identifyBytes(new TextEncoder().encode('hello world'))
console.log(id.toString())  // c41yP4cqy7jmaRDz...

const same = parse('c41yP4cqy7jmaRDz...')
console.log(id.equals(same))  // true

Parse and encode c4m files

import { Manifest } from '@avalanche-io/c4'

const manifest = await Manifest.parse(c4mText)
console.log(manifest.summary())  // "247 files, 12 dirs, 3.2 GB"

for (const [path, entry] of manifest) {
  console.log(path, entry.c4id?.toString())
}

// Encode back to c4m text
const text = manifest.encode()
const pretty = manifest.encode({ pretty: true })

Diff two manifests

import { Manifest, diff } from '@avalanche-io/c4'

const old = await Manifest.parse(oldText)
const current = await Manifest.parse(currentText)
const result = diff(old, current)

console.log(`${result.added.length} added`)
console.log(`${result.removed.length} removed`)
console.log(`${result.modified.length} modified`)

Verify files against a manifest

import { verify, MemoryFS } from '@avalanche-io/c4'

const report = await verify(manifest, fs, '/project')
if (report.isOk) {
  console.log('All files verified.')
} else {
  console.log(`${report.corrupt.length} corrupt, ${report.missing.length} missing`)
}

Scan a directory (Node.js)

import { NodeFS, TreeStore, Workspace } from '@avalanche-io/c4-node'
import { scan } from '@avalanche-io/c4'

const fs = new NodeFS()
const manifest = await scan(fs, '/projects/footage', {
  progress: (path, n) => console.log(`${n}: ${path}`)
})
console.log(manifest.summary())

Browser features

c4ts runs natively in the browser with zero bundler configuration.

Scan files via drag-and-drop or File System Access API

import { scan, FileSystemAccessFS } from '@avalanche-io/c4/browser'

// User picks a directory
const dirHandle = await window.showDirectoryPicker()
const fs = new FileSystemAccessFS(dirHandle)
const manifest = await scan(fs, '')

Persistent browser storage

import { IndexedDBStore } from '@avalanche-io/c4/browser'

const store = new IndexedDBStore('my-project')
await store.put(fileBytes)
const stream = await store.get(c4id)

Parallel hashing with Web Workers

import { createHashPool } from '@avalanche-io/c4/browser'

const pool = createHashPool(navigator.hardwareConcurrency)
const ids = await pool.identifyAll(files, {
  progress: (done, total) => updateProgressBar(done / total)
})
pool.terminate()

Composable architecture

c4ts is built on three abstract interfaces that decouple operations from backends:

The same workspace, scanner, verify, and reconciler code works against any backend — browser, Node.js, or in-memory for tests.

import { ContentResolver, storeAsSource, MemoryStore } from '@avalanche-io/c4'

const resolver = new ContentResolver()
resolver.addSource(storeAsSource(localStore, 'local', 0))
resolver.addSource(storeAsSource(remoteStore, 'remote', 10))

// Fastest source wins
const stream = await resolver.get(c4id)

Workspace

Declarative directory management — like Docker for data:

import { Workspace, MemoryStore, MemoryFS } from '@avalanche-io/c4'

const ws = new Workspace('/data', fs, store)
await ws.checkout(manifest)    // make directory match manifest
const snap = await ws.snapshot()  // capture current state
await ws.reset()               // revert to last checkout
const changes = await ws.diffFromCurrent()

Interoperability

c4ts produces byte-identical C4 IDs and c4m files as every other tool in the ecosystem. A manifest created by the Go CLI can be parsed by c4ts, and vice versa. Cross-language compatibility is verified by shared test vectors from the reference implementation.