@xyo-network/hash 2.89.3 → 2.90.1

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 (50) hide show
  1. package/dist/browser/PayloadHasher.d.cts +13 -0
  2. package/dist/browser/PayloadHasher.d.cts.map +1 -1
  3. package/dist/browser/PayloadHasher.d.mts +13 -0
  4. package/dist/browser/PayloadHasher.d.mts.map +1 -1
  5. package/dist/browser/PayloadHasher.d.ts +13 -0
  6. package/dist/browser/PayloadHasher.d.ts.map +1 -1
  7. package/dist/browser/index.cjs +75 -8
  8. package/dist/browser/index.cjs.map +1 -1
  9. package/dist/browser/index.js +75 -8
  10. package/dist/browser/index.js.map +1 -1
  11. package/dist/browser/worker/jsHash.cjs +34 -0
  12. package/dist/browser/worker/jsHash.cjs.map +1 -0
  13. package/dist/browser/worker/jsHash.js +10 -0
  14. package/dist/browser/worker/jsHash.js.map +1 -0
  15. package/dist/browser/worker/subtleHash.cjs +11 -0
  16. package/dist/browser/worker/subtleHash.cjs.map +1 -0
  17. package/dist/browser/worker/subtleHash.js +9 -0
  18. package/dist/browser/worker/subtleHash.js.map +1 -0
  19. package/dist/browser/worker/wasmHash.cjs +12 -0
  20. package/dist/browser/worker/wasmHash.cjs.map +1 -0
  21. package/dist/browser/worker/wasmHash.js +10 -0
  22. package/dist/browser/worker/wasmHash.js.map +1 -0
  23. package/dist/node/PayloadHasher.d.cts +13 -0
  24. package/dist/node/PayloadHasher.d.cts.map +1 -1
  25. package/dist/node/PayloadHasher.d.mts +13 -0
  26. package/dist/node/PayloadHasher.d.mts.map +1 -1
  27. package/dist/node/PayloadHasher.d.ts +13 -0
  28. package/dist/node/PayloadHasher.d.ts.map +1 -1
  29. package/dist/node/index.cjs +75 -8
  30. package/dist/node/index.cjs.map +1 -1
  31. package/dist/node/index.js +75 -8
  32. package/dist/node/index.js.map +1 -1
  33. package/dist/node/worker/jsHash.cjs +34 -0
  34. package/dist/node/worker/jsHash.cjs.map +1 -0
  35. package/dist/node/worker/jsHash.js +10 -0
  36. package/dist/node/worker/jsHash.js.map +1 -0
  37. package/dist/node/worker/subtleHash.cjs +11 -0
  38. package/dist/node/worker/subtleHash.cjs.map +1 -0
  39. package/dist/node/worker/subtleHash.js +9 -0
  40. package/dist/node/worker/subtleHash.js.map +1 -0
  41. package/dist/node/worker/wasmHash.cjs +12 -0
  42. package/dist/node/worker/wasmHash.cjs.map +1 -0
  43. package/dist/node/worker/wasmHash.js +10 -0
  44. package/dist/node/worker/wasmHash.js.map +1 -0
  45. package/package.json +6 -3
  46. package/src/PayloadHasher.ts +86 -8
  47. package/src/worker/jsHash.js +10 -0
  48. package/src/worker/subtleHash.js +9 -0
  49. package/src/worker/wasmHash.js +10 -0
  50. package/xy.config.ts +14 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/PayloadHasher.ts","../../src/removeEmptyFields.ts","../../src/removeFields.ts","../../src/sortFields.ts"],"sourcesContent":["import { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'\nimport { EmptyObject, ObjectWrapper } from '@xylabs/object'\nimport { subtle } from '@xylabs/platform'\nimport { WasmSupport } from '@xyo-network/wasm'\nimport { sha256 } from 'hash-wasm'\nimport shajs from 'sha.js'\n\nimport { removeEmptyFields } from './removeEmptyFields'\nimport { deepOmitPrefixedFields } from './removeFields'\nimport { sortFields } from './sortFields'\n\nconst wasmSupportStatic = new WasmSupport(['bigInt'])\n\nexport class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {\n static allowSubtle = true\n static readonly wasmInitialized = wasmSupportStatic.initialize()\n static readonly wasmSupport = wasmSupportStatic\n\n static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.hashPairs(objs)).filter(([_, objHash]) => !hashes.includes(objHash))?.map((pair) => pair[0])\n }\n\n static async filterIncludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.hashPairs(objs)).filter(([_, objHash]) => hashes.includes(objHash))?.map((pair) => pair[0])\n }\n\n static async findByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash): Promise<T | undefined> {\n return (await this.hashPairs(objs)).find(([_, objHash]) => objHash === hash)?.[0]\n }\n\n /**\n * Asynchronously hashes a payload\n * @param obj A payload\n * @returns The payload hash\n */\n static async hash<T extends EmptyObject>(obj: T): Promise<Hash> {\n if (PayloadHasher.allowSubtle) {\n try {\n const enc = new TextEncoder()\n const stringToHash = this.stringifyHashFields(obj)\n const b = enc.encode(stringToHash)\n const hashArray = await subtle.digest('SHA-256', b)\n return hexFromArrayBuffer(hashArray, { bitLength: 256 })\n } catch (ex) {\n const error = ex as Error\n console.error(`Setting allowSubtle to false [${error.message}]`)\n console.log(error.stack)\n PayloadHasher.allowSubtle = false\n }\n }\n\n await this.wasmInitialized\n if (this.wasmSupport.canUseWasm) {\n const stringToHash = this.stringifyHashFields(obj)\n try {\n return asHash(await sha256(stringToHash), true)\n } catch {\n this.wasmSupport.allowWasm = false\n }\n }\n return this.hashSync(obj)\n }\n\n static hashFields<T extends EmptyObject>(obj: T): T {\n return sortFields(removeEmptyFields(deepOmitPrefixedFields(obj, '_')))\n }\n\n /**\n * Creates an array of payload/hash tuples based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload/hash tuples\n */\n static async hashPairs<T extends EmptyObject>(objs: T[]): Promise<[T, Hash][]> {\n return await Promise.all(objs.map<Promise<[T, string]>>(async (obj) => [obj, await PayloadHasher.hash(obj)]))\n }\n\n /**\n * Synchronously hashes a payload\n * @param obj A payload\n * @returns The payload hash\n */\n static hashSync<T extends EmptyObject>(obj: T): Hash {\n return asHash(shajs('sha256').update(this.stringifyHashFields(obj)).digest().toString('hex'), true)\n }\n\n /**\n * Creates an array of payload hashes based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload hashes\n */\n static async hashes<T extends EmptyObject>(objs?: T[]): Promise<Hash[] | undefined> {\n return objs ? await Promise.all(objs.map((obj) => this.hash(obj))) : undefined\n }\n\n /**\n * Returns a clone of the payload that is JSON safe\n * @param obj A payload\n * @param meta Keeps underscore (meta) fields if set to true\n * @returns Returns a clone of the payload that is JSON safe\n */\n static json<T extends EmptyObject>(payload: T, meta = false): T {\n return sortFields(removeEmptyFields(meta ? payload : deepOmitPrefixedFields(payload, '_')))\n }\n\n /** @deprecated us json instead */\n static jsonPayload<T extends EmptyObject>(payload: T, meta = false): T {\n return this.json(payload, meta)\n }\n\n static stringifyHashFields<T extends EmptyObject>(obj: T) {\n return JSON.stringify(this.hashFields(obj))\n }\n\n async hash(): Promise<Hash> {\n return await PayloadHasher.hash(this.obj)\n }\n\n hashSync(): Hash {\n return PayloadHasher.hashSync(this.obj)\n }\n\n /**\n * Returns a clone of the payload that is JSON safe\n * @param meta Keeps underscore (meta) fields if set to true\n * @returns Returns a clone of the payload that is JSON safe\n */\n jsonPayload(meta = false): T {\n return PayloadHasher.jsonPayload(this.obj, meta)\n }\n}\n","import { AnyObject, EmptyObject } from '@xylabs/object'\nimport { typeOf } from '@xylabs/typeof'\n\nexport const removeEmptyFields = <T extends EmptyObject>(obj: T): T => {\n if (obj === null || Array.isArray(obj)) return obj\n\n const newObject: AnyObject = {}\n for (const [key, value] of Object.entries(obj)) {\n if (typeOf(value) === 'object') {\n newObject[key] = removeEmptyFields(value as Record<string, unknown>)\n } else if (value !== undefined) {\n newObject[key] = value\n }\n }\n return newObject as T\n}\n","import { assertEx } from '@xylabs/assert'\nimport { mapValues, merge, omitBy, pickBy } from '@xylabs/lodash'\nimport { EmptyObject, isObject } from '@xylabs/object'\n// eslint-disable-next-line no-restricted-imports\ntype ValueKeyIteratee<T> = (value: T, key: string) => unknown\n\nexport const deepBy = <T extends EmptyObject>(obj: T, predicate: ValueKeyIteratee<T>, func: typeof omitBy | typeof pickBy): T => {\n if (Array.isArray(obj)) {\n return obj\n }\n\n //pick the child objects\n const onlyObjects = pickBy<T>(obj, isObject)\n\n //pick the child non-objects\n const nonObjects = pickBy<T>(obj, (value) => !isObject(value))\n\n const pickedObjects = omitBy(onlyObjects, predicate)\n const pickedNonObjects = omitBy(nonObjects, predicate)\n\n const processedObjects = mapValues(pickedObjects, (obj: T) => deepBy(obj, predicate, func))\n\n return merge({}, pickedNonObjects, processedObjects) as T\n}\n\nexport const deepOmitPrefixedFields = <T extends EmptyObject>(obj: T, prefix: string): T => {\n return deepBy(\n obj,\n (_, key) => {\n assertEx(typeof key === 'string', () => `Invalid key type [${key}, ${typeof key}]`)\n return key.startsWith(prefix)\n },\n omitBy,\n )\n}\n\nexport const deepPickUnderscoreFields = <T extends EmptyObject>(obj: T): T => {\n return deepBy(\n obj,\n (_, key) => {\n assertEx(typeof key === 'string', () => `Invalid key type [${key}, ${typeof key}]`)\n return key.startsWith('_')\n },\n pickBy,\n )\n}\n","import { AnyObject, EmptyObject, isObject } from '@xylabs/object'\n\n//if an object, sub-sort\nconst subSort = (value: unknown) => {\n return isObject(value) ? sortFields(value) : value\n}\n\nexport const sortFields = <T extends EmptyObject>(obj: T) => {\n const result: AnyObject = {}\n const keys = Object.keys(obj) as (keyof T)[]\n for (const key of keys.sort()) {\n result[key] = subSort(obj[key])\n }\n return result as T\n}\n"],"mappings":"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","names":["asHash","hexFromArrayBuffer","ObjectWrapper","subtle","WasmSupport","sha256","shajs","typeOf","removeEmptyFields","obj","Array","isArray","newObject","key","value","Object","entries","typeOf","undefined","assertEx","mapValues","merge","omitBy","pickBy","isObject","deepBy","obj","predicate","func","Array","isArray","onlyObjects","pickBy","isObject","nonObjects","value","pickedObjects","omitBy","pickedNonObjects","processedObjects","mapValues","merge","deepOmitPrefixedFields","prefix","_","key","assertEx","startsWith","deepPickUnderscoreFields","isObject","subSort","value","isObject","sortFields","obj","result","keys","Object","key","sort","wasmSupportStatic","WasmSupport","PayloadHasher","ObjectWrapper","filterExcludeByHash","objs","hash","hashes","Array","isArray","hashPairs","filter","_","objHash","includes","map","pair","filterIncludeByHash","findByHash","find","obj","allowSubtle","enc","TextEncoder","stringToHash","stringifyHashFields","b","encode","hashArray","subtle","digest","hexFromArrayBuffer","bitLength","ex","error","console","message","log","stack","wasmInitialized","wasmSupport","canUseWasm","asHash","sha256","allowWasm","hashSync","hashFields","sortFields","removeEmptyFields","deepOmitPrefixedFields","Promise","all","shajs","update","toString","undefined","json","payload","meta","jsonPayload","JSON","stringify","initialize"]}
1
+ {"version":3,"sources":["../../src/PayloadHasher.ts","../../src/removeEmptyFields.ts","../../src/removeFields.ts","../../src/sortFields.ts"],"sourcesContent":["import { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'\nimport { EmptyObject, ObjectWrapper } from '@xylabs/object'\nimport { WasmSupport } from '@xyo-network/wasm'\nimport { Semaphore } from 'async-mutex'\nimport shajs from 'sha.js'\nimport { spawn, Worker } from 'threads'\n\nimport { removeEmptyFields } from './removeEmptyFields'\nimport { deepOmitPrefixedFields } from './removeFields'\nimport { sortFields } from './sortFields'\n\nconst wasmSupportStatic = new WasmSupport(['bigInt'])\nconst maxHashThreads = 8\nconst maxListenersPerThread = 1\n\nexport class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {\n static allowSubtle = true\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n static readonly jsHashThreads: any[] = []\n static readonly jsSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)\n\n static lastJsThreadUsed: number\n static lastSubtleThreadUsed: number\n static lastWasmThreadUsed: number\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n static readonly subtleHashThreads: any[] = []\n static readonly subtleSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n static readonly wasmHashThreads: any[] = []\n\n static readonly wasmInitialized = wasmSupportStatic.initialize()\n static readonly wasmSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)\n static readonly wasmSupport = wasmSupportStatic\n\n static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.hashPairs(objs)).filter(([_, objHash]) => !hashes.includes(objHash))?.map((pair) => pair[0])\n }\n\n static async filterIncludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.hashPairs(objs)).filter(([_, objHash]) => hashes.includes(objHash))?.map((pair) => pair[0])\n }\n\n static async findByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash): Promise<T | undefined> {\n return (await this.hashPairs(objs)).find(([_, objHash]) => objHash === hash)?.[0]\n }\n\n /**\n * Asynchronously hashes a payload\n * @param obj A payload\n * @returns The payload hash\n */\n static async hash<T extends EmptyObject>(obj: T): Promise<Hash> {\n const stringToHash = this.stringifyHashFields(obj)\n\n if (PayloadHasher.allowSubtle) {\n try {\n const enc = new TextEncoder()\n const data = enc.encode(stringToHash)\n const hashArray = await this.subtleHash(data)\n return hexFromArrayBuffer(hashArray, { bitLength: 256 })\n } catch (ex) {\n const error = ex as Error\n console.error(`Setting allowSubtle to false [${error.message}]`)\n console.log(error.stack)\n PayloadHasher.allowSubtle = false\n }\n }\n\n await this.wasmInitialized\n if (this.wasmSupport.canUseWasm) {\n try {\n return this.wasmHash(stringToHash)\n } catch {\n this.wasmSupport.allowWasm = false\n }\n }\n return await this.jsHash(stringToHash)\n }\n\n static hashFields<T extends EmptyObject>(obj: T): T {\n return sortFields(removeEmptyFields(deepOmitPrefixedFields(obj, '_')))\n }\n\n /**\n * Creates an array of payload/hash tuples based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload/hash tuples\n */\n static async hashPairs<T extends EmptyObject>(objs: T[]): Promise<[T, Hash][]> {\n return await Promise.all(objs.map<Promise<[T, string]>>(async (obj) => [obj, await PayloadHasher.hash(obj)]))\n }\n\n /**\n * Synchronously hashes a payload\n * @param obj A payload\n * @returns The payload hash\n */\n static hashSync<T extends EmptyObject>(obj: T): Hash {\n return asHash(shajs('sha256').update(this.stringifyHashFields(obj)).digest().toString('hex'), true)\n }\n\n /**\n * Creates an array of payload hashes based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload hashes\n */\n static async hashes<T extends EmptyObject>(objs?: T[]): Promise<Hash[] | undefined> {\n return objs ? await Promise.all(objs.map((obj) => this.hash(obj))) : undefined\n }\n\n static async jsHash(data: string) {\n await this.jsSemaphore.acquire()\n try {\n if (this.jsHashThreads.length < maxHashThreads) {\n const w = new Worker('./worker/jsHash.js')\n const worker = await spawn(w)\n this.jsHashThreads.push(worker)\n }\n let threadToUse = this.lastJsThreadUsed === undefined ? 0 : this.lastJsThreadUsed + 1\n if (threadToUse >= this.jsHashThreads.length) {\n threadToUse = 0\n }\n this.lastJsThreadUsed = threadToUse\n\n return await this.jsHashThreads[threadToUse].hash(data)\n } finally {\n this.jsSemaphore.release()\n }\n }\n\n /**\n * Returns a clone of the payload that is JSON safe\n * @param obj A payload\n * @param meta Keeps underscore (meta) fields if set to true\n * @returns Returns a clone of the payload that is JSON safe\n */\n static json<T extends EmptyObject>(payload: T, meta = false): T {\n return sortFields(removeEmptyFields(meta ? payload : deepOmitPrefixedFields(payload, '_')))\n }\n\n /** @deprecated us json instead */\n static jsonPayload<T extends EmptyObject>(payload: T, meta = false): T {\n return this.json(payload, meta)\n }\n\n static stringifyHashFields<T extends EmptyObject>(obj: T) {\n return JSON.stringify(this.hashFields(obj))\n }\n\n static async subtleHash(data: Uint8Array): Promise<ArrayBuffer> {\n await this.subtleSemaphore.acquire()\n try {\n if (this.subtleHashThreads.length < maxHashThreads) {\n const w = new Worker('./worker/subtleHash.js')\n const worker = await spawn(w)\n this.subtleHashThreads.push(worker)\n }\n let threadToUse = this.lastSubtleThreadUsed === undefined ? 0 : this.lastSubtleThreadUsed + 1\n if (threadToUse >= this.subtleHashThreads.length) {\n threadToUse = 0\n }\n this.lastSubtleThreadUsed = threadToUse\n\n return await this.subtleHashThreads[threadToUse].hash(data)\n } finally {\n this.subtleSemaphore.release()\n }\n }\n\n static async wasmHash(data: string) {\n await this.wasmSemaphore.acquire()\n try {\n if (this.wasmHashThreads.length < maxHashThreads) {\n const w = new Worker('./worker/wasmHash.js')\n const worker = await spawn(w)\n this.wasmHashThreads.push(worker)\n }\n let threadToUse = this.lastWasmThreadUsed === undefined ? 0 : this.lastWasmThreadUsed + 1\n if (threadToUse >= this.wasmHashThreads.length) {\n threadToUse = 0\n }\n this.lastWasmThreadUsed = threadToUse\n\n return await this.wasmHashThreads[threadToUse].hash(data)\n } finally {\n this.wasmSemaphore.release()\n }\n }\n\n async hash(): Promise<Hash> {\n return await PayloadHasher.hash(this.obj)\n }\n\n hashSync(): Hash {\n return PayloadHasher.hashSync(this.obj)\n }\n\n /**\n * Returns a clone of the payload that is JSON safe\n * @param meta Keeps underscore (meta) fields if set to true\n * @returns Returns a clone of the payload that is JSON safe\n */\n jsonPayload(meta = false): T {\n return PayloadHasher.jsonPayload(this.obj, meta)\n }\n}\n","import { AnyObject, EmptyObject } from '@xylabs/object'\nimport { typeOf } from '@xylabs/typeof'\n\nexport const removeEmptyFields = <T extends EmptyObject>(obj: T): T => {\n if (obj === null || Array.isArray(obj)) return obj\n\n const newObject: AnyObject = {}\n for (const [key, value] of Object.entries(obj)) {\n if (typeOf(value) === 'object') {\n newObject[key] = removeEmptyFields(value as Record<string, unknown>)\n } else if (value !== undefined) {\n newObject[key] = value\n }\n }\n return newObject as T\n}\n","import { assertEx } from '@xylabs/assert'\nimport { mapValues, merge, omitBy, pickBy } from '@xylabs/lodash'\nimport { EmptyObject, isObject } from '@xylabs/object'\n// eslint-disable-next-line no-restricted-imports\ntype ValueKeyIteratee<T> = (value: T, key: string) => unknown\n\nexport const deepBy = <T extends EmptyObject>(obj: T, predicate: ValueKeyIteratee<T>, func: typeof omitBy | typeof pickBy): T => {\n if (Array.isArray(obj)) {\n return obj\n }\n\n //pick the child objects\n const onlyObjects = pickBy<T>(obj, isObject)\n\n //pick the child non-objects\n const nonObjects = pickBy<T>(obj, (value) => !isObject(value))\n\n const pickedObjects = omitBy(onlyObjects, predicate)\n const pickedNonObjects = omitBy(nonObjects, predicate)\n\n const processedObjects = mapValues(pickedObjects, (obj: T) => deepBy(obj, predicate, func))\n\n return merge({}, pickedNonObjects, processedObjects) as T\n}\n\nexport const deepOmitPrefixedFields = <T extends EmptyObject>(obj: T, prefix: string): T => {\n return deepBy(\n obj,\n (_, key) => {\n assertEx(typeof key === 'string', () => `Invalid key type [${key}, ${typeof key}]`)\n return key.startsWith(prefix)\n },\n omitBy,\n )\n}\n\nexport const deepPickUnderscoreFields = <T extends EmptyObject>(obj: T): T => {\n return deepBy(\n obj,\n (_, key) => {\n assertEx(typeof key === 'string', () => `Invalid key type [${key}, ${typeof key}]`)\n return key.startsWith('_')\n },\n pickBy,\n )\n}\n","import { AnyObject, EmptyObject, isObject } from '@xylabs/object'\n\n//if an object, sub-sort\nconst subSort = (value: unknown) => {\n return isObject(value) ? sortFields(value) : value\n}\n\nexport const sortFields = <T extends EmptyObject>(obj: T) => {\n const result: AnyObject = {}\n const keys = Object.keys(obj) as (keyof T)[]\n for (const key of keys.sort()) {\n result[key] = subSort(obj[key])\n }\n return result as T\n}\n"],"mappings":"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","names":["asHash","hexFromArrayBuffer","ObjectWrapper","WasmSupport","Semaphore","shajs","spawn","Worker","typeOf","removeEmptyFields","obj","Array","isArray","newObject","key","value","Object","entries","typeOf","undefined","assertEx","mapValues","merge","omitBy","pickBy","isObject","deepBy","obj","predicate","func","Array","isArray","onlyObjects","pickBy","isObject","nonObjects","value","pickedObjects","omitBy","pickedNonObjects","processedObjects","mapValues","merge","deepOmitPrefixedFields","prefix","_","key","assertEx","startsWith","deepPickUnderscoreFields","isObject","subSort","value","isObject","sortFields","obj","result","keys","Object","key","sort","wasmSupportStatic","WasmSupport","maxHashThreads","maxListenersPerThread","PayloadHasher","ObjectWrapper","filterExcludeByHash","objs","hash","hashes","Array","isArray","hashPairs","filter","_","objHash","includes","map","pair","filterIncludeByHash","findByHash","find","obj","stringToHash","stringifyHashFields","allowSubtle","enc","TextEncoder","data","encode","hashArray","subtleHash","hexFromArrayBuffer","bitLength","ex","error","console","message","log","stack","wasmInitialized","wasmSupport","canUseWasm","wasmHash","allowWasm","jsHash","hashFields","sortFields","removeEmptyFields","deepOmitPrefixedFields","Promise","all","hashSync","asHash","shajs","update","digest","toString","undefined","jsSemaphore","acquire","jsHashThreads","length","w","Worker","worker","spawn","push","threadToUse","lastJsThreadUsed","release","json","payload","meta","jsonPayload","JSON","stringify","subtleSemaphore","subtleHashThreads","lastSubtleThreadUsed","wasmSemaphore","wasmHashThreads","lastWasmThreadUsed","Semaphore","initialize"]}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/worker/jsHash.js
26
+ var import_hex = require("@xylabs/hex");
27
+ var import_sha = __toESM(require("sha.js"), 1);
28
+ var import_worker = require("threads/worker");
29
+ (0, import_worker.expose)({
30
+ hash(data) {
31
+ return (0, import_hex.asHash)((0, import_sha.default)("sha256").update(data).digest().toString("hex"), true);
32
+ }
33
+ });
34
+ //# sourceMappingURL=jsHash.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/jsHash.js"],"sourcesContent":["import { asHash } from '@xylabs/hex'\nimport shajs from 'sha.js'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n hash(data) {\n return asHash(shajs('sha256').update(data).digest().toString('hex'), true)\n },\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAAuB;AACvB,iBAAkB;AAElB,oBAAuB;IAEvBA,sBAAO;EACLC,KAAKC,MAAI;AACP,eAAOC,uBAAOC,WAAAA,SAAM,QAAA,EAAUC,OAAOH,IAAAA,EAAMI,OAAM,EAAGC,SAAS,KAAA,GAAQ,IAAA;EACvE;AACF,CAAA;","names":["expose","hash","data","asHash","shajs","update","digest","toString"]}
@@ -0,0 +1,10 @@
1
+ // src/worker/jsHash.js
2
+ import { asHash } from "@xylabs/hex";
3
+ import shajs from "sha.js";
4
+ import { expose } from "threads/worker";
5
+ expose({
6
+ hash(data) {
7
+ return asHash(shajs("sha256").update(data).digest().toString("hex"), true);
8
+ }
9
+ });
10
+ //# sourceMappingURL=jsHash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/jsHash.js"],"sourcesContent":["import { asHash } from '@xylabs/hex'\nimport shajs from 'sha.js'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n hash(data) {\n return asHash(shajs('sha256').update(data).digest().toString('hex'), true)\n },\n})\n"],"mappings":";AAAA,SAASA,cAAc;AACvB,OAAOC,WAAW;AAElB,SAASC,cAAc;AAEvBA,OAAO;EACLC,KAAKC,MAAI;AACP,WAAOJ,OAAOC,MAAM,QAAA,EAAUI,OAAOD,IAAAA,EAAME,OAAM,EAAGC,SAAS,KAAA,GAAQ,IAAA;EACvE;AACF,CAAA;","names":["asHash","shajs","expose","hash","data","update","digest","toString"]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ // src/worker/subtleHash.js
4
+ var import_platform = require("@xylabs/platform");
5
+ var import_worker = require("threads/worker");
6
+ (0, import_worker.expose)({
7
+ async hash(data) {
8
+ return await import_platform.subtle.digest("SHA-256", data);
9
+ }
10
+ });
11
+ //# sourceMappingURL=subtleHash.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/subtleHash.js"],"sourcesContent":["import { subtle } from '@xylabs/platform'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n async hash(data) {\n return await subtle.digest('SHA-256', data)\n },\n})\n"],"mappings":";;;AAAA,sBAAuB;AAEvB,oBAAuB;IAEvBA,sBAAO;EACL,MAAMC,KAAKC,MAAI;AACb,WAAO,MAAMC,uBAAOC,OAAO,WAAWF,IAAAA;EACxC;AACF,CAAA;","names":["expose","hash","data","subtle","digest"]}
@@ -0,0 +1,9 @@
1
+ // src/worker/subtleHash.js
2
+ import { subtle } from "@xylabs/platform";
3
+ import { expose } from "threads/worker";
4
+ expose({
5
+ async hash(data) {
6
+ return await subtle.digest("SHA-256", data);
7
+ }
8
+ });
9
+ //# sourceMappingURL=subtleHash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/subtleHash.js"],"sourcesContent":["import { subtle } from '@xylabs/platform'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n async hash(data) {\n return await subtle.digest('SHA-256', data)\n },\n})\n"],"mappings":";AAAA,SAASA,cAAc;AAEvB,SAASC,cAAc;AAEvBA,OAAO;EACL,MAAMC,KAAKC,MAAI;AACb,WAAO,MAAMH,OAAOI,OAAO,WAAWD,IAAAA;EACxC;AACF,CAAA;","names":["subtle","expose","hash","data","digest"]}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ // src/worker/wasmHash.js
4
+ var import_hex = require("@xylabs/hex");
5
+ var import_hash_wasm = require("hash-wasm");
6
+ var import_worker = require("threads/worker");
7
+ (0, import_worker.expose)({
8
+ async hash(data) {
9
+ return (0, import_hex.asHash)(await (0, import_hash_wasm.sha256)(data), true);
10
+ }
11
+ });
12
+ //# sourceMappingURL=wasmHash.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/wasmHash.js"],"sourcesContent":["import { asHash } from '@xylabs/hex'\nimport { sha256 } from 'hash-wasm'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n async hash(data) {\n return asHash(await sha256(data), true)\n },\n})\n"],"mappings":";;;AAAA,iBAAuB;AACvB,uBAAuB;AAEvB,oBAAuB;IAEvBA,sBAAO;EACL,MAAMC,KAAKC,MAAI;AACb,eAAOC,mBAAO,UAAMC,yBAAOF,IAAAA,GAAO,IAAA;EACpC;AACF,CAAA;","names":["expose","hash","data","asHash","sha256"]}
@@ -0,0 +1,10 @@
1
+ // src/worker/wasmHash.js
2
+ import { asHash } from "@xylabs/hex";
3
+ import { sha256 } from "hash-wasm";
4
+ import { expose } from "threads/worker";
5
+ expose({
6
+ async hash(data) {
7
+ return asHash(await sha256(data), true);
8
+ }
9
+ });
10
+ //# sourceMappingURL=wasmHash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/worker/wasmHash.js"],"sourcesContent":["import { asHash } from '@xylabs/hex'\nimport { sha256 } from 'hash-wasm'\n// eslint-disable-next-line import/no-internal-modules\nimport { expose } from 'threads/worker'\n\nexpose({\n async hash(data) {\n return asHash(await sha256(data), true)\n },\n})\n"],"mappings":";AAAA,SAASA,cAAc;AACvB,SAASC,cAAc;AAEvB,SAASC,cAAc;AAEvBA,OAAO;EACL,MAAMC,KAAKC,MAAI;AACb,WAAOJ,OAAO,MAAMC,OAAOG,IAAAA,GAAO,IAAA;EACpC;AACF,CAAA;","names":["asHash","sha256","expose","hash","data"]}
package/package.json CHANGED
@@ -16,13 +16,16 @@
16
16
  "@xylabs/object": "^2.89.0",
17
17
  "@xylabs/platform": "^2.14.0",
18
18
  "@xylabs/typeof": "^2.14.0",
19
- "@xyo-network/wasm": "~2.89.3",
19
+ "@xyo-network/wasm": "~2.90.1",
20
+ "async-mutex": "^0.4.1",
20
21
  "hash-wasm": "^4.11.0",
21
- "sha.js": "^2.4.11"
22
+ "sha.js": "^2.4.11",
23
+ "threads": "^1.7.0"
22
24
  },
