@xyo-network/hash 2.90.10 → 2.90.12

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 (113) hide show
  1. package/dist/browser/BrowserPayloadHasher.d.cts +9 -0
  2. package/dist/browser/BrowserPayloadHasher.d.cts.map +1 -0
  3. package/dist/browser/BrowserPayloadHasher.d.mts +9 -0
  4. package/dist/browser/BrowserPayloadHasher.d.mts.map +1 -0
  5. package/dist/browser/BrowserPayloadHasher.d.ts +9 -0
  6. package/dist/browser/BrowserPayloadHasher.d.ts.map +1 -0
  7. package/dist/browser/NodePayloadHasher.d.cts +5 -0
  8. package/dist/browser/NodePayloadHasher.d.cts.map +1 -0
  9. package/dist/browser/NodePayloadHasher.d.mts +5 -0
  10. package/dist/browser/NodePayloadHasher.d.mts.map +1 -0
  11. package/dist/browser/NodePayloadHasher.d.ts +5 -0
  12. package/dist/browser/NodePayloadHasher.d.ts.map +1 -0
  13. package/dist/browser/PayloadHasher.d.cts +14 -10
  14. package/dist/browser/PayloadHasher.d.cts.map +1 -1
  15. package/dist/browser/PayloadHasher.d.mts +14 -10
  16. package/dist/browser/PayloadHasher.d.mts.map +1 -1
  17. package/dist/browser/PayloadHasher.d.ts +14 -10
  18. package/dist/browser/PayloadHasher.d.ts.map +1 -1
  19. package/dist/browser/createBrowserWorker.d.cts +2 -0
  20. package/dist/browser/createBrowserWorker.d.cts.map +1 -0
  21. package/dist/browser/createBrowserWorker.d.mts +2 -0
  22. package/dist/browser/createBrowserWorker.d.mts.map +1 -0
  23. package/dist/browser/createBrowserWorker.d.ts +2 -0
  24. package/dist/browser/createBrowserWorker.d.ts.map +1 -0
  25. package/dist/browser/createNodeWorker.d.cts +2 -0
  26. package/dist/browser/createNodeWorker.d.cts.map +1 -0
  27. package/dist/browser/createNodeWorker.d.mts +2 -0
  28. package/dist/browser/createNodeWorker.d.mts.map +1 -0
  29. package/dist/browser/createNodeWorker.d.ts +2 -0
  30. package/dist/browser/createNodeWorker.d.ts.map +1 -0
  31. package/dist/browser/index-browser.cjs +96 -104
  32. package/dist/browser/index-browser.cjs.map +1 -1
  33. package/dist/browser/index-browser.d.cts +1 -1
  34. package/dist/browser/index-browser.d.cts.map +1 -1
  35. package/dist/browser/index-browser.d.mts +1 -1
  36. package/dist/browser/index-browser.d.mts.map +1 -1
  37. package/dist/browser/index-browser.d.ts +1 -1
  38. package/dist/browser/index-browser.d.ts.map +1 -1
  39. package/dist/browser/index-browser.js +95 -103
  40. package/dist/browser/index-browser.js.map +1 -1
  41. package/dist/browser/index.d.cts +1 -1
  42. package/dist/browser/index.d.cts.map +1 -1
  43. package/dist/browser/index.d.mts +1 -1
  44. package/dist/browser/index.d.mts.map +1 -1
  45. package/dist/browser/index.d.ts +1 -1
  46. package/dist/browser/index.d.ts.map +1 -1
  47. package/dist/node/BrowserPayloadHasher.d.cts +9 -0
  48. package/dist/node/BrowserPayloadHasher.d.cts.map +1 -0
  49. package/dist/node/BrowserPayloadHasher.d.mts +9 -0
  50. package/dist/node/BrowserPayloadHasher.d.mts.map +1 -0
  51. package/dist/node/BrowserPayloadHasher.d.ts +9 -0
  52. package/dist/node/BrowserPayloadHasher.d.ts.map +1 -0
  53. package/dist/node/NodePayloadHasher.d.cts +5 -0
  54. package/dist/node/NodePayloadHasher.d.cts.map +1 -0
  55. package/dist/node/NodePayloadHasher.d.mts +5 -0
  56. package/dist/node/NodePayloadHasher.d.mts.map +1 -0
  57. package/dist/node/NodePayloadHasher.d.ts +5 -0
  58. package/dist/node/NodePayloadHasher.d.ts.map +1 -0
  59. package/dist/node/PayloadHasher.d.cts +14 -10
  60. package/dist/node/PayloadHasher.d.cts.map +1 -1
  61. package/dist/node/PayloadHasher.d.mts +14 -10
  62. package/dist/node/PayloadHasher.d.mts.map +1 -1
  63. package/dist/node/PayloadHasher.d.ts +14 -10
  64. package/dist/node/PayloadHasher.d.ts.map +1 -1
  65. package/dist/node/createBrowserWorker.d.cts +2 -0
  66. package/dist/node/createBrowserWorker.d.cts.map +1 -0
  67. package/dist/node/createBrowserWorker.d.mts +2 -0
  68. package/dist/node/createBrowserWorker.d.mts.map +1 -0
  69. package/dist/node/createBrowserWorker.d.ts +2 -0
  70. package/dist/node/createBrowserWorker.d.ts.map +1 -0
  71. package/dist/node/createNodeWorker.d.cts +2 -0
  72. package/dist/node/createNodeWorker.d.cts.map +1 -0
  73. package/dist/node/createNodeWorker.d.mts +2 -0
  74. package/dist/node/createNodeWorker.d.mts.map +1 -0
  75. package/dist/node/createNodeWorker.d.ts +2 -0
  76. package/dist/node/createNodeWorker.d.ts.map +1 -0
  77. package/dist/node/index-browser.d.cts +1 -1
  78. package/dist/node/index-browser.d.cts.map +1 -1
  79. package/dist/node/index-browser.d.mts +1 -1
  80. package/dist/node/index-browser.d.mts.map +1 -1
  81. package/dist/node/index-browser.d.ts +1 -1
  82. package/dist/node/index-browser.d.ts.map +1 -1
  83. package/dist/node/index.cjs +60 -86
  84. package/dist/node/index.cjs.map +1 -1
  85. package/dist/node/index.d.cts +1 -1
  86. package/dist/node/index.d.cts.map +1 -1
  87. package/dist/node/index.d.mts +1 -1
  88. package/dist/node/index.d.mts.map +1 -1
  89. package/dist/node/index.d.ts +1 -1
  90. package/dist/node/index.d.ts.map +1 -1
  91. package/dist/node/index.js +60 -86
  92. package/dist/node/index.js.map +1 -1
  93. package/package.json +2 -3
  94. package/src/BrowserPayloadHasher.ts +34 -0
  95. package/src/NodePayloadHasher.ts +8 -0
  96. package/src/PayloadHasher.ts +40 -82
  97. package/src/createBrowserWorker.ts +10 -0
  98. package/src/createNodeWorker.ts +15 -0
  99. package/src/index-browser.ts +1 -1
  100. package/src/index.ts +1 -1
  101. package/dist/browser/PayloadHasher-browser.d.cts +0 -69
  102. package/dist/browser/PayloadHasher-browser.d.cts.map +0 -1
  103. package/dist/browser/PayloadHasher-browser.d.mts +0 -69
  104. package/dist/browser/PayloadHasher-browser.d.mts.map +0 -1
  105. package/dist/browser/PayloadHasher-browser.d.ts +0 -69
  106. package/dist/browser/PayloadHasher-browser.d.ts.map +0 -1
  107. package/dist/node/PayloadHasher-browser.d.cts +0 -69
  108. package/dist/node/PayloadHasher-browser.d.cts.map +0 -1
  109. package/dist/node/PayloadHasher-browser.d.mts +0 -69
  110. package/dist/node/PayloadHasher-browser.d.mts.map +0 -1
  111. package/dist/node/PayloadHasher-browser.d.ts +0 -69
  112. package/dist/node/PayloadHasher-browser.d.ts.map +0 -1
  113. package/src/PayloadHasher-browser.ts +0 -248
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA"}
@@ -1,4 +1,4 @@
1
- export * from './PayloadHasher';
1
+ export { NodePayloadHasher as PayloadHasher } from './NodePayloadHasher';
2
2
  export * from './removeEmptyFields';
