@geoprotocol/grc-20 0.1.0
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/dist/builder/edit.d.ts +107 -0
- package/dist/builder/edit.d.ts.map +1 -0
- package/dist/builder/edit.js +221 -0
- package/dist/builder/edit.js.map +1 -0
- package/dist/builder/entity.d.ts +62 -0
- package/dist/builder/entity.d.ts.map +1 -0
- package/dist/builder/entity.js +126 -0
- package/dist/builder/entity.js.map +1 -0
- package/dist/builder/index.d.ts +5 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +5 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/relation.d.ts +66 -0
- package/dist/builder/relation.d.ts.map +1 -0
- package/dist/builder/relation.js +114 -0
- package/dist/builder/relation.js.map +1 -0
- package/dist/builder/update.d.ts +90 -0
- package/dist/builder/update.d.ts.map +1 -0
- package/dist/builder/update.js +174 -0
- package/dist/builder/update.js.map +1 -0
- package/dist/codec/edit.d.ts +17 -0
- package/dist/codec/edit.d.ts.map +1 -0
- package/dist/codec/edit.js +393 -0
- package/dist/codec/edit.js.map +1 -0
- package/dist/codec/index.d.ts +3 -0
- package/dist/codec/index.d.ts.map +1 -0
- package/dist/codec/index.js +3 -0
- package/dist/codec/index.js.map +1 -0
- package/dist/codec/op.d.ts +27 -0
- package/dist/codec/op.d.ts.map +1 -0
- package/dist/codec/op.js +333 -0
- package/dist/codec/op.js.map +1 -0
- package/dist/codec/primitives.d.ts +138 -0
- package/dist/codec/primitives.d.ts.map +1 -0
- package/dist/codec/primitives.js +285 -0
- package/dist/codec/primitives.js.map +1 -0
- package/dist/codec/value.d.ts +41 -0
- package/dist/codec/value.d.ts.map +1 -0
- package/dist/codec/value.js +202 -0
- package/dist/codec/value.js.map +1 -0
- package/dist/genesis/index.d.ts +109 -0
- package/dist/genesis/index.d.ts.map +1 -0
- package/dist/genesis/index.js +183 -0
- package/dist/genesis/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/test/basic.test.d.ts +2 -0
- package/dist/test/basic.test.d.ts.map +1 -0
- package/dist/test/basic.test.js +270 -0
- package/dist/test/basic.test.js.map +1 -0
- package/dist/types/edit.d.ts +46 -0
- package/dist/types/edit.d.ts.map +1 -0
- package/dist/types/edit.js +13 -0
- package/dist/types/edit.js.map +1 -0
- package/dist/types/id.d.ts +32 -0
- package/dist/types/id.d.ts.map +1 -0
- package/dist/types/id.js +45 -0
- package/dist/types/id.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/op.d.ts +147 -0
- package/dist/types/op.d.ts.map +1 -0
- package/dist/types/op.js +60 -0
- package/dist/types/op.js.map +1 -0
- package/dist/types/value.d.ts +107 -0
- package/dist/types/value.d.ts.map +1 -0
- package/dist/types/value.js +126 -0
- package/dist/types/value.js.map +1 -0
- package/dist/util/id.d.ts +51 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +215 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +2 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +68 -0
- package/readme.md +232 -0
package/dist/util/id.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { createId } from "../types/id.js";
|
|
2
|
+
/**
|
|
3
|
+
* Formats a UUID as non-hyphenated lowercase hex (recommended display format).
|
|
4
|
+
*/
|
|
5
|
+
export function formatId(id) {
|
|
6
|
+
let s = "";
|
|
7
|
+
for (let i = 0; i < 16; i++) {
|
|
8
|
+
s += id[i].toString(16).padStart(2, "0");
|
|
9
|
+
}
|
|
10
|
+
return s;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parses a UUID from hex string (with or without hyphens).
|
|
14
|
+
* Returns undefined if the string is invalid.
|
|
15
|
+
*/
|
|
16
|
+
export function parseId(s) {
|
|
17
|
+
// Remove hyphens if present
|
|
18
|
+
const hex = s.replace(/-/g, "").toLowerCase();
|
|
19
|
+
if (hex.length !== 32) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
const bytes = new Uint8Array(16);
|
|
23
|
+
for (let i = 0; i < 16; i++) {
|
|
24
|
+
const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
25
|
+
if (Number.isNaN(byte)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
bytes[i] = byte;
|
|
29
|
+
}
|
|
30
|
+
return createId(bytes);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Generates a random UUIDv4.
|
|
34
|
+
*/
|
|
35
|
+
export function randomId() {
|
|
36
|
+
const bytes = new Uint8Array(16);
|
|
37
|
+
crypto.getRandomValues(bytes);
|
|
38
|
+
// Set version 4 (0100 in bits 4-7 of byte 6)
|
|
39
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
40
|
+
// Set RFC 4122 variant (10 in bits 6-7 of byte 8)
|
|
41
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
42
|
+
return createId(bytes);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* SHA-256 hash function using Web Crypto API.
|
|
46
|
+
* Works in both Node.js and browsers.
|
|
47
|
+
*/
|
|
48
|
+
async function sha256(data) {
|
|
49
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
50
|
+
return new Uint8Array(hashBuffer);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Synchronous SHA-256 implementation for environments where async is not ideal.
|
|
54
|
+
* Uses a pure JavaScript implementation.
|
|
55
|
+
*/
|
|
56
|
+
function sha256Sync(data) {
|
|
57
|
+
// SHA-256 constants
|
|
58
|
+
const K = new Uint32Array([
|
|
59
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
|
60
|
+
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
61
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
|
62
|
+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
63
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
|
64
|
+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
65
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
|
66
|
+
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
67
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
|
68
|
+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
69
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
70
|
+
]);
|
|
71
|
+
// Initial hash values
|
|
72
|
+
let h0 = 0x6a09e667;
|
|
73
|
+
let h1 = 0xbb67ae85;
|
|
74
|
+
let h2 = 0x3c6ef372;
|
|
75
|
+
let h3 = 0xa54ff53a;
|
|
76
|
+
let h4 = 0x510e527f;
|
|
77
|
+
let h5 = 0x9b05688c;
|
|
78
|
+
let h6 = 0x1f83d9ab;
|
|
79
|
+
let h7 = 0x5be0cd19;
|
|
80
|
+
// Pre-processing: adding padding bits
|
|
81
|
+
const bitLen = data.length * 8;
|
|
82
|
+
const paddedLen = Math.ceil((data.length + 9) / 64) * 64;
|
|
83
|
+
const padded = new Uint8Array(paddedLen);
|
|
84
|
+
padded.set(data);
|
|
85
|
+
padded[data.length] = 0x80;
|
|
86
|
+
// Append original length in bits as 64-bit big-endian
|
|
87
|
+
const view = new DataView(padded.buffer);
|
|
88
|
+
view.setUint32(paddedLen - 4, bitLen, false);
|
|
89
|
+
// Process each 64-byte chunk
|
|
90
|
+
const W = new Uint32Array(64);
|
|
91
|
+
for (let offset = 0; offset < paddedLen; offset += 64) {
|
|
92
|
+
// Copy chunk into first 16 words
|
|
93
|
+
for (let i = 0; i < 16; i++) {
|
|
94
|
+
W[i] = view.getUint32(offset + i * 4, false);
|
|
95
|
+
}
|
|
96
|
+
// Extend the first 16 words into the remaining 48 words
|
|
97
|
+
for (let i = 16; i < 64; i++) {
|
|
98
|
+
const s0 = ((W[i - 15] >>> 7) | (W[i - 15] << 25)) ^
|
|
99
|
+
((W[i - 15] >>> 18) | (W[i - 15] << 14)) ^
|
|
100
|
+
(W[i - 15] >>> 3);
|
|
101
|
+
const s1 = ((W[i - 2] >>> 17) | (W[i - 2] << 15)) ^
|
|
102
|
+
((W[i - 2] >>> 19) | (W[i - 2] << 13)) ^
|
|
103
|
+
(W[i - 2] >>> 10);
|
|
104
|
+
W[i] = (W[i - 16] + s0 + W[i - 7] + s1) >>> 0;
|
|
105
|
+
}
|
|
106
|
+
// Initialize working variables
|
|
107
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
|
|
108
|
+
// Compression function main loop
|
|
109
|
+
for (let i = 0; i < 64; i++) {
|
|
110
|
+
const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
|
|
111
|
+
const ch = (e & f) ^ (~e & g);
|
|
112
|
+
const temp1 = (h + S1 + ch + K[i] + W[i]) >>> 0;
|
|
113
|
+
const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
|
|
114
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
115
|
+
const temp2 = (S0 + maj) >>> 0;
|
|
116
|
+
h = g;
|
|
117
|
+
g = f;
|
|
118
|
+
f = e;
|
|
119
|
+
e = (d + temp1) >>> 0;
|
|
120
|
+
d = c;
|
|
121
|
+
c = b;
|
|
122
|
+
b = a;
|
|
123
|
+
a = (temp1 + temp2) >>> 0;
|
|
124
|
+
}
|
|
125
|
+
// Add the compressed chunk to the current hash value
|
|
126
|
+
h0 = (h0 + a) >>> 0;
|
|
127
|
+
h1 = (h1 + b) >>> 0;
|
|
128
|
+
h2 = (h2 + c) >>> 0;
|
|
129
|
+
h3 = (h3 + d) >>> 0;
|
|
130
|
+
h4 = (h4 + e) >>> 0;
|
|
131
|
+
h5 = (h5 + f) >>> 0;
|
|
132
|
+
h6 = (h6 + g) >>> 0;
|
|
133
|
+
h7 = (h7 + h) >>> 0;
|
|
134
|
+
}
|
|
135
|
+
// Produce the final hash value (big-endian)
|
|
136
|
+
const result = new Uint8Array(32);
|
|
137
|
+
const resultView = new DataView(result.buffer);
|
|
138
|
+
resultView.setUint32(0, h0, false);
|
|
139
|
+
resultView.setUint32(4, h1, false);
|
|
140
|
+
resultView.setUint32(8, h2, false);
|
|
141
|
+
resultView.setUint32(12, h3, false);
|
|
142
|
+
resultView.setUint32(16, h4, false);
|
|
143
|
+
resultView.setUint32(20, h5, false);
|
|
144
|
+
resultView.setUint32(24, h6, false);
|
|
145
|
+
resultView.setUint32(28, h7, false);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Derives a UUIDv8 from input bytes using SHA-256.
|
|
150
|
+
*
|
|
151
|
+
* This implements the `derived_uuid` function from spec Section 2.1:
|
|
152
|
+
* ```
|
|
153
|
+
* hash = SHA-256(input_bytes)[0:16]
|
|
154
|
+
* hash[6] = (hash[6] & 0x0F) | 0x80 // version 8
|
|
155
|
+
* hash[8] = (hash[8] & 0x3F) | 0x80 // RFC 4122 variant
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export function derivedUuid(input) {
|
|
159
|
+
const hash = sha256Sync(input);
|
|
160
|
+
const id = new Uint8Array(16);
|
|
161
|
+
id.set(hash.subarray(0, 16));
|
|
162
|
+
// Set version 8 (1000 in bits 4-7 of byte 6)
|
|
163
|
+
id[6] = (id[6] & 0x0f) | 0x80;
|
|
164
|
+
// Set RFC 4122 variant (10 in bits 6-7 of byte 8)
|
|
165
|
+
id[8] = (id[8] & 0x3f) | 0x80;
|
|
166
|
+
return createId(id);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Async version of derivedUuid using Web Crypto API.
|
|
170
|
+
*/
|
|
171
|
+
export async function derivedUuidAsync(input) {
|
|
172
|
+
const hash = await sha256(input);
|
|
173
|
+
const id = new Uint8Array(16);
|
|
174
|
+
id.set(hash.subarray(0, 16));
|
|
175
|
+
// Set version 8 (1000 in bits 4-7 of byte 6)
|
|
176
|
+
id[6] = (id[6] & 0x0f) | 0x80;
|
|
177
|
+
// Set RFC 4122 variant (10 in bits 6-7 of byte 8)
|
|
178
|
+
id[8] = (id[8] & 0x3f) | 0x80;
|
|
179
|
+
return createId(id);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Derives a UUIDv8 from a string using SHA-256.
|
|
183
|
+
*/
|
|
184
|
+
export function derivedUuidFromString(input) {
|
|
185
|
+
return derivedUuid(new TextEncoder().encode(input));
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Derives a unique-mode relation ID.
|
|
189
|
+
*
|
|
190
|
+
* ```
|
|
191
|
+
* id = derived_uuid(from_id || to_id || type_id)
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export function uniqueRelationId(fromId, toId, typeId) {
|
|
195
|
+
const input = new Uint8Array(48);
|
|
196
|
+
input.set(fromId, 0);
|
|
197
|
+
input.set(toId, 16);
|
|
198
|
+
input.set(typeId, 32);
|
|
199
|
+
return derivedUuid(input);
|
|
200
|
+
}
|
|
201
|
+
const RELATION_ENTITY_PREFIX = new TextEncoder().encode("grc20:relation-entity:");
|
|
202
|
+
/**
|
|
203
|
+
* Derives the reified entity ID from a relation ID.
|
|
204
|
+
*
|
|
205
|
+
* ```
|
|
206
|
+
* entity_id = derived_uuid("grc20:relation-entity:" || relation_id)
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
export function relationEntityId(relationId) {
|
|
210
|
+
const input = new Uint8Array(RELATION_ENTITY_PREFIX.length + 16);
|
|
211
|
+
input.set(RELATION_ENTITY_PREFIX, 0);
|
|
212
|
+
input.set(relationId, RELATION_ENTITY_PREFIX.length);
|
|
213
|
+
return derivedUuid(input);
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@geoprotocol/grc-20",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GRC-20 TypeScript library for binary property graph encoding/decoding",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"import": "./dist/types/index.js",
|
|
15
|
+
"types": "./dist/types/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./builder": {
|
|
18
|
+
"import": "./dist/builder/index.js",
|
|
19
|
+
"types": "./dist/builder/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./codec": {
|
|
22
|
+
"import": "./dist/codec/index.js",
|
|
23
|
+
"types": "./dist/codec/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./genesis": {
|
|
26
|
+
"import": "./dist/genesis/index.js",
|
|
27
|
+
"types": "./dist/genesis/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./util": {
|
|
30
|
+
"import": "./dist/util/index.js",
|
|
31
|
+
"types": "./dist/util/index.d.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"test:browser": "vitest run --config vitest.browser.config.ts",
|
|
42
|
+
"test:all": "npm run test && npm run test:browser",
|
|
43
|
+
"bundle:analyze": "node scripts/bundle-analyze.js",
|
|
44
|
+
"demo": "npx serve .",
|
|
45
|
+
"lint": "eslint src --ext .ts",
|
|
46
|
+
"prepublishOnly": "npm run build"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"grc-20",
|
|
50
|
+
"graph",
|
|
51
|
+
"knowledge-graph",
|
|
52
|
+
"binary-format",
|
|
53
|
+
"encoding"
|
|
54
|
+
],
|
|
55
|
+
"author": "Geo Browser",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^20.11.0",
|
|
59
|
+
"@vitest/browser": "^1.2.0",
|
|
60
|
+
"esbuild": "^0.20.0",
|
|
61
|
+
"playwright": "^1.41.0",
|
|
62
|
+
"typescript": "^5.3.3",
|
|
63
|
+
"vitest": "^1.2.0"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=18"
|
|
67
|
+
}
|
|
68
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# @geoprotocol/grc-20
|
|
2
|
+
|
|
3
|
+
TypeScript library for encoding and decoding GRC-20 binary property graph data.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @geoprotocol/grc-20
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import {
|
|
15
|
+
EditBuilder,
|
|
16
|
+
encodeEdit,
|
|
17
|
+
decodeEdit,
|
|
18
|
+
randomId,
|
|
19
|
+
properties,
|
|
20
|
+
} from "@geoprotocol/grc-20";
|
|
21
|
+
|
|
22
|
+
// Create an edit with an entity
|
|
23
|
+
const edit = new EditBuilder(randomId())
|
|
24
|
+
.setName("Create Alice")
|
|
25
|
+
.addAuthor(randomId())
|
|
26
|
+
.setCreatedNow()
|
|
27
|
+
.createEntity(randomId(), (e) =>
|
|
28
|
+
e
|
|
29
|
+
.text(properties.name(), "Alice", undefined)
|
|
30
|
+
.text(properties.description(), "A person", undefined)
|
|
31
|
+
)
|
|
32
|
+
.build();
|
|
33
|
+
|
|
34
|
+
// Encode to binary
|
|
35
|
+
const bytes = encodeEdit(edit);
|
|
36
|
+
|
|
37
|
+
// Decode back
|
|
38
|
+
const decoded = decodeEdit(bytes);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- **Type-safe API** - Full TypeScript definitions
|
|
44
|
+
- **Builder pattern** - Fluent API for constructing edits
|
|
45
|
+
- **Binary codec** - Pure TypeScript encoder/decoder (no WASM)
|
|
46
|
+
- **Tree-shakeable** - Separate entry points for minimal bundles
|
|
47
|
+
- **Cross-platform** - Works in Node.js and browsers
|
|
48
|
+
|
|
49
|
+
## Bundle Sizes
|
|
50
|
+
|
|
51
|
+
| Entry Point | Gzipped |
|
|
52
|
+
|-------------|---------|
|
|
53
|
+
| Full library | ~8.7 KB |
|
|
54
|
+
| Types only | ~1.4 KB |
|
|
55
|
+
| Builder only | ~1.2 KB |
|
|
56
|
+
| Codec only | ~4.8 KB |
|
|
57
|
+
| Genesis IDs | ~1.9 KB |
|
|
58
|
+
| Utilities | ~1.6 KB |
|
|
59
|
+
|
|
60
|
+
### Lazy Loading
|
|
61
|
+
|
|
62
|
+
For optimal initial load, import the codec separately:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Initial load (~4.6 KB gzipped)
|
|
66
|
+
import { EditBuilder, randomId, properties } from "@geoprotocol/grc-20/builder";
|
|
67
|
+
import { properties } from "@geoprotocol/grc-20/genesis";
|
|
68
|
+
|
|
69
|
+
// Lazy load codec when needed (~4.8 KB gzipped)
|
|
70
|
+
const { encodeEdit } = await import("@geoprotocol/grc-20/codec");
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API Reference
|
|
74
|
+
|
|
75
|
+
### Types
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import {
|
|
79
|
+
Id, // 16-byte UUID (Uint8Array branded type)
|
|
80
|
+
Edit, // Batch of operations with metadata
|
|
81
|
+
Op, // Union of all operation types
|
|
82
|
+
Value, // Union of all value types
|
|
83
|
+
DataType, // Enum: Bool, Int64, Float64, Text, etc.
|
|
84
|
+
PropertyValue, // Property ID + Value pair
|
|
85
|
+
} from "@geoprotocol/grc-20";
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Builders
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import {
|
|
92
|
+
EditBuilder, // Build Edit objects
|
|
93
|
+
EntityBuilder, // Build entity values
|
|
94
|
+
UpdateEntityBuilder, // Build update operations
|
|
95
|
+
RelationBuilder, // Build relation operations
|
|
96
|
+
} from "@geoprotocol/grc-20";
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### EditBuilder
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const edit = new EditBuilder(editId)
|
|
103
|
+
.setName("My Edit")
|
|
104
|
+
.addAuthor(authorId)
|
|
105
|
+
.setCreatedAt(BigInt(Date.now()) * 1000n) // microseconds
|
|
106
|
+
.createEntity(entityId, e => e
|
|
107
|
+
.text(propId, "value", languageId)
|
|
108
|
+
.int64(propId, 42n, unitId)
|
|
109
|
+
.float64(propId, 3.14, undefined)
|
|
110
|
+
.bool(propId, true)
|
|
111
|
+
.bytes(propId, new Uint8Array([1, 2, 3]))
|
|
112
|
+
.point(propId, 40.7128, -74.006)
|
|
113
|
+
.date(propId, "2024-01-15")
|
|
114
|
+
.timestamp(propId, 1704067200000000n)
|
|
115
|
+
)
|
|
116
|
+
.updateEntity(entityId, u => u
|
|
117
|
+
.setText(propId, "new value", undefined)
|
|
118
|
+
.unsetAll(propId)
|
|
119
|
+
)
|
|
120
|
+
.deleteEntity(entityId)
|
|
121
|
+
.restoreEntity(entityId)
|
|
122
|
+
.createRelationUnique(fromId, toId, relationTypeId)
|
|
123
|
+
.createRelationMany(relationId, fromId, toId, relationTypeId)
|
|
124
|
+
.deleteRelation(relationId)
|
|
125
|
+
.createProperty(propId, DataType.Text)
|
|
126
|
+
.build();
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Codec
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { encodeEdit, decodeEdit } from "@geoprotocol/grc-20";
|
|
133
|
+
|
|
134
|
+
// Encode
|
|
135
|
+
const bytes = encodeEdit(edit);
|
|
136
|
+
const bytesCanonical = encodeEdit(edit, { canonical: true });
|
|
137
|
+
|
|
138
|
+
// Decode
|
|
139
|
+
const edit = decodeEdit(bytes);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### ID Utilities
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import {
|
|
146
|
+
randomId, // Generate random UUIDv4
|
|
147
|
+
parseId, // Parse hex string to Id
|
|
148
|
+
formatId, // Format Id as hex string
|
|
149
|
+
derivedUuid, // Derive UUIDv8 from bytes (SHA-256)
|
|
150
|
+
derivedUuidFromString,
|
|
151
|
+
uniqueRelationId, // Derive relation ID from endpoints
|
|
152
|
+
relationEntityId, // Derive entity ID from relation ID
|
|
153
|
+
idsEqual, // Compare two Ids
|
|
154
|
+
NIL_ID, // Zero UUID
|
|
155
|
+
} from "@geoprotocol/grc-20";
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Genesis IDs
|
|
159
|
+
|
|
160
|
+
Well-known IDs from the Genesis Space:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { properties, types, relationTypes, languages } from "@geoprotocol/grc-20";
|
|
164
|
+
|
|
165
|
+
// Properties
|
|
166
|
+
properties.name() // Name (TEXT)
|
|
167
|
+
properties.description() // Description (TEXT)
|
|
168
|
+
properties.avatar() // Avatar URL (TEXT)
|
|
169
|
+
properties.url() // External URL (TEXT)
|
|
170
|
+
properties.created() // Creation time (TIMESTAMP)
|
|
171
|
+
properties.modified() // Last modified (TIMESTAMP)
|
|
172
|
+
|
|
173
|
+
// Types
|
|
174
|
+
types.person()
|
|
175
|
+
types.organization()
|
|
176
|
+
types.place()
|
|
177
|
+
types.topic()
|
|
178
|
+
|
|
179
|
+
// Relation Types
|
|
180
|
+
relationTypes.types() // Type membership
|
|
181
|
+
relationTypes.partOf() // Composition
|
|
182
|
+
relationTypes.relatedTo() // Generic association
|
|
183
|
+
|
|
184
|
+
// Languages
|
|
185
|
+
languages.english() // or languages.fromCode("en")
|
|
186
|
+
languages.spanish()
|
|
187
|
+
languages.french()
|
|
188
|
+
// ... etc
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Entry Points
|
|
192
|
+
|
|
193
|
+
For tree-shaking, use specific entry points:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { ... } from "@geoprotocol/grc-20"; // Full library
|
|
197
|
+
import { ... } from "@geoprotocol/grc-20/types"; // Types only
|
|
198
|
+
import { ... } from "@geoprotocol/grc-20/builder"; // Builders only
|
|
199
|
+
import { ... } from "@geoprotocol/grc-20/codec"; // Codec only
|
|
200
|
+
import { ... } from "@geoprotocol/grc-20/genesis"; // Genesis IDs only
|
|
201
|
+
import { ... } from "@geoprotocol/grc-20/util"; // Utilities only
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Development
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Install dependencies
|
|
208
|
+
npm install
|
|
209
|
+
|
|
210
|
+
# Build
|
|
211
|
+
npm run build
|
|
212
|
+
|
|
213
|
+
# Test (Node.js)
|
|
214
|
+
npm test
|
|
215
|
+
|
|
216
|
+
# Test (Browser via Playwright)
|
|
217
|
+
npm run test:browser
|
|
218
|
+
|
|
219
|
+
# Test both
|
|
220
|
+
npm run test:all
|
|
221
|
+
|
|
222
|
+
# Analyze bundle sizes
|
|
223
|
+
npm run bundle:analyze
|
|
224
|
+
|
|
225
|
+
# Run browser demo
|
|
226
|
+
npm run demo
|
|
227
|
+
# Then open http://localhost:3000/examples/browser-demo.html
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT
|