@emagjby/strata-js 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -0
- package/package.json +28 -28
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# @emagjby/strata-js
|
|
2
|
+
|
|
3
|
+
Deterministic Strata implementation for JavaScript.
|
|
4
|
+
|
|
5
|
+
Strata is a deterministic binary data format with canonical encoding: identical logical values must produce identical bytes (and therefore identical hashes) across all implementations.
|
|
6
|
+
|
|
7
|
+
This package is a **parity implementation** with the Rust reference implementation. If Rust and JavaScript ever disagree, **that is a bug**.
|
|
8
|
+
|
|
9
|
+
- Canonical encoding: one value → one byte representation
|
|
10
|
+
- Hashing: stable hash over canonical bytes (BLAKE3-256)
|
|
11
|
+
- Strata Text (`.st`): human authoring format that compiles to canonical Strata Core Binary (`.scb`)
|
|
12
|
+
|
|
13
|
+
Docs: https://strata.emagjby.com/docs
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
Library:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @emagjby/strata-js
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
CLI:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @emagjby/strata-js
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quickstart (Library)
|
|
30
|
+
|
|
31
|
+
### Parse Strata Text (`.st`) → encode (`.scb`) → hash
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { parse, encodeValue, hashValueHex } from "@emagjby/strata-js";
|
|
35
|
+
|
|
36
|
+
const source = `{
|
|
37
|
+
"name": "alice",
|
|
38
|
+
"active": true,
|
|
39
|
+
"count": 3
|
|
40
|
+
}`;
|
|
41
|
+
|
|
42
|
+
const value = parse(source);
|
|
43
|
+
const scb = encodeValue(value); // Uint8Array canonical bytes
|
|
44
|
+
|
|
45
|
+
// Hashing is defined over canonical bytes.
|
|
46
|
+
console.log(hashValueHex(value));
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Decode `.scb` bytes back into a Strata value
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
import { decodeValue, encodeValue } from "@emagjby/strata-js";
|
|
53
|
+
|
|
54
|
+
// Given canonical bytes (or bytes captured from storage/wire)
|
|
55
|
+
const originalScb = new Uint8Array([0x00]); // example only
|
|
56
|
+
|
|
57
|
+
const value = decodeValue(originalScb);
|
|
58
|
+
const roundtrippedScb = encodeValue(value);
|
|
59
|
+
|
|
60
|
+
// Strata guarantees: decode(encode(value)) == value
|
|
61
|
+
// The reverse is intentionally NOT guaranteed.
|
|
62
|
+
console.log(roundtrippedScb);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Hash a value (canonical re-encode)
|
|
66
|
+
|
|
67
|
+
If you already have a JS `Value` and want a canonical hash:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import { hashValueHex, parse } from "@emagjby/strata-js";
|
|
71
|
+
|
|
72
|
+
const value = parse("[1, 2, 3]");
|
|
73
|
+
console.log(hashValueHex(value));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## CLI
|
|
77
|
+
|
|
78
|
+
The `strata-js` CLI mirrors the Rust CLI.
|
|
79
|
+
|
|
80
|
+
Commands:
|
|
81
|
+
|
|
82
|
+
- `compile` – compile `.st` → canonical `.scb`
|
|
83
|
+
- `decode` – decode `.scb` into a stable inspection format
|
|
84
|
+
- `hash` – compute deterministic hash (BLAKE3-256)
|
|
85
|
+
- `fmt` – parse `.st` and print a structured inspection format
|
|
86
|
+
|
|
87
|
+
### Compile
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
strata-js compile input.st output.scb
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Hash
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
strata-js hash input.st
|
|
97
|
+
strata-js hash input.scb
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Behavior:
|
|
101
|
+
|
|
102
|
+
- If input is `.st`, it is parsed and canonically encoded first
|
|
103
|
+
- If input is `.scb`, bytes are hashed directly
|
|
104
|
+
- Output is lowercase hex
|
|
105
|
+
|
|
106
|
+
### Decode
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
strata-js decode input.scb
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Fmt
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
strata-js fmt input.st
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Exit codes
|
|
119
|
+
|
|
120
|
+
- `0` success
|
|
121
|
+
- `1` invalid input
|
|
122
|
+
- `2` I/O failure
|
|
123
|
+
- `100` internal error
|
|
124
|
+
|
|
125
|
+
## JavaScript value model (important)
|
|
126
|
+
|
|
127
|
+
Strata values in JS are **not JSON** and are intentionally strict.
|
|
128
|
+
|
|
129
|
+
- Integers are `bigint` (JS `number` MUST NOT be used)
|
|
130
|
+
- Bytes are `Uint8Array`
|
|
131
|
+
- Maps are `ReadonlyMap<string, Value>`
|
|
132
|
+
|
|
133
|
+
If you need to bridge into JSON:
|
|
134
|
+
|
|
135
|
+
- `bigint` cannot be directly serialized by `JSON.stringify`
|
|
136
|
+
- You must choose an explicit representation (commonly decimal strings)
|
|
137
|
+
|
|
138
|
+
Type shape (abridged):
|
|
139
|
+
|
|
140
|
+
- `{ kind: "null" }`
|
|
141
|
+
- `{ kind: "bool", value: boolean }`
|
|
142
|
+
- `{ kind: "int", value: bigint }`
|
|
143
|
+
- `{ kind: "string", value: string }`
|
|
144
|
+
- `{ kind: "bytes", value: Uint8Array }`
|
|
145
|
+
- `{ kind: "list", value: readonly Value[] }`
|
|
146
|
+
- `{ kind: "map", value: ReadonlyMap<string, Value> }`
|
|
147
|
+
|
|
148
|
+
## Determinism notes
|
|
149
|
+
|
|
150
|
+
- Hashing is defined over **canonical encoded bytes**, not decoded structures.
|
|
151
|
+
- Decoding exists to inspect reality; encoding defines canonical truth.
|
|
152
|
+
- Map keys are canonically ordered by UTF-8 byte order during encoding.
|
|
153
|
+
|
|
154
|
+
If your system needs “mostly the same bytes”, Strata is not the tool. If it needs _exactly the same bytes_, it is.
|
|
155
|
+
|
|
156
|
+
## Golden vectors
|
|
157
|
+
|
|
158
|
+
Strata correctness is enforced via golden vectors (authored in `.st`) and cross-implementation tests.
|
|
159
|
+
|
|
160
|
+
Golden vectors are not examples; they are law:
|
|
161
|
+
|
|
162
|
+
- If this package disagrees with a golden vector, **the implementation is wrong**.
|
|
163
|
+
- Vectors are not adjusted to match buggy behavior.
|
|
164
|
+
|
|
165
|
+
## What Strata does NOT do
|
|
166
|
+
|
|
167
|
+
Strata intentionally does not provide:
|
|
168
|
+
|
|
169
|
+
- Schemas or validation rules
|
|
170
|
+
- Optional fields or default values
|
|
171
|
+
- Backward-compatible schema evolution
|
|
172
|
+
- Floating point numbers
|
|
173
|
+
- Streaming/framing rules (transport concerns are external)
|
|
174
|
+
- Compression, encryption, or authentication
|
|
175
|
+
|
|
176
|
+
## Links
|
|
177
|
+
|
|
178
|
+
- Documentation: https://strata.emagjby.com/docs
|
|
179
|
+
- Repo: https://github.com/Emagjby/Strata
|
|
180
|
+
- Strata JS package source: https://github.com/Emagjby/Strata/tree/main/strata-js
|
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
2
|
+
"name": "@emagjby/strata-js",
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"strata-js": "./dist/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"test": "tsx --test",
|
|
19
|
+
"check": "tsc --noEmit && npm run test",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^25.0.3",
|
|
24
|
+
"tsx": "^4.21.0",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@noble/hashes": "^2.0.1"
|
|
29
|
+
}
|
|
30
30
|
}
|