3
3
  export * from './removeFields';
4
4
  export * from './sortFields';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA"}
@@ -13,13 +13,31 @@ var __publicField = (obj, key, value) => {
13
13
  return value;
14
14
  };
15
15
 
16
+ // src/createNodeWorker.ts
17
+ import { Worker } from "threads";
18
+ var createNodeWorker = /* @__PURE__ */ __name((func) => {
19
+ try {
20
+ const code = (func == null ? void 0 : func.toString().slice(6)) ?? "";
21
+ const w = new Worker(
22
+ code,
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ {
25
+ fromSource: true
26
+ }
27
+ );
28
+ return w;
29
+ } catch {
30
+ return;
31
+ }
32
+ }, "createNodeWorker");
33
+
16
34
  // src/PayloadHasher.ts
35
+ import { assertEx as assertEx2 } from "@xylabs/assert";
17
36
  import { asHash, hexFromArrayBuffer } from "@xylabs/hex";
18
37
  import { ObjectWrapper } from "@xylabs/object";
19
38
  import { WasmSupport } from "@xyo-network/wasm";
20
- import { Semaphore } from "async-mutex";
21
39
  import shajs from "sha.js";
22
- import { spawn, Worker } from "threads";
40
+ import { Pool, spawn } from "threads";
23
41
 
