# snapdir for Node.js The `@snapdir/snapdir` package wraps the same Rust core (`snapdir-api → snapdir-core`) that powers the CLI, so the manifests and snapshot IDs it produces are bit-identical to `snapdir id`, `snapdir push`, and every other binding. The surface is idiomatic Node.js: synchronous helpers plus `Promise`-returning `async` operations that never block the event loop. ## Install ```sh npm install @snapdir/snapdir ``` **Prebuilt, zero build tools.** The package ships precompiled native binaries for Linux (glibc + musl) and macOS on x64 and arm64. There is no source build: no Rust toolchain, no C compiler, no post-install step. The loader selects the correct `.node` binary for your platform, so it runs on Alpine/musl out of the box. ## Usage The store URI is always an **argument**, never an environment variable — use `file://$PWD/store` for a no-setup local store, or `gs://bucket/prefix` for Google Cloud Storage. ```js import { id, manifest, push, pull, fetch, diff, SnapdirError } from '@snapdir/snapdir' const store = `file://${process.cwd()}/store` // Snapshot ID — pure and deterministic, no store touched. const snapshotId = await id('./my-dir') console.log(snapshotId) // 64-char lowercase hex // Full manifest: per-entry path, checksum, and size. size is always bigint. const m = await manifest('./my-dir') for (const entry of m.entries) { console.log(entry.path, entry.size) // size: bigint (u64) } // Push to the store; returns the same 64-hex ID. const sid = await push('./my-dir', store) // Fetch into the local cache, or pull + materialize into a directory. await fetch(sid, store) await pull(sid, store, './restored') // Diff two stores: { from, to } are arrays of store URIs. // A pinned snapshot reference uses the store@id convention — the last '@' // splits the store URI from the 64-hex snapshot ID. const entries = await diff({ from: [store], to: [`${store}-next`] }) for (const e of entries) { console.log(`${e.status}\t${e.path}`) // A / D / M / = — byte-identical to the CLI } ``` For Google Cloud, swap the store URI for a `gs://` URL: ```js const sid = await push('./my-dir', 'gs://my-bucket/snapshots') ``` ## Errors Every failure is a `SnapdirError` (extends `Error`) whose `.code` is one of the eight stable `SCREAMING_SNAKE_CASE` codes shared across all bindings and the CLI. ```js import { push, SnapdirError } from '@snapdir/snapdir' try { await push('./missing', 'file://$PWD/store') } catch (err) { if (err instanceof SnapdirError) { switch (err.code) { case 'IO_ERROR': break // filesystem read/write failure case 'HASH_MISMATCH': break // content did not match its expected checksum case 'STORE_ERROR': break // object-store transport/backend failure case 'IN_FLUX': break // a file changed while being read case 'CATALOG_ERROR': break // manifest/catalog could not be parsed case 'INVALID_ID': break // snapshot ID is not 64-hex case 'INVALID_STORE': break // store URI is malformed or unsupported case 'CONFLICT': break // a concurrent write conflicted } console.error(err.code, err.message) } } ``` ## Platform support Every binding is CI-verified against its live public registry (npm) before release. | Platform | Supported | | --- | --- | | Linux glibc (x64 + arm64) | yes | | Linux musl / Alpine (x64 + arm64) | yes | | macOS | yes | | Windows | no | The Node.js binding runs on both glibc and musl. The only binding-wide exception to musl support is **Java**, which is glibc-only today (musl planned for 1.11.1); the Node.js binding has no such caveat. Windows is unsupported — snapdir is Unix-only.