genome 1.0.0 → 1.0.3

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.
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Compares two structure ID strings and returns a similarity score
3
+ * between 0.0 (completely different) and 1.0 (identical).
4
+ *
5
+ * ```js
6
+ * import { compare } from 'genome'
7
+ * const score = compare("L0:100-L1:200", "L0:100-L1:200") // 1.0
8
+ * ```
9
+ * @param {string} id_a
10
+ * @param {string} id_b
11
+ * @returns {number}
12
+ */
13
+ export function compare(id_a, id_b) {
14
+ const ptr0 = passStringToWasm0(id_a, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
15
+ const len0 = WASM_VECTOR_LEN;
16
+ const ptr1 = passStringToWasm0(id_b, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
17
+ const len1 = WASM_VECTOR_LEN;
18
+ const ret = wasm.compare(ptr0, len0, ptr1, len1);
19
+ return ret;
20
+ }
21
+
22
+ /**
23
+ * Compares two JSON strings structurally and returns a similarity score.
24
+ *
25
+ * ```js
26
+ * import { compareValues } from 'genome'
27
+ * const score = compareValues(
28
+ * JSON.stringify({ id: 1, name: "alice" }),
29
+ * JSON.stringify({ id: 2, name: "bob" }),
30
+ * ) // 1.0 — same structure
31
+ * ```
32
+ * @param {string} a
33
+ * @param {string} b
34
+ * @returns {number}
35
+ */
36
+ export function compareValues(a, b) {
37
+ const ptr0 = passStringToWasm0(a, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
38
+ const len0 = WASM_VECTOR_LEN;
39
+ const ptr1 = passStringToWasm0(b, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
40
+ const len1 = WASM_VECTOR_LEN;
41
+ const ret = wasm.compareValues(ptr0, len0, ptr1, len1);
42
+ if (ret[2]) {
43
+ throw takeFromExternrefTable0(ret[1]);
44
+ }
45
+ return ret[0];
46
+ }
47
+
48
+ /**
49
+ * Generates a deterministic hierarchical structure ID for a JSON string.
50
+ *
51
+ * ```js
52
+ * import { hash } from 'genome'
53
+ * const id = hash(JSON.stringify({ id: 1, name: "alice" }))
54
+ * ```
55
+ * @param {string} json
56
+ * @returns {string}
57
+ */
58
+ export function hash(json) {
59
+ let deferred3_0;
60
+ let deferred3_1;
61
+ try {
62
+ const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
63
+ const len0 = WASM_VECTOR_LEN;
64
+ const ret = wasm.hash(ptr0, len0);
65
+ var ptr2 = ret[0];
66
+ var len2 = ret[1];
67
+ if (ret[3]) {
68
+ ptr2 = 0; len2 = 0;
69
+ throw takeFromExternrefTable0(ret[2]);
70
+ }
71
+ deferred3_0 = ptr2;
72
+ deferred3_1 = len2;
73
+ return getStringFromWasm0(ptr2, len2);
74
+ } finally {
75
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Hashes a string with xxHash32 and returns a hex string.
81
+ *
82
+ * ```js
83
+ * import { hashStr } from 'genome'
84
+ * const hex = hashStr("hello", 0)
85
+ * ```
86
+ * @param {string} input
87
+ * @param {number} seed
88
+ * @returns {string}
89
+ */
90
+ export function hashStr(input, seed) {
91
+ let deferred2_0;
92
+ let deferred2_1;
93
+ try {
94
+ const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
95
+ const len0 = WASM_VECTOR_LEN;
96
+ const ret = wasm.hashStr(ptr0, len0, seed);
97
+ deferred2_0 = ret[0];
98
+ deferred2_1 = ret[1];
99
+ return getStringFromWasm0(ret[0], ret[1]);
100
+ } finally {
101
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Resets all internal state — clears the key cache and collision counters.
107
+ *
108
+ * ```js
109
+ * import { reset } from 'genome'
110
+ * reset()
111
+ * ```
112
+ */
113
+ export function reset() {
114
+ wasm.reset();
115
+ }
116
+
117
+ /**
118
+ * Seeds the collision counter for a known signature.
119
+ * Use this to restore persisted counter state.
120
+ *
121
+ * ```js
122
+ * import { seed } from 'genome'
123
+ * seed("L1:12345-L2:67890", 3n)
124
+ * ```
125
+ * @param {string} signature
126
+ * @param {bigint} count
127
+ */
128
+ export function seed(signature, count) {
129
+ const ptr0 = passStringToWasm0(signature, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
130
+ const len0 = WASM_VECTOR_LEN;
131
+ wasm.seed(ptr0, len0, count);
132
+ }
133
+
134
+ /**
135
+ * Sets the global config. Call this before using any other functions
136
+ * if you need non-default behaviour.
137
+ *
138
+ * ```js
139
+ * import { setConfig, hash } from 'genome'
140
+ *
141
+ * setConfig({ ignoreArrayLength: true, ignoreValueTypes: true })
142
+ * const id = hash(JSON.stringify({ items: [1, 2, 3] }))
143
+ * ```
144
+ * @param {boolean} new_id_on_collision
145
+ * @param {boolean} ignore_array_length
146
+ * @param {boolean} ignore_value_types
147
+ */
148
+ export function setConfig(new_id_on_collision, ignore_array_length, ignore_value_types) {
149
+ wasm.setConfig(new_id_on_collision, ignore_array_length, ignore_value_types);
150
+ }
151
+
152
+ /**
153
+ * Returns the structural signature for a JSON string.
154
+ *
155
+ * In default mode returns the full ID. When `newIdOnCollision` is true
156
+ * (set via `setConfig`), strips L0 and returns L1+ only.
157
+ *
158
+ * ```js
159
+ * import { signature } from 'genome'
160
+ * const sig = signature(JSON.stringify({ id: 1, name: "alice" }))
161
+ * ```
162
+ * @param {string} json
163
+ * @returns {string}
164
+ */
165
+ export function signature(json) {
166
+ let deferred3_0;
167
+ let deferred3_1;
168
+ try {
169
+ const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
170
+ const len0 = WASM_VECTOR_LEN;
171
+ const ret = wasm.signature(ptr0, len0);
172
+ var ptr2 = ret[0];
173
+ var len2 = ret[1];
174
+ if (ret[3]) {
175
+ ptr2 = 0; len2 = 0;
176
+ throw takeFromExternrefTable0(ret[2]);
177
+ }
178
+ deferred3_0 = ptr2;
179
+ deferred3_1 = len2;
180
+ return getStringFromWasm0(ptr2, len2);
181
+ } finally {
182
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
183
+ }
184
+ }
185
+ export function __wbindgen_cast_0000000000000001(arg0, arg1) {
186
+ // Cast intrinsic for `Ref(String) -> Externref`.
187
+ const ret = getStringFromWasm0(arg0, arg1);
188
+ return ret;
189
+ }
190
+ export function __wbindgen_init_externref_table() {
191
+ const table = wasm.__wbindgen_externrefs;
192
+ const offset = table.grow(4);
193
+ table.set(0, undefined);
194
+ table.set(offset + 0, undefined);
195
+ table.set(offset + 1, null);
196
+ table.set(offset + 2, true);
197
+ table.set(offset + 3, false);
198
+ }
199
+ function getStringFromWasm0(ptr, len) {
200
+ ptr = ptr >>> 0;
201
+ return decodeText(ptr, len);
202
+ }
203
+
204
+ let cachedUint8ArrayMemory0 = null;
205
+ function getUint8ArrayMemory0() {
206
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
207
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
208
+ }
209
+ return cachedUint8ArrayMemory0;
210
+ }
211
+
212
+ function passStringToWasm0(arg, malloc, realloc) {
213
+ if (realloc === undefined) {
214
+ const buf = cachedTextEncoder.encode(arg);
215
+ const ptr = malloc(buf.length, 1) >>> 0;
216
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
217
+ WASM_VECTOR_LEN = buf.length;
218
+ return ptr;
219
+ }
220
+
221
+ let len = arg.length;
222
+ let ptr = malloc(len, 1) >>> 0;
223
+
224
+ const mem = getUint8ArrayMemory0();
225
+
226
+ let offset = 0;
227
+
228
+ for (; offset < len; offset++) {
229
+ const code = arg.charCodeAt(offset);
230
+ if (code > 0x7F) break;
231
+ mem[ptr + offset] = code;
232
+ }
233
+ if (offset !== len) {
234
+ if (offset !== 0) {
235
+ arg = arg.slice(offset);
236
+ }
237
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
238
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
239
+ const ret = cachedTextEncoder.encodeInto(arg, view);
240
+
241
+ offset += ret.written;
242
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
243
+ }
244
+
245
+ WASM_VECTOR_LEN = offset;
246
+ return ptr;
247
+ }
248
+
249
+ function takeFromExternrefTable0(idx) {
250
+ const value = wasm.__wbindgen_externrefs.get(idx);
251
+ wasm.__externref_table_dealloc(idx);
252
+ return value;
253
+ }
254
+
255
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
256
+ cachedTextDecoder.decode();
257
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
258
+ let numBytesDecoded = 0;
259
+ function decodeText(ptr, len) {
260
+ numBytesDecoded += len;
261
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
262
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
263
+ cachedTextDecoder.decode();
264
+ numBytesDecoded = len;
265
+ }
266
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
267
+ }
268
+
269
+ const cachedTextEncoder = new TextEncoder();
270
+
271
+ if (!('encodeInto' in cachedTextEncoder)) {
272
+ cachedTextEncoder.encodeInto = function (arg, view) {
273
+ const buf = cachedTextEncoder.encode(arg);
274
+ view.set(buf);
275
+ return {
276
+ read: arg.length,
277
+ written: buf.length
278
+ };
279
+ };
280
+ }
281
+
282
+ let WASM_VECTOR_LEN = 0;
283
+
284
+
285
+ let wasm;
286
+ export function __wbg_set_wasm(val) {
287
+ wasm = val;
288
+ }
Binary file
package/package.json CHANGED
@@ -1,96 +1,52 @@
1
1
  {
2
- "private": false,
3
- "name": "genome",
4
- "version": "1.0.0",
5
- "description": "Deterministic structure ID generation for JavaScript objects using hierarchical hashing and collision-resistant algorithms",
6
- "author": "Michael Sweeney <overthemike@gmail.com>",
7
- "type": "module",
8
- "source": "./src/index.ts",
9
- "main": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "exports": {
12
- "./package.json": "./package.json",
13
- ".": {
14
- "require": {
15
- "types": "./dist/index.d.ts",
16
- "default": "./dist/index.cjs"
17
- },
18
- "import": {
19
- "types": "./dist/index.d.ts",
20
- "default": "./dist/index.js"
21
- }
22
- }
23
- },
24
- "scripts": {
25
- "build": "pnpm run clean && pnpm run build:types && pnpm run build:js",
26
- "build:types": "tsc --emitDeclarationOnly --declarationMap",
27
- "build:js": "tsup",
28
- "changeset": "changeset",
29
- "version": "changeset version",
30
- "release": "changeset publish",
31
- "clean": "rm -rf dist",
32
- "lint": "biome lint",
33
- "lint:fix": "biome lint --fix",
34
- "test": "vitest run",
35
- "typecheck": "tsc --noEmit",
36
- "prepublishOnly": "pnpm run build",
37
- "bench": "vitest bench",
38
- "coverage": "vitest run --coverage",
39
- "test:ui": "vitest --ui"
40
- },
41
- "files": [
42
- "dist",
43
- "README.md"
44
- ],
45
- "publishConfig": {
46
- "access": "public"
47
- },
48
- "repository": {
49
- "type": "git",
50
- "url": "https://github.com/synpatico/genome.git"
51
- },
52
- "bugs": {
53
- "url": "https://github.com/synpatico/gnome/issues"
54
- },
55
- "homepage": "https://github.com/synpatico/genome",
56
- "directories": {
57
- "test": "tests"
58
- },
59
- "license": "MIT",
60
- "devDependencies": {
61
- "@biomejs/biome": "^2.1.4",
62
- "@testing-library/jest-dom": "^6.6.3",
63
- "@types/benchmark": "^2.1.5",
64
- "@types/node": "^22.13.14",
65
- "@vitest/coverage-v8": "^3.0.9",
66
- "@vitest/ui": "^3.0.9",
67
- "tsup": "^8.4.0",
68
- "typescript": "^5.8.2",
69
- "vite": "^6.2.3",
70
- "vitest": "^3.0.9"
71
- },
72
- "keywords": [
73
- "structure",
74
- "shape",
75
- "id",
76
- "identifier",
77
- "generator",
78
- "hash",
79
- "fingerprint",
80
- "signature",
81
- "genome",
82
- "schema",
83
- "compare",
84
- "diff",
85
- "deduplication",
86
- "memoization",
87
- "caching",
88
- "serialization",
89
- "object",
90
- "json",
91
- "deterministic",
92
- "unique",
93
- "synpatico",
94
- "type"
95
- ]
2
+ "name": "genome",
3
+ "type": "module",
4
+ "collaborators": [
5
+ "Michael Sweeney <overthemike@gmail.com>"
6
+ ],
7
+ "description": "Deterministic structure ID generation for JavaScript objects using hierarchical hashing and collision-resistant algorithms",
8
+ "version": "1.0.3",
9
+ "license": "MIT",
10
+ "repository": "https://github.com/overthemike/genome.git",
11
+ "files": [
12
+ "genome_rs_bg.wasm",
13
+ "genome_rs.js",
14
+ "genome_rs_bg.js",
15
+ "genome_rs.d.ts"
16
+ ],
17
+ "main": "genome_rs.js",
18
+ "homepage": "https://github.com/overthemike/genome",
19
+ "types": "genome_rs.d.ts",
20
+ "sideEffects": [
21
+ "./genome_rs.js",
22
+ "./snippets/*"
23
+ ],
24
+ "keywords": [
25
+ "structure",
26
+ "shape",
27
+ "id",
28
+ "identifier",
29
+ "generator",
30
+ "hash",
31
+ "fingerprint",
32
+ "signature",
33
+ "genome",
34
+ "schema",
35
+ "compare",
36
+ "diff",
37
+ "deduplication",
38
+ "memoization",
39
+ "caching",
40
+ "serialization",
41
+ "object",
42
+ "json",
43
+ "deterministic",
44
+ "unique",
45
+ "synpatico",
46
+ "type",
47
+ "wasm",
48
+ "rust"
49
+ ],
50
+ "author": "Michael Sweeney <overthemike@gmail.com>",
51
+ "bugs": "https://github.com/overthemike/genome/issues"
96
52
  }
package/dist/hash.d.ts DELETED
@@ -1,67 +0,0 @@
1
- /**
2
- * @fileoverview Fast, non-cryptographic hash functions for structure ID generation
3
- * @module @synpatico/genome/hash
4
- */
5
- /**
6
- * Available hash function implementations
7
- */
8
- export declare const hashFunction: {
9
- readonly MURMUR: typeof murmurHash3;
10
- readonly XXHASH: typeof xxHash32;
11
- };
12
- /**
13
- * Type representing available hash functions
14
- */
15
- export type HashFunction = (typeof hashFunction)[keyof typeof hashFunction];
16
- /**
17
- * Options for hash function selection
18
- */
19
- type HashFunctionProps = {
20
- /** Built-in hash function to use */
21
- type?: HashFunction;
22
- /** Custom hash function implementation */
23
- custom?: (str: string) => string;
24
- };
25
- /**
26
- * Generates a hash from a string using the specified algorithm.
27
- * Defaults to xxHash32 for optimal performance.
28
- *
29
- * @param str - The string to hash
30
- * @param options - Optional hash function configuration
31
- * @returns A hexadecimal hash string
32
- *
33
- * @example
34
- * ```javascript
35
- * // Using default xxHash32
36
- * const h1 = hash("hello"); // "884863d4"
37
- *
38
- * // Using MurmurHash3
39
- * const h2 = hash("hello", { type: hashFunction.MURMUR }); // "613cae7d"
40
- *
41
- * // Using custom function
42
- * const h3 = hash("hello", { custom: (s) => s.length.toString() }); // "5"
43
- * ```
44
- */
45
- export declare const hash: (str: string, options?: HashFunctionProps) => string;
46
- /**
47
- * MurmurHash3 implementation - fast non-cryptographic hash function.
48
- * Provides good distribution and collision resistance for hash tables.
49
- *
50
- * @param str - The string to hash
51
- * @returns A hexadecimal hash string
52
- *
53
- * @example
54
- * ```javascript
55
- * const hash = murmurHash3("hello world");
56
- * console.log(hash); // "5e928f0f"
57
- * ```
58
- */
59
- export declare function murmurHash3(str: string): string;
60
- /**
61
- *
62
- * @param input - byte array or string
63
- * @param seed - optional seed (32-bit unsigned);
64
- */
65
- export declare function xxHash32(input: Uint8Array | string, seed?: number): string;
66
- export {};
67
- //# sourceMappingURL=hash.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;CAGf,CAAA;AAEV;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA;AAE3E;;GAEG;AACH,KAAK,iBAAiB,GAAG;IACxB,oCAAoC;IACpC,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,MAAM,EAAE,UAAU,iBAAiB,KAAG,MAU/D,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAyD/C;AAsBD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,IAAI,SAAI,GAAG,MAAM,CA2KrE"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Order-preserving structure ID generator that avoids GLOBAL_KEY_MAP growth
3
- * from array indices and lengths by hashing numeric values directly.
4
- *
5
- * This mirrors the current generateStructureId algorithm with one change:
6
- * - For arrays, we compute index/length contributions via numeric hashing
7
- * (fixed seeds) instead of storing strings like "[i]" and "length:n"
8
- * in GLOBAL_KEY_MAP. Property names still use GLOBAL_KEY_MAP.
9
- */
10
- import { type StructureIdConfig } from "./index";
11
- /**
12
- * Generate a structure ID while avoiding GLOBAL_KEY_MAP growth from array indices/lengths.
13
- * Property names still use GLOBAL_KEY_MAP like the current implementation.
14
- */
15
- export declare const generateStructureIdIndexHash: (obj: unknown, config?: StructureIdConfig) => string;
16
- export declare function getStructureInfoIndexHash(obj: unknown, config?: StructureIdConfig): {
17
- id: string;
18
- levels: number;
19
- collisionCount: number;
20
- };
21
- //# sourceMappingURL=id-indexhash.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"id-indexhash.d.ts","sourceRoot":"","sources":["../src/id-indexhash.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAML,KAAK,iBAAiB,EACvB,MAAM,SAAS,CAAA;AA8DhB;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACvC,KAAK,OAAO,EACZ,SAAS,iBAAiB,KACzB,MAuHF,CAAA;AAED,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,CAAC,EAAE,iBAAiB,GACzB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAUxD"}
@@ -1,6 +0,0 @@
1
- export declare function generateStructureIdMultiset(obj: unknown): string;
2
- export declare function getStructureInfoMultiset(obj: unknown): {
3
- id: string;
4
- levels: number;
5
- };
6
- //# sourceMappingURL=id-multiset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"id-multiset.d.ts","sourceRoot":"","sources":["../src/id-multiset.ts"],"names":[],"mappings":"AAgCA,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAyEhE;AAGD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAGrF"}
@@ -1,2 +0,0 @@
1
- export declare function generateStructureIdMultiset32(obj: unknown): string;
2
- //# sourceMappingURL=id-multiset32.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"id-multiset32.d.ts","sourceRoot":"","sources":["../src/id-multiset32.ts"],"names":[],"mappings":"AAwCA,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAiElE"}