23
25
  "description": "Primary SDK for using XYO Protocol 2.0",
24
26
  "devDependencies": {
25
27
  "@types/sha.js": "^2.4.4",
28
+ "@xylabs/delay": "^2.14.0",
26
29
  "@xylabs/ts-scripts-yarn3": "^3.2.42",
27
30
  "@xylabs/tsconfig": "^3.2.42",
28
31
  "typescript": "^5.3.3"
@@ -65,6 +68,6 @@
65
68
  "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
66
69
  },
67
70
  "sideEffects": false,
68
- "version": "2.89.3",
71
+ "version": "2.90.1",
69
72
  "type": "module"
70
73
  }
@@ -1,19 +1,37 @@
1
1
  import { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'
2
2
  import { EmptyObject, ObjectWrapper } from '@xylabs/object'
3
- import { subtle } from '@xylabs/platform'
4
3
  import { WasmSupport } from '@xyo-network/wasm'
5
- import { sha256 } from 'hash-wasm'
4
+ import { Semaphore } from 'async-mutex'
6
5
  import shajs from 'sha.js'
6
+ import { spawn, Worker } from 'threads'
7
7
 
8
8
  import { removeEmptyFields } from './removeEmptyFields'
9
9
  import { deepOmitPrefixedFields } from './removeFields'
10
10
  import { sortFields } from './sortFields'
11
11
 
12
12
  const wasmSupportStatic = new WasmSupport(['bigInt'])
13
+ const maxHashThreads = 8
14
+ const maxListenersPerThread = 1
13
15
 
14
16
  export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {
15
17
  static allowSubtle = true
18
+
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ static readonly jsHashThreads: any[] = []
21
+ static readonly jsSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
22
+
23
+ static lastJsThreadUsed: number
24
+ static lastSubtleThreadUsed: number
25
+ static lastWasmThreadUsed: number
26
+
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ static readonly subtleHashThreads: any[] = []
29
+ static readonly subtleSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ static readonly wasmHashThreads: any[] = []
32
+
16
33
  static readonly wasmInitialized = wasmSupportStatic.initialize()
34
+ static readonly wasmSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
17
35
  static readonly wasmSupport = wasmSupportStatic
18
36
 
19
37
  static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
@@ -36,12 +54,13 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
36
54
  * @returns The payload hash
37
55
  */
38
56
  static async hash<T extends EmptyObject>(obj: T): Promise<Hash> {
57
+ const stringToHash = this.stringifyHashFields(obj)
58
+
39
59
  if (PayloadHasher.allowSubtle) {
40
60
  try {
41
61
  const enc = new TextEncoder()
42
- const stringToHash = this.stringifyHashFields(obj)
43
- const b = enc.encode(stringToHash)
44
- const hashArray = await subtle.digest('SHA-256', b)
62
+ const data = enc.encode(stringToHash)
63
+ const hashArray = await this.subtleHash(data)
45
64
  return hexFromArrayBuffer(hashArray, { bitLength: 256 })
46
65
  } catch (ex) {
47
66
  const error = ex as Error
@@ -53,14 +72,13 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
53
72
 
54
73
  await this.wasmInitialized
55
74
  if (this.wasmSupport.canUseWasm) {
56
- const stringToHash = this.stringifyHashFields(obj)
57
75
  try {
58
- return asHash(await sha256(stringToHash), true)
76
+ return this.wasmHash(stringToHash)
59
77
  } catch {
60
78
  this.wasmSupport.allowWasm = false
61
79
  }
62
80
  }
63
- return this.hashSync(obj)
81
+ return await this.jsHash(stringToHash)
64
82
  }
65
83
 
66
84
  static hashFields<T extends EmptyObject>(obj: T): T {
@@ -94,6 +112,26 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
94
112
  return objs ? await Promise.all(objs.map((obj) => this.hash(obj))) : undefined
95
113
  }
96
114
 
115
+ static async jsHash(data: string) {
116
+ await this.jsSemaphore.acquire()
117
+ try {
118
+ if (this.jsHashThreads.length < maxHashThreads) {
119
+ const w = new Worker('./worker/jsHash.js')
120
+ const worker = await spawn(w)
121
+ this.jsHashThreads.push(worker)
122
+ }
123
+ let threadToUse = this.lastJsThreadUsed === undefined ? 0 : this.lastJsThreadUsed + 1
124
+ if (threadToUse >= this.jsHashThreads.length) {
125
+ threadToUse = 0
126
+ }
127
+ this.lastJsThreadUsed = threadToUse
128
+
129
+ return await this.jsHashThreads[threadToUse].hash(data)
130
+ } finally {
131
+ this.jsSemaphore.release()
132
+ }
133
+ }
134
+
97
135
  /**
98
136
  * Returns a clone of the payload that is JSON safe
99
137
  * @param obj A payload
@@ -113,6 +151,46 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
113
151
  return JSON.stringify(this.hashFields(obj))
114
152
  }
115
153
 
154
+ static async subtleHash(data: Uint8Array): Promise<ArrayBuffer> {
155
+ await this.subtleSemaphore.acquire()
156
+ try {
157
+ if (this.subtleHashThreads.length < maxHashThreads) {
158
+ const w = new Worker('./worker/subtleHash.js')
159
+ const worker = await spawn(w)
160
+ this.subtleHashThreads.push(worker)
161
+ }
162
+ let threadToUse = this.lastSubtleThreadUsed === undefined ? 0 : this.lastSubtleThreadUsed + 1
163
+ if (threadToUse >= this.subtleHashThreads.length) {
164
+ threadToUse = 0
165
+ }
166
+ this.lastSubtleThreadUsed = threadToUse
167
+
168
+ return await this.subtleHashThreads[threadToUse].hash(data)
169
+ } finally {
170
+ this.subtleSemaphore.release()
171
+ }
172
+ }
173
+
174
+ static async wasmHash(data: string) {
175
+ await this.wasmSemaphore.acquire()
176
+ try {
177
+ if (this.wasmHashThreads.length < maxHashThreads) {
178
+ const w = new Worker('./worker/wasmHash.js')
179
+ const worker = await spawn(w)
180
+ this.wasmHashThreads.push(worker)
181
+ }
182
+ let threadToUse = this.lastWasmThreadUsed === undefined ? 0 : this.lastWasmThreadUsed + 1
183
+ if (threadToUse >= this.wasmHashThreads.length) {
184
+ threadToUse = 0
185
+ }
186
+ this.lastWasmThreadUsed = threadToUse
187
+
188
+ return await this.wasmHashThreads[threadToUse].hash(data)
189
+ } finally {
190
+ this.wasmSemaphore.release()
191
+ }
192
+ }
193
+
116
194
  async hash(): Promise<Hash> {
117
195
  return await PayloadHasher.hash(this.obj)
118
196
  }
@@ -0,0 +1,10 @@
1
+ import { asHash } from '@xylabs/hex'
2
+ import shajs from 'sha.js'
3
+ // eslint-disable-next-line import/no-internal-modules
4
+ import { expose } from 'threads/worker'
5
+
6
+ expose({
7
+ hash(data) {
8
+ return asHash(shajs('sha256').update(data).digest().toString('hex'), true)
9
+ },
10
+ })
@@ -0,0 +1,9 @@
1
+ import { subtle } from '@xylabs/platform'
2
+ // eslint-disable-next-line import/no-internal-modules
3
+ import { expose } from 'threads/worker'
4
+
5
+ expose({
6
+ async hash(data) {
7
+ return await subtle.digest('SHA-256', data)
8
+ },
9
+ })
@@ -0,0 +1,10 @@
1
+ import { asHash } from '@xylabs/hex'
2
+ import { sha256 } from 'hash-wasm'
3
+ // eslint-disable-next-line import/no-internal-modules
4
+ import { expose } from 'threads/worker'
5
+
6
+ expose({
7
+ async hash(data) {
8
+ return asHash(await sha256(data), true)
9
+ },
10
+ })
package/xy.config.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
2
+ const config: XyTsupConfig = {
3
+ compile: {
4
+ browser: {
5
+ src: { entry: ['./src/index.ts', './src/worker/*'] },
6
+ },
7
+ node: {
8
+ src: { entry: ['./src/index.ts', './src/worker/*'] },
9
+ },
10
+ },
11
+ }
12
+
13
+ // eslint-disable-next-line import/no-default-export
14
+ export default config