@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.
Files changed (2) hide show
  1. package/README.md +180 -0
  2. 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
- "name": "@emagjby/strata-js",
3
- "version": "0.3.1",
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
- }
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
  }