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).
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:
- Store — content-addressed blob storage (MemoryStore, IndexedDBStore, TreeStore)
- FileSystem — filesystem operations (MemoryFS, FileSystemAccessFS, NodeFS)
- ContentResolver — multi-source content resolution with
Promise.race()
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.