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.
package/dist/index.d.ts DELETED
@@ -1,272 +0,0 @@
1
- /**
2
- * @fileoverview Deterministic structure ID generation for JavaScript objects using hierarchical hashing and collision-resistant algorithms
3
- * @module @synpatico/genome
4
- */
5
- /**
6
- * Global cache of property names to their deterministic hash values.
7
- * Used to ensure consistent bit generation across different executions.
8
- */
9
- export declare const GLOBAL_KEY_MAP: Map<string, bigint>;
10
- /**
11
- * Tracks collision counts for structure signatures to handle hash conflicts.
12
- * Maps structure signatures to their collision counter values.
13
- */
14
- export declare const STRUCTURE_HASH_COUNTER: Map<string, number>;
15
- /**
16
- * WeakMap cache for object-to-structure-ID mappings.
17
- * Automatically garbage collected when objects are no longer referenced.
18
- */
19
- export declare let OBJECT_ID_CACHE: WeakMap<object, string>;
20
- /**
21
- * WeakMap cache for object-to-signature mappings.
22
- * Stores the signature portion (excluding L0 level) for collision detection.
23
- */
24
- export declare let OBJECT_SIGNATURE_CACHE: WeakMap<object, string>;
25
- /**
26
- * WeakMap cache for complete structure information including metadata.
27
- * Stores comprehensive structure analysis results for performance optimization.
28
- */
29
- export declare let STRUCTURE_INFO_CACHE: WeakMap<object, {
30
- id: string;
31
- levels: number;
32
- collisionCount: number;
33
- }>;
34
- /**
35
- * Configuration options for structure ID generation
36
- */
37
- export interface StructureIdConfig {
38
- /** Whether to generate new IDs on collision (default: false) */
39
- newIdOnCollision?: boolean;
40
- /**
41
- * When true, arrays with different lengths but the same element shapes
42
- * will produce the same structure ID. Distinct element shapes within
43
- * an array are still differentiated. (default: false)
44
- *
45
- * @example
46
- * // Same ID:
47
- * generateStructureId({ items: [1, 2, 3] }, { ignoreArrayLength: true })
48
- * generateStructureId({ items: [1, 2] }, { ignoreArrayLength: true })
49
- *
50
- * // Different ID (different element shapes):
51
- * generateStructureId({ items: [1, 'a'] }, { ignoreArrayLength: true })
52
- * generateStructureId({ items: [{ id: 1 }, 'a'] }, { ignoreArrayLength: true })
53
- */
54
- ignoreArrayLength?: boolean;
55
- }
56
- /**
57
- * Sets the global configuration for structure ID generation
58
- * @param config - The configuration options to apply
59
- * @example
60
- * ```javascript
61
- * setStructureIdConfig({ newIdOnCollision: true });
62
- * ```
63
- */
64
- export declare function setStructureIdConfig(config: StructureIdConfig): void;
65
- /**
66
- * Gets the current global configuration for structure ID generation
67
- * @returns A copy of the current configuration
68
- */
69
- export declare function getStructureIdConfig(): StructureIdConfig;
70
- /**
71
- * Generates a unique, deterministic structure ID for any JavaScript value.
72
- * The ID captures the complete shape and type information hierarchically.
73
- *
74
- * @param obj - The value to generate a structure ID for
75
- * @param config - Optional configuration to override global settings
76
- * @returns A hierarchical structure ID in format "L0:hash-L1:hash-L2:hash..."
77
- *
78
- * @example
79
- * ```javascript
80
- * const obj = { users: [{ id: 1, name: "John" }] };
81
- * const id = generateStructureId(obj);
82
- * // Returns: "L0:384729-L1:8374629-L2:9283746"
83
- * ```
84
- *
85
- * @example
86
- * ```javascript
87
- * // Empty objects and arrays have special IDs
88
- * generateStructureId({}); // Returns: "{}"
89
- * generateStructureId([]); // Returns: "[]"
90
- * ```
91
- */
92
- export declare const generateStructureId: (obj: unknown, config?: StructureIdConfig) => string;
93
- /**
94
- * Gets the structure signature (without L0 collision counter) for an object.
95
- * This signature represents the object's shape and is used for collision detection.
96
- *
97
- * @param obj - The object to get a signature for
98
- * @returns A signature string like "L1:hash-L2:hash" or "type:primitive" for primitives
99
- *
100
- * @example
101
- * ```javascript
102
- * const sig1 = getStructureSignature({ id: 1, name: "John" });
103
- * const sig2 = getStructureSignature({ id: 2, name: "Jane" });
104
- * console.log(sig1 === sig2); // true (same structure)
105
- * ```
106
- */
107
- export declare function getStructureSignature(obj: unknown): string;
108
- /**
109
- * Registers a structure with a specific collision count.
110
- * Used to pre-populate collision counters for known structures.
111
- *
112
- * @param obj - The object whose structure to register
113
- * @param collisionCount - The collision count to set for this structure
114
- *
115
- * @example
116
- * ```javascript
117
- * const template = { id: 0, name: "" };
118
- * registerStructure(template, 5); // Pre-register with collision count 5
119
- * ```
120
- */
121
- export declare function registerStructure(obj: unknown, collisionCount: number): void;
122
- /**
123
- * Batch registers multiple structures with their collision counts.
124
- * Useful for pre-populating the collision counter from saved state.
125
- *
126
- * @param registrations - Array of structure-count pairs to register
127
- *
128
- * @example
129
- * ```javascript
130
- * registerStructures([
131
- * { structure: { id: 0 }, count: 3 },
132
- * { structure: { name: "" }, count: 1 }
133
- * ]);
134
- * ```
135
- */
136
- export declare function registerStructures(registrations: Array<{
137
- structure: unknown;
138
- count: number;
139
- }>): void;
140
- /**
141
- * Structure registration data for importing/exporting collision state
142
- */
143
- export interface StructureRegistration {
144
- /** The structure signature (without L0) */
145
- signature: string;
146
- /** The collision counter value */
147
- count: number;
148
- }
149
- /**
150
- * Registers structure signatures directly without needing object instances.
151
- * Useful for importing collision state from external sources.
152
- *
153
- * @param signatures - Array of signature-count pairs to register
154
- *
155
- * @example
156
- * ```javascript
157
- * registerStructureSignatures([
158
- * { signature: "L1:123-L2:456", count: 2 },
159
- * { signature: "L1:789-L2:012", count: 0 }
160
- * ]);
161
- * ```
162
- */
163
- export declare function registerStructureSignatures(signatures: Array<StructureRegistration>): void;
164
- /**
165
- * Gets comprehensive structure information including ID, depth levels, and collision count.
166
- * Caches results for performance optimization.
167
- *
168
- * @param obj - The object to analyze
169
- * @param config - Optional configuration to override global settings
170
- * @returns Structure information object
171
- *
172
- * @example
173
- * ```javascript
174
- * const info = getStructureInfo({ users: [{ id: 1, name: "John" }] });
175
- * console.log(info);
176
- * // {
177
- * // id: "L0:384729-L1:8374629-L2:9283746",
178
- * // levels: 3,
179
- * // collisionCount: 0
180
- * // }
181
- * ```
182
- */
183
- export declare function getStructureInfo(obj: unknown, config?: StructureIdConfig): {
184
- id: string;
185
- levels: number;
186
- collisionCount: number;
187
- };
188
- /**
189
- * Resets all global state including caches and collision counters.
190
- * Useful for testing or when you need to start fresh.
191
- *
192
- * @example
193
- * ```javascript
194
- * resetState(); // Clear all caches and counters
195
- * ```
196
- */
197
- export declare function resetState(): void;
198
- /**
199
- * Serializable state of the structure ID system
200
- */
201
- export interface StructureState {
202
- /** Map of keys to their hash values */
203
- keyMap: Record<string, string>;
204
- /** Map of structure signatures to collision counts */
205
- collisionCounters: Record<string, number>;
206
- }
207
- /**
208
- * Exports the current state of the structure ID system.
209
- * Useful for persisting state across sessions or sharing between environments.
210
- *
211
- * @returns The current state including key mappings and collision counters
212
- *
213
- * @example
214
- * ```javascript
215
- * const state = exportStructureState();
216
- * localStorage.setItem('genomeState', JSON.stringify(state));
217
- * ```
218
- */
219
- export declare function exportStructureState(): StructureState;
220
- /**
221
- * Imports a previously exported structure state.
222
- * Resets current state before importing to ensure clean slate.
223
- *
224
- * @param state - The state to import
225
- *
226
- * @example
227
- * ```javascript
228
- * const savedState = JSON.parse(localStorage.getItem('genomeState'));
229
- * importStructureState(savedState);
230
- * ```
231
- */
232
- export declare function importStructureState(state: StructureState): void;
233
- /**
234
- * Generates a compact, fixed-length structure ID using SHA-256 hashing.
235
- * Useful when you need consistent-length IDs regardless of object depth.
236
- *
237
- * @param obj - The object to generate a compact ID for
238
- * @param config - Optional configuration to override global settings
239
- * @returns A 64-character hexadecimal hash string
240
- *
241
- * @example
242
- * ```javascript
243
- * const compactId = getCompactId({ users: [{ id: 1, name: "John" }] });
244
- * console.log(compactId); // "a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5..."
245
- * ```
246
- */
247
- export declare const getCompactId: (obj: unknown, config?: StructureIdConfig) => string;
248
- /**
249
- * Gets structure information with a compact ID format.
250
- * Combines the comprehensive analysis of getStructureInfo with compact ID generation.
251
- *
252
- * @param obj - The object to analyze
253
- * @param config - Optional configuration to override global settings
254
- * @returns Structure info with compact hash ID
255
- *
256
- * @example
257
- * ```javascript
258
- * const info = getCompactInfo({ users: [] });
259
- * console.log(info);
260
- * // {
261
- * // id: "a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5...",
262
- * // levels: 2,
263
- * // collisionCount: 0
264
- * // }
265
- * ```
266
- */
267
- export declare const getCompactInfo: (obj: unknown, config?: StructureIdConfig) => {
268
- id: string;
269
- levels: number;
270
- collisionCount: number;
271
- };
272
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqBH;;;GAGG;AACH,eAAO,MAAM,cAAc,qBAA4B,CAAA;AAEvD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qBAA4B,CAAA;AAE/D;;;GAGG;AACH,eAAO,IAAI,eAAe,yBAAgC,CAAA;AAE1D;;;GAGG;AACH,eAAO,IAAI,sBAAsB,yBAAgC,CAAA;AAEjE;;;GAGG;AACH,eAAO,IAAI,oBAAoB;QAGzB,MAAM;YACF,MAAM;oBACE,MAAM;EAErB,CAAA;AA2BH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAWD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAEpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,EAAE,SAAS,iBAAiB,KAAG,MAqM9E,CAAA;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAe1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAG5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CACjC,aAAa,EAAE,KAAK,CAAC;IACpB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACb,CAAC,GACA,IAAI,CAIN;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,KAAK,CAAC,qBAAqB,CAAC,GAAG,IAAI,CAI1F;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,OAAO,EACZ,MAAM,CAAC,EAAE,iBAAiB,GACxB;IACF,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;CACtB,CAgDA;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAcjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAerD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAkBhE;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,OAAO,EAAE,SAAS,iBAAiB,KAAG,MAIvE,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,GAC1B,KAAK,OAAO,EACZ,SAAS,iBAAiB,KACxB;IACF,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;CAOtB,CAAA"}
package/dist/index.js DELETED
@@ -1,405 +0,0 @@
1
- // src/hash.ts
2
- var hashFunction = {
3
- MURMUR: murmurHash3,
4
- XXHASH: xxHash32
5
- };
6
- var hash = (str, options) => {
7
- if (options) {
8
- if (options.custom !== void 0 && typeof options.custom === "function") {
9
- return options.custom(str);
10
- }
11
- if (options.type) {
12
- return options.type(str);
13
- }
14
- }
15
- return hashFunction.XXHASH(str);
16
- };
17
- function murmurHash3(str) {
18
- const seed = 0;
19
- const c1 = 3432918353;
20
- const c2 = 461845907;
21
- const r1 = 15;
22
- const r2 = 13;
23
- const m = 5;
24
- const n = 3864292196;
25
- let hash2 = seed;
26
- const data = new TextEncoder().encode(str);
27
- const len = data.length;
28
- const nblocks = Math.floor(len / 4);
29
- for (let i = 0; i < nblocks; i++) {
30
- let k2 = data[i * 4] | data[i * 4 + 1] << 8 | data[i * 4 + 2] << 16 | data[i * 4 + 3] << 24;
31
- k2 = Math.imul(k2, c1);
32
- k2 = k2 << r1 | k2 >>> 32 - r1;
33
- k2 = Math.imul(k2, c2);
34
- hash2 ^= k2;
35
- hash2 = hash2 << r2 | hash2 >>> 32 - r2;
36
- hash2 = Math.imul(hash2, m) + n;
37
- }
38
- let k = 0;
39
- const remaining = len - nblocks * 4;
40
- const offset = nblocks * 4;
41
- if (remaining === 3) {
42
- k ^= data[offset + 2] << 16;
43
- }
44
- if (remaining >= 2) {
45
- k ^= data[offset + 1] << 8;
46
- }
47
- if (remaining >= 1) {
48
- k ^= data[offset];
49
- k = Math.imul(k, c1);
50
- k = k << r1 | k >>> 32 - r1;
51
- k = Math.imul(k, c2);
52
- hash2 ^= k;
53
- }
54
- hash2 ^= len;
55
- hash2 ^= hash2 >>> 16;
56
- hash2 = Math.imul(hash2, 2246822507);
57
- hash2 ^= hash2 >>> 13;
58
- hash2 = Math.imul(hash2, 3266489909);
59
- hash2 ^= hash2 >>> 16;
60
- return (hash2 >>> 0).toString(16);
61
- }
62
- var PRIME32_1 = 2654435761;
63
- var PRIME32_2 = 2246822519;
64
- var PRIME32_3 = 3266489917;
65
- var PRIME32_4 = 668265263;
66
- var PRIME32_5 = 374761393;
67
- var encoder;
68
- function xxHash32(input, seed = 0) {
69
- const buffer = typeof input === "string" ? (
70
- // biome-ignore lint/suspicious/noAssignInExpressions: allow
71
- (encoder ??= new TextEncoder()).encode(input)
72
- ) : input;
73
- const b = buffer;
74
- let acc = seed + PRIME32_5 & 4294967295;
75
- let offset = 0;
76
- if (b.length >= 16) {
77
- const accN = [
78
- seed + PRIME32_1 + PRIME32_2 & 4294967295,
79
- seed + PRIME32_2 & 4294967295,
80
- seed + 0 & 4294967295,
81
- seed - PRIME32_1 & 4294967295
82
- ];
83
- const b2 = buffer;
84
- const limit2 = b2.length - 16;
85
- let lane = 0;
86
- for (offset = 0; (offset & 4294967280) <= limit2; offset += 4) {
87
- const i = offset;
88
- const laneN0 = b2[i + 0] + (b2[i + 1] << 8);
89
- const laneN1 = b2[i + 2] + (b2[i + 3] << 8);
90
- const laneNP = laneN0 * PRIME32_2 + (laneN1 * PRIME32_2 << 16);
91
- let acc2 = accN[lane] + laneNP & 4294967295;
92
- acc2 = acc2 << 13 | acc2 >>> 19;
93
- const acc0 = acc2 & 65535;
94
- const acc1 = acc2 >>> 16;
95
- accN[lane] = acc0 * PRIME32_1 + (acc1 * PRIME32_1 << 16) & 4294967295;
96
- lane = lane + 1 & 3;
97
- }
98
- acc = (accN[0] << 1 | accN[0] >>> 31) + (accN[1] << 7 | accN[1] >>> 25) + (accN[2] << 12 | accN[2] >>> 20) + (accN[3] << 18 | accN[3] >>> 14) & 4294967295;
99
- }
100
- acc = acc + buffer.length & 4294967295;
101
- const limit = buffer.length - 4;
102
- for (; offset <= limit; offset += 4) {
103
- const i = offset;
104
- const laneN0 = b[i + 0] + (b[i + 1] << 8);
105
- const laneN1 = b[i + 2] + (b[i + 3] << 8);
106
- const laneP = laneN0 * PRIME32_3 + (laneN1 * PRIME32_3 << 16);
107
- acc = acc + laneP & 4294967295;
108
- acc = acc << 17 | acc >>> 15;
109
- acc = (acc & 65535) * PRIME32_4 + ((acc >>> 16) * PRIME32_4 << 16) & 4294967295;
110
- }
111
- for (; offset < b.length; ++offset) {
112
- const lane = b[offset];
113
- acc = acc + lane * PRIME32_5;
114
- acc = acc << 11 | acc >>> 21;
115
- acc = (acc & 65535) * PRIME32_1 + ((acc >>> 16) * PRIME32_1 << 16) & 4294967295;
116
- }
117
- acc = acc ^ acc >>> 15;
118
- acc = ((acc & 65535) * PRIME32_2 & 4294967295) + ((acc >>> 16) * PRIME32_2 << 16);
119
- acc = acc ^ acc >>> 13;
120
- acc = ((acc & 65535) * PRIME32_3 & 4294967295) + ((acc >>> 16) * PRIME32_3 << 16);
121
- acc = acc ^ acc >>> 16;
122
- return acc < 0 ? (acc + 4294967296).toString(16) : acc.toString(16);
123
- }
124
-
125
- // src/index.ts
126
- var TYPE_BITS = {
127
- root: BigInt(0),
128
- number: BigInt(1),
129
- string: BigInt(2),
130
- boolean: BigInt(4),
131
- bigint: BigInt(8),
132
- null: BigInt(16),
133
- undefined: BigInt(32),
134
- symbol: BigInt(64),
135
- object: BigInt(128),
136
- array: BigInt(256)
137
- };
138
- var GLOBAL_KEY_MAP = /* @__PURE__ */ new Map();
139
- var STRUCTURE_HASH_COUNTER = /* @__PURE__ */ new Map();
140
- var OBJECT_ID_CACHE = /* @__PURE__ */ new WeakMap();
141
- var OBJECT_SIGNATURE_CACHE = /* @__PURE__ */ new WeakMap();
142
- var STRUCTURE_INFO_CACHE = /* @__PURE__ */ new WeakMap();
143
- var isObject = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
144
- var getBit = (key) => {
145
- if (!GLOBAL_KEY_MAP.has(key)) {
146
- const hashResult = xxHash32(key);
147
- const deterministicBit = BigInt(`0x${hashResult}`);
148
- GLOBAL_KEY_MAP.set(key, deterministicBit);
149
- }
150
- return GLOBAL_KEY_MAP.get(key);
151
- };
152
- var globalConfig = {
153
- newIdOnCollision: false,
154
- ignoreArrayLength: false
155
- };
156
- function setStructureIdConfig(config) {
157
- globalConfig = { ...config };
158
- }
159
- function getStructureIdConfig() {
160
- return { ...globalConfig };
161
- }
162
- var generateStructureId = (obj, config) => {
163
- const emptyObj = isObject(obj) && Object.keys(obj).length === 0;
164
- const emptyArr = Array.isArray(obj) && obj.length === 0;
165
- if (emptyObj) return "{}";
166
- if (emptyArr) return "[]";
167
- const effectiveConfig = config ?? globalConfig;
168
- const ignoreArrayLength = effectiveConfig.ignoreArrayLength ?? false;
169
- if (typeof obj !== "object" || obj === null) {
170
- return `L0:${TYPE_BITS[typeof obj] || BigInt(0)}-L1:${TYPE_BITS[typeof obj] || BigInt(0)}`;
171
- }
172
- if (!effectiveConfig?.newIdOnCollision && OBJECT_ID_CACHE.has(obj)) {
173
- return OBJECT_ID_CACHE.get(obj);
174
- }
175
- const objectMap = /* @__PURE__ */ new Map();
176
- const levelHashes = {};
177
- const getType = (value) => {
178
- if (value === null) return "null";
179
- if (value === void 0) return "undefined";
180
- if (Array.isArray(value)) return "array";
181
- return typeof value;
182
- };
183
- const getObjectSignature = (obj2, path) => {
184
- const type = Array.isArray(obj2) ? "array" : "object";
185
- if (type === "object") {
186
- const keys = Object.keys(obj2).sort().join(",");
187
- return `${path.join(".")}.{${keys}}`;
188
- }
189
- return `${path.join(".")}.[${obj2.length}]`;
190
- };
191
- const processStructure = (value, level = 0, path = []) => {
192
- if (!levelHashes[level]) {
193
- levelHashes[level] = BigInt(1) << BigInt(level);
194
- }
195
- const type = getType(value);
196
- levelHashes[level] += TYPE_BITS[type] || BigInt(0);
197
- if (type !== "object" && type !== "array") {
198
- return;
199
- }
200
- if (isObject(value) || Array.isArray(value)) {
201
- const objValue = value;
202
- const objSig = getObjectSignature(objValue, path);
203
- if (objectMap.has(objValue)) {
204
- const circularPath = objectMap.get(objValue);
205
- levelHashes[level] += getBit(`circular:${circularPath}`);
206
- return;
207
- }
208
- objectMap.set(objValue, objSig);
209
- const objTypeBit = getBit(`type:${type}`);
210
- levelHashes[level] += objTypeBit;
211
- const isRootLevel = level === 0;
212
- const isEmpty = isObject(value) && Object.keys(value).length === 0 || Array.isArray(value) && value.length === 0;
213
- if (!isRootLevel || !isEmpty) {
214
- if (type === "object") {
215
- const objValue2 = value;
216
- const keys = Object.keys(objValue2).sort();
217
- let multiplier = BigInt(1);
218
- for (const key of keys) {
219
- const propType = getType(objValue2[key]);
220
- const keyBit = getBit(key);
221
- levelHashes[level] += keyBit * multiplier;
222
- levelHashes[level] += (TYPE_BITS[propType] || BigInt(0)) * multiplier;
223
- multiplier++;
224
- processStructure(objValue2[key], level + 1, [...path, key]);
225
- }
226
- } else if (type === "array") {
227
- const arrayValue = value;
228
- if (!ignoreArrayLength) {
229
- const lengthBit = getBit(`length:${arrayValue.length}`);
230
- levelHashes[level] += lengthBit;
231
- let multiplier = BigInt(1);
232
- for (let i = 0; i < arrayValue.length; i++) {
233
- const itemType = getType(arrayValue[i]);
234
- const indexBit = getBit(`[${i}]`);
235
- levelHashes[level] += indexBit * multiplier;
236
- levelHashes[level] += (TYPE_BITS[itemType] || BigInt(0)) * multiplier;
237
- multiplier++;
238
- processStructure(arrayValue[i], level + 1, [...path, `[${i}]`]);
239
- }
240
- } else {
241
- const seenShapes = /* @__PURE__ */ new Set();
242
- for (const item of arrayValue) {
243
- const itemType = getType(item);
244
- const shapeKey = itemType === "object" || itemType === "array" ? getObjectSignature(item, [...path, "[*]"]) : `scalar:${itemType}`;
245
- if (!seenShapes.has(shapeKey)) {
246
- seenShapes.add(shapeKey);
247
- levelHashes[level] += getBit(shapeKey);
248
- processStructure(item, level + 1, [...path, "[*]"]);
249
- }
250
- }
251
- levelHashes[level] += getBit("array:variadic");
252
- }
253
- }
254
- }
255
- }
256
- };
257
- processStructure(obj);
258
- const structureLevels = Object.entries(levelHashes).filter(([level]) => Number(level) > 0).sort(([a], [b]) => Number(a) - Number(b)).map(([level, hash2]) => `L${level}:${hash2}`);
259
- const structureSignature = structureLevels.join("-");
260
- if (typeof obj === "object" && obj !== null) {
261
- OBJECT_SIGNATURE_CACHE.set(obj, structureSignature);
262
- }
263
- const currentCount = STRUCTURE_HASH_COUNTER.get(structureSignature) ?? 0;
264
- if (effectiveConfig?.newIdOnCollision) {
265
- levelHashes[0] = BigInt(currentCount);
266
- STRUCTURE_HASH_COUNTER.set(structureSignature, currentCount + 1);
267
- }
268
- const idParts = Object.entries(levelHashes).sort(([a], [b]) => Number(a) - Number(b)).map(([level, hash2]) => `L${level}:${hash2}`);
269
- const finalId = idParts.join("-");
270
- if (!effectiveConfig?.newIdOnCollision && typeof obj === "object" && obj !== null) {
271
- OBJECT_ID_CACHE.set(obj, finalId);
272
- }
273
- if (typeof obj === "object" && obj !== null && STRUCTURE_INFO_CACHE.has(obj)) {
274
- STRUCTURE_INFO_CACHE.delete(obj);
275
- }
276
- return finalId;
277
- };
278
- function calculateIdLevels(id) {
279
- return id.split("-").length;
280
- }
281
- function getStructureSignature(obj) {
282
- if (typeof obj !== "object" || obj === null) {
283
- return `type:${typeof obj}`;
284
- }
285
- if (OBJECT_SIGNATURE_CACHE.has(obj)) {
286
- return OBJECT_SIGNATURE_CACHE.get(obj);
287
- }
288
- const tempId = generateStructureId(obj, { newIdOnCollision: false });
289
- const signature = tempId.split("-").slice(1).join("-");
290
- OBJECT_SIGNATURE_CACHE.set(obj, signature);
291
- return signature;
292
- }
293
- function registerStructure(obj, collisionCount) {
294
- const signature = getStructureSignature(obj);
295
- STRUCTURE_HASH_COUNTER.set(signature, collisionCount);
296
- }
297
- function registerStructures(registrations) {
298
- for (const { structure, count } of registrations) {
299
- registerStructure(structure, count);
300
- }
301
- }
302
- function registerStructureSignatures(signatures) {
303
- for (const { signature, count } of signatures) {
304
- STRUCTURE_HASH_COUNTER.set(signature, count);
305
- }
306
- }
307
- function getStructureInfo(obj, config) {
308
- const effectiveConfig = config ?? globalConfig;
309
- if (typeof obj !== "object" || obj === null) {
310
- const id2 = generateStructureId(obj, { newIdOnCollision: false });
311
- return {
312
- id: id2,
313
- levels: calculateIdLevels(id2),
314
- collisionCount: 0
315
- };
316
- }
317
- if (STRUCTURE_INFO_CACHE.has(obj)) {
318
- return STRUCTURE_INFO_CACHE.get(obj);
319
- }
320
- const structureSignature = OBJECT_SIGNATURE_CACHE.has(obj) ? OBJECT_SIGNATURE_CACHE.get(obj) : generateStructureId(obj, { newIdOnCollision: false }).split("-").slice(1).join("-");
321
- const collisionCount = STRUCTURE_HASH_COUNTER.get(structureSignature) || 0;
322
- let id;
323
- if (effectiveConfig.newIdOnCollision) {
324
- const l0Hash = BigInt(collisionCount);
325
- const l0Part = `L0:${l0Hash}`;
326
- id = [l0Part, structureSignature].join("-");
327
- } else {
328
- id = OBJECT_ID_CACHE.has(obj) ? OBJECT_ID_CACHE.get(obj) : generateStructureId(obj, { newIdOnCollision: false });
329
- }
330
- const levels = calculateIdLevels(id);
331
- const result = {
332
- id,
333
- levels,
334
- collisionCount
335
- };
336
- STRUCTURE_INFO_CACHE.set(obj, result);
337
- return result;
338
- }
339
- function resetState() {
340
- GLOBAL_KEY_MAP.clear();
341
- STRUCTURE_HASH_COUNTER.clear();
342
- OBJECT_ID_CACHE = /* @__PURE__ */ new WeakMap();
343
- OBJECT_SIGNATURE_CACHE = /* @__PURE__ */ new WeakMap();
344
- STRUCTURE_INFO_CACHE = /* @__PURE__ */ new WeakMap();
345
- }
346
- function exportStructureState() {
347
- const keyMap = {};
348
- for (const [key, value] of GLOBAL_KEY_MAP.entries()) {
349
- keyMap[key] = value.toString();
350
- }
351
- const collisionCounters = {};
352
- for (const [signature, count] of STRUCTURE_HASH_COUNTER.entries()) {
353
- collisionCounters[signature] = count;
354
- }
355
- return {
356
- keyMap,
357
- collisionCounters
358
- };
359
- }
360
- function importStructureState(state) {
361
- resetState();
362
- for (const [key, valueStr] of Object.entries(state.keyMap)) {
363
- GLOBAL_KEY_MAP.set(key, BigInt(valueStr));
364
- }
365
- for (const [signature, count] of Object.entries(state.collisionCounters)) {
366
- STRUCTURE_HASH_COUNTER.set(signature, count);
367
- }
368
- let maxBit = BigInt(0);
369
- for (const bitStr of Object.values(state.keyMap)) {
370
- const bit = BigInt(bitStr);
371
- if (bit > maxBit) {
372
- maxBit = bit;
373
- }
374
- }
375
- }
376
- var getCompactId = (obj, config) => {
377
- const fullId = generateStructureId(obj, config);
378
- return hash(fullId);
379
- };
380
- var getCompactInfo = (obj, config) => {
381
- const info = getStructureInfo(obj, config);
382
- info.id = hash(info.id);
383
- return info;
384
- };
385
- export {
386
- GLOBAL_KEY_MAP,
387
- OBJECT_ID_CACHE,
388
- OBJECT_SIGNATURE_CACHE,
389
- STRUCTURE_HASH_COUNTER,
390
- STRUCTURE_INFO_CACHE,
391
- exportStructureState,
392
- generateStructureId,
393
- getCompactId,
394
- getCompactInfo,
395
- getStructureIdConfig,
396
- getStructureInfo,
397
- getStructureSignature,
398
- importStructureState,
399
- registerStructure,
400
- registerStructureSignatures,
401
- registerStructures,
402
- resetState,
403
- setStructureIdConfig
404
- };
405
- //# sourceMappingURL=index.js.map