24
42
  // src/removeEmptyFields.ts
25
43
  import { typeOf } from "@xylabs/typeof";
@@ -118,9 +136,20 @@ var wasmHashFunc = /* @__PURE__ */ __name(() => {
118
136
  var wasmSupportStatic = new WasmSupport([
119
137
  "bigInt"
120
138
  ]);
121
- var maxHashThreads = 8;
122
- var maxListenersPerThread = 1;
123
139
  var _PayloadHasher = class _PayloadHasher extends ObjectWrapper {
140
+ static get jsHashPool() {
141
+ return this._jsHashPool = this._jsHashPool ?? this.createWorkerPool(this.jsHashWorkerUrl, jsHashFunc);
142
+ }
143
+ static get subtleHashPool() {
144
+ return this._subtleHashPool = this._subtleHashPool ?? this.createWorkerPool(this.subtleHashWorkerUrl, subtleHashFunc);
145
+ }
146
+ static get wasmHashPool() {
147
+ return this._wasmHashPool = this._wasmHashPool ?? this.createWorkerPool(this.wasmHashWorkerUrl, wasmHashFunc);
148
+ }
149
+ static createWorker(url, func) {
150
+ var _a, _b;
151
+ return assertEx2(((_a = this.createBrowserWorker) == null ? void 0 : _a.call(this, url)) ?? ((_b = this.createNodeWorker) == null ? void 0 : _b.call(this, func)), "Unable to create worker");
152
+ }
124
153
  static async filterExcludeByHash(objs = [], hash) {
125
154
  var _a;
126
155
  const hashes = Array.isArray(hash) ? hash : [
@@ -199,32 +228,10 @@ var _PayloadHasher = class _PayloadHasher extends ObjectWrapper {
199
228
  return objs ? await Promise.all(objs.map((obj) => this.hash(obj))) : void 0;
200
229
  }
201
230
  static async jsHash(data) {
202
- await this.jsSemaphore.acquire();
203
231
  if (_PayloadHasher.warnIfUsingJsHash) {
204
232
  console.warn("Using jsHash [No subtle or wasm?]");
205
233
  }
206
- try {
207
- if (this.jsHashThreads.length < maxHashThreads) {
208
- const code = jsHashFunc.toString().slice(6);
209
- const w = new Worker(
210
- code,
211
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
212
- {
213
- fromSource: true
214
- }
215
- );
216
- const worker = await spawn(w);
217
- this.jsHashThreads.push(worker);
218
- }
219
- let threadToUse = this.lastJsThreadUsed === void 0 ? 0 : this.lastJsThreadUsed + 1;
220
- if (threadToUse >= this.jsHashThreads.length) {
221
- threadToUse = 0;
222
- }
223
- this.lastJsThreadUsed = threadToUse;
224
- return await this.jsHashThreads[threadToUse].hash(data);
225
- } finally {
226
- this.jsSemaphore.release();
227
- }
234
+ return await this.jsHashPool.queue(async (thread) => await thread.hash(data));
228
235
  }
229
236
  /**
230
237
  * Returns a clone of the payload that is JSON safe
@@ -243,54 +250,14 @@ var _PayloadHasher = class _PayloadHasher extends ObjectWrapper {
243
250
  return JSON.stringify(this.hashFields(obj));
244
251
  }
245
252
  static async subtleHash(data) {
246
- await this.subtleSemaphore.acquire();
247
- try {
248
- if (this.subtleHashThreads.length < maxHashThreads) {
249
- const code = subtleHashFunc.toString().slice(6);
250
- const w = new Worker(
251
- code,
252
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
253
- {
254
- fromSource: true
255
- }
256
- );
257
- const worker = await spawn(w);
258
- this.subtleHashThreads.push(worker);
259
- }
260
- let threadToUse = this.lastSubtleThreadUsed === void 0 ? 0 : this.lastSubtleThreadUsed + 1;
261
- if (threadToUse >= this.subtleHashThreads.length) {
262
- threadToUse = 0;
263
- }
264
- this.lastSubtleThreadUsed = threadToUse;
265
- return await this.subtleHashThreads[threadToUse].hash(data);
266
- } finally {
267
- this.subtleSemaphore.release();
268
- }
253
+ return await this.subtleHashPool.queue(async (thread) => await thread.hash(data));
269
254
  }
270
255
  static async wasmHash(data) {
271
- await this.wasmSemaphore.acquire();
272
- try {
273
- if (this.wasmHashThreads.length < maxHashThreads) {
274
- const code = wasmHashFunc.toString().slice(6);
275
- const w = new Worker(
276
- code,
277
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
278
- {
279
- fromSource: true
280
- }
281
- );
282
- const worker = await spawn(w);
283
- this.wasmHashThreads.push(worker);
284
- }
285
- let threadToUse = this.lastWasmThreadUsed === void 0 ? 0 : this.lastWasmThreadUsed + 1;
286
- if (threadToUse >= this.wasmHashThreads.length) {
287
- threadToUse = 0;
288
- }
289
- this.lastWasmThreadUsed = threadToUse;
290
- return await this.wasmHashThreads[threadToUse].hash(data);
291
- } finally {
292
- this.wasmSemaphore.release();
293
- }
256
+ return await this.wasmHashPool.queue(async (thread) => await thread.hash(data));
257
+ }
258
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
259
+ static createWorkerPool(url, func, size = 8) {
260
+ return Pool(() => spawn(this.createWorker(url, func)), size);
294
261
  }
295
262
  async hash() {
296
263
  return await _PayloadHasher.hash(this.obj);
@@ -309,24 +276,31 @@ var _PayloadHasher = class _PayloadHasher extends ObjectWrapper {
309
276
  };
310
277
  __name(_PayloadHasher, "PayloadHasher");
311
278
  __publicField(_PayloadHasher, "allowSubtle", true);
312
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
- __publicField(_PayloadHasher, "jsHashThreads", []);
314
- __publicField(_PayloadHasher, "jsSemaphore", new Semaphore(maxHashThreads * maxListenersPerThread));
315
- __publicField(_PayloadHasher, "lastJsThreadUsed");
316
- __publicField(_PayloadHasher, "lastSubtleThreadUsed");
317
- __publicField(_PayloadHasher, "lastWasmThreadUsed");
318
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
319
- __publicField(_PayloadHasher, "subtleHashThreads", []);
320
- __publicField(_PayloadHasher, "subtleSemaphore", new Semaphore(maxHashThreads * maxListenersPerThread));
279
+ __publicField(_PayloadHasher, "createBrowserWorker");
280
+ __publicField(_PayloadHasher, "createNodeWorker");
281
+ __publicField(_PayloadHasher, "jsHashWorkerUrl");
282
+ __publicField(_PayloadHasher, "subtleHashWorkerUrl");
321
283
  __publicField(_PayloadHasher, "warnIfUsingJsHash", true);
322
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
323
- __publicField(_PayloadHasher, "wasmHashThreads", []);
284
+ __publicField(_PayloadHasher, "wasmHashWorkerUrl");
324
285
  __publicField(_PayloadHasher, "wasmInitialized", wasmSupportStatic.initialize());
325
- __publicField(_PayloadHasher, "wasmSemaphore", new Semaphore(maxHashThreads * maxListenersPerThread));
326
286
  __publicField(_PayloadHasher, "wasmSupport", wasmSupportStatic);
287
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
288
+ __publicField(_PayloadHasher, "_jsHashPool");
289
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
290
+ __publicField(_PayloadHasher, "_subtleHashPool");
291
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
+ __publicField(_PayloadHasher, "_wasmHashPool");
327
293
  var PayloadHasher = _PayloadHasher;
294
+
295
+ // src/NodePayloadHasher.ts
296
+ PayloadHasher.createNodeWorker = createNodeWorker;
297
+ var _NodePayloadHasher = class _NodePayloadHasher extends PayloadHasher {
298
+ };
299
+ __name(_NodePayloadHasher, "NodePayloadHasher");
300
+ __publicField(_NodePayloadHasher, "createNodeWorker", createNodeWorker);
301
+ var NodePayloadHasher = _NodePayloadHasher;
328
302
  export {
329
- PayloadHasher,
303
+ NodePayloadHasher as PayloadHasher,
330
304
  deepBy,
331
305
  deepOmitPrefixedFields,
332
306
  deepPickUnderscoreFields,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/PayloadHasher.ts","../../src/removeEmptyFields.ts","../../src/removeFields.ts","../../src/sortFields.ts","../../src/worker/jsHash.ts","../../src/worker/subtleHash.ts","../../src/worker/wasmHash.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'\nimport { jsHashFunc, subtleHashFunc, wasmHashFunc } from './worker'\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 static warnIfUsingJsHash = true\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 {\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 if (PayloadHasher.warnIfUsingJsHash) {\n console.warn('Using jsHash [No subtle or wasm?]')\n }\n try {\n if (this.jsHashThreads.length < maxHashThreads) {\n const code = jsHashFunc.toString().slice(6)\n const w = new Worker(\n code,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n { fromSource: true } as any,\n )\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 code = subtleHashFunc.toString().slice(6)\n const w = new Worker(\n code,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n { fromSource: true } as any,\n )\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 code = wasmHashFunc.toString().slice(6)\n const w = new Worker(\n code,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n { fromSource: true } as any,\n )\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","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const jsHashFunc = () => {\n const shajs = require('sha.js')\n const { asHash } = require('@xylabs/hex')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n hash(data: string) {\n return asHash(shajs('sha256').update(data).digest().toString('hex'), true)\n },\n })\n}\n","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const subtleHashFunc = () => {\n const { subtle } = require('@xylabs/platform')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n async hash(data: ArrayBuffer) {\n return await subtle.digest('SHA-256', data)\n },\n })\n}\n","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const wasmHashFunc = () => {\n const { sha256 } = require('hash-wasm')\n const { asHash } = require('@xylabs/hex')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n async hash(data: string) {\n return asHash(await sha256(data), true)\n },\n })\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","jsHashFunc","shajs","require","asHash","expose","hash","data","update","digest","toString","subtleHashFunc","subtle","require","expose","hash","data","digest","wasmHashFunc","sha256","require","asHash","expose","hash","data","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","wasmInitialized","wasmSupport","canUseWasm","wasmHash","allowWasm","jsHash","hashFields","sortFields","removeEmptyFields","deepOmitPrefixedFields","Promise","all","hashSync","asHash","shajs","update","digest","toString","undefined","jsSemaphore","acquire","warnIfUsingJsHash","console","warn","jsHashThreads","length","code","jsHashFunc","slice","w","Worker","fromSource","worker","spawn","push","threadToUse","lastJsThreadUsed","release","json","payload","meta","jsonPayload","JSON","stringify","subtleSemaphore","subtleHashThreads","subtleHashFunc","lastSubtleThreadUsed","wasmSemaphore","wasmHashThreads","wasmHashFunc","lastWasmThreadUsed","Semaphore","initialize"]}
1
+ {"version":3,"sources":["../../src/createNodeWorker.ts","../../src/PayloadHasher.ts","../../src/removeEmptyFields.ts","../../src/removeFields.ts","../../src/sortFields.ts","../../src/worker/jsHash.ts","../../src/worker/subtleHash.ts","../../src/worker/wasmHash.ts","../../src/NodePayloadHasher.ts"],"sourcesContent":["import { Worker } from 'threads'\n\nexport const createNodeWorker = (func?: () => unknown) => {\n try {\n const code = func?.toString().slice(6) ?? ''\n const w = new Worker(\n code,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n { fromSource: true } as any,\n )\n return w\n } catch {\n return\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'\nimport { EmptyObject, ObjectWrapper } from '@xylabs/object'\nimport { WasmSupport } from '@xyo-network/wasm'\nimport shajs from 'sha.js'\nimport { ModuleThread, Pool, spawn, Worker } from 'threads'\n// eslint-disable-next-line import/no-internal-modules\nimport { WorkerModule } from 'threads/dist/types/worker'\n\nimport { removeEmptyFields } from './removeEmptyFields'\nimport { deepOmitPrefixedFields } from './removeFields'\nimport { sortFields } from './sortFields'\nimport { jsHashFunc, subtleHashFunc, wasmHashFunc } from './worker'\n\nconst wasmSupportStatic = new WasmSupport(['bigInt'])\n\nexport class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {\n static allowSubtle = true\n static createBrowserWorker?: (url?: URL) => Worker | undefined\n static createNodeWorker?: (func?: () => unknown) => Worker | undefined\n\n static jsHashWorkerUrl?: URL\n static subtleHashWorkerUrl?: URL\n\n static warnIfUsingJsHash = true\n\n static wasmHashWorkerUrl?: URL\n\n static readonly wasmInitialized = wasmSupportStatic.initialize()\n static readonly wasmSupport = wasmSupportStatic\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static _jsHashPool?: Pool<ModuleThread<WorkerModule<any>>>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static _subtleHashPool?: Pool<ModuleThread<WorkerModule<any>>>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static _wasmHashPool?: Pool<ModuleThread<WorkerModule<any>>>\n\n private static get jsHashPool() {\n return (this._jsHashPool = this._jsHashPool ?? this.createWorkerPool(this.jsHashWorkerUrl, jsHashFunc))\n }\n\n private static get subtleHashPool() {\n return (this._subtleHashPool = this._subtleHashPool ?? this.createWorkerPool(this.subtleHashWorkerUrl, subtleHashFunc))\n }\n\n private static get wasmHashPool() {\n return (this._wasmHashPool = this._wasmHashPool ?? this.createWorkerPool(this.wasmHashWorkerUrl, wasmHashFunc))\n }\n\n static createWorker(url?: URL, func?: () => unknown) {\n return assertEx(this.createBrowserWorker?.(url) ?? this.createNodeWorker?.(func), 'Unable to create worker')\n }\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 {\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 if (PayloadHasher.warnIfUsingJsHash) {\n console.warn('Using jsHash [No subtle or wasm?]')\n }\n return await this.jsHashPool.queue(async (thread) => await thread.hash(data))\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 return await this.subtleHashPool.queue(async (thread) => await thread.hash(data))\n }\n\n static async wasmHash(data: string) {\n return await this.wasmHashPool.queue(async (thread) => await thread.hash(data))\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static createWorkerPool<T extends WorkerModule<any>>(url?: URL, func?: () => unknown, size = 8) {\n return Pool(() => spawn<T>(this.createWorker(url, func)), size)\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","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const jsHashFunc = () => {\n const shajs = require('sha.js')\n const { asHash } = require('@xylabs/hex')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n hash(data: string) {\n return asHash(shajs('sha256').update(data).digest().toString('hex'), true)\n },\n })\n}\n","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const subtleHashFunc = () => {\n const { subtle } = require('@xylabs/platform')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n async hash(data: ArrayBuffer) {\n return await subtle.digest('SHA-256', data)\n },\n })\n}\n","/* eslint-disable @typescript-eslint/no-var-requires */\nexport const wasmHashFunc = () => {\n const { sha256 } = require('hash-wasm')\n const { asHash } = require('@xylabs/hex')\n // eslint-disable-next-line import/no-internal-modules\n const { expose } = require('threads/worker')\n\n expose({\n async hash(data: string) {\n return asHash(await sha256(data), true)\n },\n })\n}\n","import { createNodeWorker } from './createNodeWorker'\nimport { PayloadHasher } from './PayloadHasher'\n\nPayloadHasher.createNodeWorker = createNodeWorker\n\nexport class NodePayloadHasher extends PayloadHasher {\n static override createNodeWorker = createNodeWorker\n}\n"],"mappings":"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","names":["Worker","createNodeWorker","func","code","toString","slice","w","Worker","fromSource","assertEx","asHash","hexFromArrayBuffer","ObjectWrapper","WasmSupport","shajs","Pool","spawn","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","jsHashFunc","shajs","require","asHash","expose","hash","data","update","digest","toString","subtleHashFunc","subtle","require","expose","hash","data","digest","wasmHashFunc","sha256","require","asHash","expose","hash","data","wasmSupportStatic","WasmSupport","PayloadHasher","ObjectWrapper","jsHashPool","_jsHashPool","createWorkerPool","jsHashWorkerUrl","jsHashFunc","subtleHashPool","_subtleHashPool","subtleHashWorkerUrl","subtleHashFunc","wasmHashPool","_wasmHashPool","wasmHashWorkerUrl","wasmHashFunc","createWorker","url","func","assertEx","createBrowserWorker","createNodeWorker","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","wasmInitialized","wasmSupport","canUseWasm","wasmHash","allowWasm","jsHash","hashFields","sortFields","removeEmptyFields","deepOmitPrefixedFields","Promise","all","hashSync","asHash","shajs","update","digest","toString","undefined","warnIfUsingJsHash","console","warn","queue","thread","json","payload","meta","jsonPayload","JSON","stringify","size","Pool","spawn","initialize","PayloadHasher","createNodeWorker","NodePayloadHasher"]}
package/package.json CHANGED
@@ -16,8 +16,7 @@
16
16
  "@xylabs/object": "^2.89.1",
17
17
  "@xylabs/platform": "^2.14.1",
18
18
  "@xylabs/typeof": "^2.14.1",
19
- "@xyo-network/wasm": "~2.90.10",
20
- "async-mutex": "^0.4.1",
19
+ "@xyo-network/wasm": "~2.90.12",
21
20
  "hash-wasm": "^4.11.0",
22
21
  "sha.js": "^2.4.11",
23
22
  "threads": "^1.7.0"
@@ -68,6 +67,6 @@
68
67
  "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
69
68
  },
70
69
  "sideEffects": false,
71
- "version": "2.90.10",
70
+ "version": "2.90.12",
72
71
  "type": "module"
73
72
  }
@@ -0,0 +1,34 @@
1
+ import { createBrowserWorker } from './createBrowserWorker'
2
+ import { createNodeWorker } from './createNodeWorker'
3
+ import { PayloadHasher } from './PayloadHasher'
4
+
5
+ // We put both in here so that things will work in jsdom/jest
6
+
7
+ PayloadHasher.createBrowserWorker = createBrowserWorker
8
+ PayloadHasher.createNodeWorker = createNodeWorker
9
+
10
+ export class BrowserPayloadHasher extends PayloadHasher {
11
+ static override createBrowserWorker = createBrowserWorker
12
+ static override createNodeWorker = createNodeWorker
13
+ static override jsHashWorkerUrl = (() => {
14
+ try {
15
+ return new URL('worker/jsHash.ts', import.meta.url)
16
+ } catch {
17
+ return
18
+ }
19
+ })()
20
+ static override subtleHashWorkerUrl = (() => {
21
+ try {
22
+ return new URL('worker/subtleHash.ts', import.meta.url)
23
+ } catch {
24
+ return
25
+ }
26
+ })()
27
+ static override wasmHashWorkerUrl = (() => {
28
+ try {
29
+ return new URL('worker/wasmHash.ts', import.meta.url)
30
+ } catch {
31
+ return
32
+ }
33
+ })()
34
+ }
@@ -0,0 +1,8 @@
1
+ import { createNodeWorker } from './createNodeWorker'
2
+ import { PayloadHasher } from './PayloadHasher'
3
+
4
+ PayloadHasher.createNodeWorker = createNodeWorker
5
+
6
+ export class NodePayloadHasher extends PayloadHasher {
7
+ static override createNodeWorker = createNodeWorker
8
+ }
@@ -1,9 +1,11 @@
1
+ import { assertEx } from '@xylabs/assert'
1
2
  import { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'
2
3
  import { EmptyObject, ObjectWrapper } from '@xylabs/object'
3
4
  import { WasmSupport } from '@xyo-network/wasm'
4
- import { Semaphore } from 'async-mutex'
5
5
  import shajs from 'sha.js'
6
- import { spawn, Worker } from 'threads'
6
+ import { ModuleThread, Pool, spawn, Worker } from 'threads'
7
+ // eslint-disable-next-line import/no-internal-modules
8
+ import { WorkerModule } from 'threads/dist/types/worker'
7
9
 
8
10
  import { removeEmptyFields } from './removeEmptyFields'
9
11
  import { deepOmitPrefixedFields } from './removeFields'
@@ -11,31 +13,45 @@ import { sortFields } from './sortFields'
11
13
  import { jsHashFunc, subtleHashFunc, wasmHashFunc } from './worker'
12
14
 
13
15
  const wasmSupportStatic = new WasmSupport(['bigInt'])
14
- const maxHashThreads = 8
15
- const maxListenersPerThread = 1
16
16
 
17
17
  export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {
18
18
  static allowSubtle = true
19
+ static createBrowserWorker?: (url?: URL) => Worker | undefined
20
+ static createNodeWorker?: (func?: () => unknown) => Worker | undefined
19
21
 
20
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
- static readonly jsHashThreads: any[] = []
22
- static readonly jsSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
23
-
24
- static lastJsThreadUsed: number
25
- static lastSubtleThreadUsed: number
26
- static lastWasmThreadUsed: number
22
+ static jsHashWorkerUrl?: URL
23
+ static subtleHashWorkerUrl?: URL
27
24
 
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- static readonly subtleHashThreads: any[] = []
30
- static readonly subtleSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
31
25
  static warnIfUsingJsHash = true
32
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
- static readonly wasmHashThreads: any[] = []
26
+
27
+ static wasmHashWorkerUrl?: URL
34
28
 
35
29
  static readonly wasmInitialized = wasmSupportStatic.initialize()
36
- static readonly wasmSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
37
30
  static readonly wasmSupport = wasmSupportStatic
38
31
 
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ private static _jsHashPool?: Pool<ModuleThread<WorkerModule<any>>>
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ private static _subtleHashPool?: Pool<ModuleThread<WorkerModule<any>>>
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ private static _wasmHashPool?: Pool<ModuleThread<WorkerModule<any>>>
38
+
39
+ private static get jsHashPool() {
40
+ return (this._jsHashPool = this._jsHashPool ?? this.createWorkerPool(this.jsHashWorkerUrl, jsHashFunc))
41
+ }
42
+
43
+ private static get subtleHashPool() {
44
+ return (this._subtleHashPool = this._subtleHashPool ?? this.createWorkerPool(this.subtleHashWorkerUrl, subtleHashFunc))
45
+ }
46
+
47
+ private static get wasmHashPool() {
48
+ return (this._wasmHashPool = this._wasmHashPool ?? this.createWorkerPool(this.wasmHashWorkerUrl, wasmHashFunc))
49
+ }
50
+
51
+ static createWorker(url?: URL, func?: () => unknown) {
52
+ return assertEx(this.createBrowserWorker?.(url) ?? this.createNodeWorker?.(func), 'Unable to create worker')
53
+ }
54
+
39
55
  static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
40
56
  const hashes = Array.isArray(hash) ? hash : [hash]
41
57
  return (await this.hashPairs(objs)).filter(([_, objHash]) => !hashes.includes(objHash))?.map((pair) => pair[0])
@@ -112,31 +128,10 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
112
128
  }
113
129
 
114
130
  static async jsHash(data: string) {
115
- await this.jsSemaphore.acquire()
116
131
  if (PayloadHasher.warnIfUsingJsHash) {
117
132
  console.warn('Using jsHash [No subtle or wasm?]')
118
133
  }
119
- try {
120
- if (this.jsHashThreads.length < maxHashThreads) {
121
- const code = jsHashFunc.toString().slice(6)
122
- const w = new Worker(
123
- code,
124
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
- { fromSource: true } as any,
126
- )
127
- const worker = await spawn(w)
128
- this.jsHashThreads.push(worker)
129
- }
130
- let threadToUse = this.lastJsThreadUsed === undefined ? 0 : this.lastJsThreadUsed + 1
131
- if (threadToUse >= this.jsHashThreads.length) {
132
- threadToUse = 0
133
- }
134
- this.lastJsThreadUsed = threadToUse
135
-
136
- return await this.jsHashThreads[threadToUse].hash(data)
137
- } finally {
138
- this.jsSemaphore.release()
139
- }
134
+ return await this.jsHashPool.queue(async (thread) => await thread.hash(data))
140
135
  }
141
136
 
142
137
  /**
@@ -159,53 +154,16 @@ export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWr
159
154
  }
160
155
 
161
156
  static async subtleHash(data: Uint8Array): Promise<ArrayBuffer> {
162
- await this.subtleSemaphore.acquire()
163
- try {
164
- if (this.subtleHashThreads.length < maxHashThreads) {
165
- const code = subtleHashFunc.toString().slice(6)
166
- const w = new Worker(
167
- code,
168
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
169
- { fromSource: true } as any,
170
- )
171
- const worker = await spawn(w)
172
- this.subtleHashThreads.push(worker)
173
- }
174
- let threadToUse = this.lastSubtleThreadUsed === undefined ? 0 : this.lastSubtleThreadUsed + 1
175
- if (threadToUse >= this.subtleHashThreads.length) {
176
- threadToUse = 0
177
- }
178
- this.lastSubtleThreadUsed = threadToUse
179
-
180
- return await this.subtleHashThreads[threadToUse].hash(data)
181
- } finally {
182
- this.subtleSemaphore.release()
183
- }
157
+ return await this.subtleHashPool.queue(async (thread) => await thread.hash(data))
184
158
  }
185
159
 
186
160
  static async wasmHash(data: string) {
187
- await this.wasmSemaphore.acquire()
188
- try {
189
- if (this.wasmHashThreads.length < maxHashThreads) {
190
- const code = wasmHashFunc.toString().slice(6)
191
- const w = new Worker(
192
- code,
193
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
194
- { fromSource: true } as any,
195
- )
196
- const worker = await spawn(w)
197
- this.wasmHashThreads.push(worker)
198
- }
199
- let threadToUse = this.lastWasmThreadUsed === undefined ? 0 : this.lastWasmThreadUsed + 1
200
- if (threadToUse >= this.wasmHashThreads.length) {
201
- threadToUse = 0
202
- }
203
- this.lastWasmThreadUsed = threadToUse
161
+ return await this.wasmHashPool.queue(async (thread) => await thread.hash(data))
162
+ }
204
163
 
205
- return await this.wasmHashThreads[threadToUse].hash(data)
206
- } finally {
207
- this.wasmSemaphore.release()
208
- }
164
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
165
+ private static createWorkerPool<T extends WorkerModule<any>>(url?: URL, func?: () => unknown, size = 8) {
166
+ return Pool(() => spawn<T>(this.createWorker(url, func)), size)
209
167
  }
210
168
 
211
169
  async hash(): Promise<Hash> {
@@ -0,0 +1,10 @@
1
+ import { Worker } from 'threads'
2
+
3
+ export const createBrowserWorker = (url?: URL) => {
4
+ try {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ return new Worker(url as any)
7
+ } catch {
8
+ return
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ import { Worker } from 'threads'
2
+
3
+ export const createNodeWorker = (func?: () => unknown) => {
4
+ try {
5
+ const code = func?.toString().slice(6) ?? ''
6
+ const w = new Worker(
7
+ code,
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ { fromSource: true } as any,
10
+ )
11
+ return w
12
+ } catch {
13
+ return
14
+ }
15
+ }
@@ -1,4 +1,4 @@
1
- export * from './PayloadHasher-browser'
1
+ export { BrowserPayloadHasher as PayloadHasher } from './BrowserPayloadHasher'
2
2
  export * from './removeEmptyFields'
3
3
  export * from './removeFields'
4
4
  export * from './sortFields'
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from './PayloadHasher'
1
+ export { NodePayloadHasher as PayloadHasher } from './NodePayloadHasher'
2
2
  export * from './removeEmptyFields'
3
3
  export * from './removeFields'
4
4
  export * from './sortFields'