npm package: @openai-hce/decode
Description: HCE (Hierarchical Columnar Encoding) decoder for converting HCE back to JSON
Author: OpenAI HCE Team
Latest version: 1.0.3

# @openai-hce/decode

Decoder for Hierarchical Columnar Encoding (HCE). Converts HCE strings generated by [`@openai-hce/encode`](../encode/README.md) back into JSON objects with full fidelity.

## Installation

```bash
npm install @openai-hce/decode
```

```bash
pnpm add @openai-hce/decode
yarn add @openai-hce/decode
```

## Quick start

```ts
import { HCEDecoder } from '@openai-hce/decode';

const hce = `users(user)[2]:
	user(id,name,role)[2]:
		1,Alice,admin|2,Bob,user`;

const decoder = new HCEDecoder();
const data = decoder.decode(hce);

console.log(data.users[0].name); // "Alice"
```

## Highlights

- Lossless round-trip with the encoder package.
- Automatic type inference (numbers, booleans, null, arrays).
- Supports nested objects via dotted paths.
- Matches any delimiter configuration used during encoding.
- Lightweight TypeScript implementation with zero dependencies.

## API overview

### `new HCEDecoder(options?: HCEDecodeOptions)`

```ts
interface HCEDecodeOptions {
	fieldDelimiter?: string;  // default: ','
	recordDelimiter?: string; // default: '|'
	nestedDelimiter?: string; // default: ';'
	missingValue?: string;    // default: ' '
	typeField?: string;       // default: 'type'
}
```

### `decoder.decode(hce: string)`

- Accepts an HCE string.
- Returns an object where each key is a root group and each value is an array of reconstructed JSON objects.

```ts
const result = decoder.decode(hce);
const users = result.users; // array
```

## Examples

### Default decoding

```ts
const hce = `entities(user,org)[3]:
	user(id,name,email)[2]:
		1,Alice,alice@example.com|2,Bob,bob@example.com
	org(id,name,industry)[1]:
		10,Acme,Tech`;

const { entities } = new HCEDecoder().decode(hce);
```

Result:
```json
[
	{ "type": "user", "id": 1, "name": "Alice", "email": "alice@example.com" },
	{ "type": "user", "id": 2, "name": "Bob", "email": "bob@example.com" },
	{ "type": "org", "id": 10, "name": "Acme", "industry": "Tech" }
]
```

### Restoring secondary grouping

```ts
const grouped = `users(user by role)[3]:
	admin(id,name)[2]:
		1,Alice|2,Bob
	guest(id,name)[1]:
		3,Carol`;

const { users } = new HCEDecoder().decode(grouped);
```

Result:
```json
[
	{ "type": "user", "role": "admin", "id": 1, "name": "Alice" },
	{ "type": "user", "role": "admin", "id": 2, "name": "Bob" },
	{ "type": "user", "role": "guest", "id": 3, "name": "Carol" }
]
```

### Nested objects and arrays

```ts
const nested = `posts(post)[2]:
	post(id,title,.author,.tags)[2]:
		1,'Hello World'|2,'Encoder Tips'
		.author(name,team)[2]:
			Alice,Platform|Bob,SDK
		.tags: intro;hce|guide`;

const { posts } = new HCEDecoder().decode(nested);
```

Result:
```json
[
	{
		"type": "post",
		"id": 1,
		"title": "Hello World",
		"author": { "name": "Alice", "team": "Platform" },
		"tags": ["intro", "hce"]
	},
	{
		"type": "post",
		"id": 2,
		"title": "Encoder Tips",
		"author": { "name": "Bob", "team": "SDK" },
		"tags": ["guide"]
	}
]
```

### Type-only grouping is implicit

```ts
const hce = `products(product)[2]:
	product(name,price)[2]:
		Laptop,999|Phone,599`;

const { products } = new HCEDecoder().decode(hce);
```

Result:
```json
[
	{ "type": "product", "name": "Laptop", "price": 999 },
	{ "type": "product", "name": "Phone", "price": 599 }
]
```

### Secondary grouping reconstruction

```ts
const grouped = `products(product by category)[4]:
	Electronics(name,price)[2]:
		Laptop,999|Phone,599
	Books(name,price)[2]:
		JS Guide,39|TS Handbook,45`;

const { products } = new HCEDecoder().decode(grouped);
```

Result:
```json
[
	{ "type": "product", "category": "Electronics", "name": "Laptop", "price": 999 },
	{ "type": "product", "category": "Electronics", "name": "Phone", "price": 599 },
	{ "type": "product", "category": "Books", "name": "JS Guide", "price": 39 },
	{ "type": "product", "category": "Books", "name": "TS Handbook", "price": 45 }
]
```

### Uniform schema stays merged

```ts
const hce = `users(user)[3]:
	user(age,name,role)[3]:
		30,Alice,admin|25,Bob,admin|35,Charlie,user`;

const { users } = new HCEDecoder().decode(hce);
```

Result:
```json
[
	{ "type": "user", "age": 30, "name": "Alice", "role": "admin" },
	{ "type": "user", "age": 25, "name": "Bob", "role": "admin" },
	{ "type": "user", "age": 35, "name": "Charlie", "role": "user" }
]
```

### Multi-type collections

```ts
const hce = `items(book,product,service)[3]:
	book(pages,title)[1]:
		200,HCE Guide
	product(name,price)[1]:
		Laptop,999
	service(name,rate)[1]:
		Consulting,150`;

const { items } = new HCEDecoder().decode(hce);
```

The type-only header lists every type value, which the decoder maps back to `type` fields.

Result:
```json
[
	{ "type": "book", "pages": 200, "title": "HCE Guide" },
	{ "type": "product", "name": "Laptop", "price": 999 },
	{ "type": "service", "name": "Consulting", "rate": 150 }
]
```

### Edge case: single secondary value

```ts
const hce = `users(user)[2]:
	user(name,role)[2]:
		Alice,admin|Bob,admin`;

const { users } = new HCEDecoder().decode(hce);
```

Result:
```json
[
	{ "type": "user", "name": "Alice", "role": "admin" },
	{ "type": "user", "name": "Bob", "role": "admin" }
]
```

### Edge case: no type column provided

```ts
const hce = `products(name,price)[2]:
	Laptop,999|Phone,599`;

const { products } = new HCEDecoder().decode(hce);
```

Result:
```json
[
	{ "name": "Laptop", "price": 999 },
	{ "name": "Phone", "price": 599 }
]
```

### Custom delimiters

```ts
const hce = `rows(row)[1]:
	row(id	value)[1]:
		1	A`;

const decoder = new HCEDecoder({
	fieldDelimiter: '\t',
	recordDelimiter: '\n',
	nestedDelimiter: ',',
});

const { rows } = decoder.decode(hce);
```

Result:
```json
[
	{ "type": "row", "id": 1, "value": "A" }
]
```

### Type inference reference

| HCE token | Parsed JSON value |
|-----------|-------------------|
| `123` | `123` (number) |
| `45.67` | `45.67` (number) |
| `true` / `false` | boolean |
| `null` | `null` |
| `'quoted text'` | `"quoted text"` |
| `unquoted` | `"unquoted"` (string) |
| `1;2;3` | `[1, 2, 3]` (array) |
| *(space)* | omitted / `undefined` |

## License

MIT © OpenAI HCE Team