Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2026-06-01

Initial public release of the JS reference implementation.

### Added

- **Core codec** — `encode(value, { provider?, types? })` and
`decode(bytes, { types?, maxNodes? })`. Cycles and shared identity are
preserved via a heap + references; decoding resolves lazily with memoization.
- **Type coverage** (tags 0–47): Null, Undefined, Bool, Int, Float, BigInt,
String; Symbol (registered / unique / well-known); Array, Object, Map, Set
with arbitrary object keys; WeakMap / WeakSet via an explicit `provider`;
Date, Bytes, TypedArray, RegExp, Url, DataView, Error; and a `Custom` tag for
user-registered extension types.
- **Extension types** — opt-in lossless serialization of class instances and
domain types through a `TypeExtension` registry.
- **JSON bridge** — `toJSON` / `fromJSON` for inspecting and hand-editing an
encoded graph (identity-lossy; cycles rejected).
- **CLI** — `graft inspect` (tree view + tag histogram) and `graft diff`
(structural diff of two value graphs).
- **Decode safety** — rejects out-of-range roots/refs, counts exceeding the
buffer, and bounds work via `maxNodes`.
- **Format spec** — `spec/FORMAT.md` as the single source of truth, with 13
golden vectors (`.bin` + language-neutral `.meta.json`).
- **Conformance** — JS / Python / Rust / Go ports verified against the golden
vectors and byte-for-byte round-trip (`encode(decode(golden)) == bytes`).

### Guarantees

- Lossless encoder → file for every value the JS runtime can represent.
- File → other-language decoders is best-effort; unrepresentable types fall back
per `spec/FORMAT.md` §5.

[0.1.0]: https://github.com/Gityosan/greft/releases/tag/v0.1.0
82 changes: 82 additions & 0 deletions js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# greft

Language-agnostic **lossless** binary serializer. Encode values in JavaScript,
decode them in other languages (Python / Rust / Go / …) and use them as-is.

- **Lossless** for everything the JS runtime can represent — cycles, shared
identity, `Map`/`Set` with arbitrary keys, `BigInt`, typed arrays, `Date`,
`RegExp`, `Error`, symbols, and more.
- **Zero runtime dependencies.** No `Buffer` / `structuredClone` / `vm` — only
standard `DataView` / `TextEncoder` / `BigInt`.
- **One format, many readers.** The byte format is a single source of truth
([`spec/FORMAT.md`](https://github.com/Gityosan/greft/blob/main/spec/FORMAT.md)),
verified byte-for-byte across JS / Python / Rust / Go conformance ports.

A primary use case: take JS mock data (e.g. from `zod-v4-mocks`) and reuse it as
test fixtures in other languages.

## Install

```bash
npm add greft # or: pnpm add greft / yarn add greft
```

## Usage

```ts
import { encode, decode } from "greft";

const bytes = encode(value); // value -> Uint8Array (lossless, cycles + shared identity)
const back = decode(bytes); // Uint8Array -> value
```

### Extension types

Losslessly serialize values the core rejects (class instances, domain types, …)
by registering a `TypeExtension`:

```ts
import { encode, decode } from "greft";

const types = [/* TypeExtension[] */];
const bytes = encode(value, { types });
const back = decode(bytes, { types });
```

### Weak collections

`WeakMap` / `WeakSet` contents are supplied explicitly via a `provider`:

```ts
encode(value, { provider });
```

### JSON bridge

Inspect or hand-edit an encoded graph as JSON (identity-lossy; cycles rejected):

```ts
import { toJSON, fromJSON } from "greft";
```

## CLI

```bash
npx graft inspect <file.bin> # tree view + tag histogram
npx graft diff <a.bin> <b.bin> # structural diff of two value graphs
```

## Decode safety

`decode(bytes, { maxNodes })` bounds work; malformed input (out-of-range refs,
counts exceeding the buffer) is rejected rather than trusted.

## Links

- Format spec: [spec/FORMAT.md](https://github.com/Gityosan/greft/blob/main/spec/FORMAT.md)
- Conformance ports (JS / Python / Rust / Go): [conformance/README.md](https://github.com/Gityosan/greft/blob/main/conformance/README.md)
- Changelog: [CHANGELOG.md](https://github.com/Gityosan/greft/blob/main/CHANGELOG.md)

## License

ISC
28 changes: 24 additions & 4 deletions js/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
{
"name": "greft",
"version": "1.0.0",
"description": "",
"keywords": [],
"version": "0.1.0",
"description": "Language-agnostic lossless binary serializer — encode in JS, decode in Python / Rust / Go / …. Zero runtime dependencies.",
"keywords": [
"serialization",
"deserialization",
"binary",
"codec",
"lossless",
"cross-language",
"leb128",
"zigzag",
"structured-clone",
"fixture"
],
"license": "ISC",
"author": "",
"author": "Gityosan (https://github.com/Gityosan)",
"repository": {
"type": "git",
"url": "git+https://github.com/Gityosan/greft.git",
"directory": "js"
},
"bugs": {
"url": "https://github.com/Gityosan/greft/issues"
},
"homepage": "https://github.com/Gityosan/greft#readme",
"bin": {
"graft": "./dist/cli.js"
},
Expand Down
Loading