@xyo-network/hash 2.90.11 → 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.
- package/dist/browser/BrowserPayloadHasher.d.cts +9 -0
- package/dist/browser/BrowserPayloadHasher.d.cts.map +1 -0
- package/dist/browser/BrowserPayloadHasher.d.mts +9 -0
- package/dist/browser/BrowserPayloadHasher.d.mts.map +1 -0
- package/dist/browser/BrowserPayloadHasher.d.ts +9 -0
- package/dist/browser/BrowserPayloadHasher.d.ts.map +1 -0
- package/dist/browser/NodePayloadHasher.d.cts +5 -0
- package/dist/browser/NodePayloadHasher.d.cts.map +1 -0
- package/dist/browser/NodePayloadHasher.d.mts +5 -0
- package/dist/browser/NodePayloadHasher.d.mts.map +1 -0
- package/dist/browser/NodePayloadHasher.d.ts +5 -0
- package/dist/browser/NodePayloadHasher.d.ts.map +1 -0
- package/dist/browser/PayloadHasher.d.cts +14 -10
- package/dist/browser/PayloadHasher.d.cts.map +1 -1
- package/dist/browser/PayloadHasher.d.mts +14 -10
- package/dist/browser/PayloadHasher.d.mts.map +1 -1
- package/dist/browser/PayloadHasher.d.ts +14 -10
- package/dist/browser/PayloadHasher.d.ts.map +1 -1
- package/dist/browser/createBrowserWorker.d.cts +2 -0
- package/dist/browser/createBrowserWorker.d.cts.map +1 -0
- package/dist/browser/createBrowserWorker.d.mts +2 -0
- package/dist/browser/createBrowserWorker.d.mts.map +1 -0
- package/dist/browser/createBrowserWorker.d.ts +2 -0
- package/dist/browser/createBrowserWorker.d.ts.map +1 -0
- package/dist/browser/createNodeWorker.d.cts +2 -0
- package/dist/browser/createNodeWorker.d.cts.map +1 -0
- package/dist/browser/createNodeWorker.d.mts +2 -0
- package/dist/browser/createNodeWorker.d.mts.map +1 -0
- package/dist/browser/createNodeWorker.d.ts +2 -0
- package/dist/browser/createNodeWorker.d.ts.map +1 -0
- package/dist/browser/index-browser.cjs +96 -104
- package/dist/browser/index-browser.cjs.map +1 -1
- package/dist/browser/index-browser.d.cts +1 -1
- package/dist/browser/index-browser.d.cts.map +1 -1
- package/dist/browser/index-browser.d.mts +1 -1
- package/dist/browser/index-browser.d.mts.map +1 -1
- package/dist/browser/index-browser.d.ts +1 -1
- package/dist/browser/index-browser.d.ts.map +1 -1
- package/dist/browser/index-browser.js +95 -103
- package/dist/browser/index-browser.js.map +1 -1
- package/dist/browser/index.d.cts +1 -1
- package/dist/browser/index.d.cts.map +1 -1
- package/dist/browser/index.d.mts +1 -1
- package/dist/browser/index.d.mts.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/node/BrowserPayloadHasher.d.cts +9 -0
- package/dist/node/BrowserPayloadHasher.d.cts.map +1 -0
- package/dist/node/BrowserPayloadHasher.d.mts +9 -0
- package/dist/node/BrowserPayloadHasher.d.mts.map +1 -0
- package/dist/node/BrowserPayloadHasher.d.ts +9 -0
- package/dist/node/BrowserPayloadHasher.d.ts.map +1 -0
- package/dist/node/NodePayloadHasher.d.cts +5 -0
- package/dist/node/NodePayloadHasher.d.cts.map +1 -0
- package/dist/node/NodePayloadHasher.d.mts +5 -0
- package/dist/node/NodePayloadHasher.d.mts.map +1 -0
- package/dist/node/NodePayloadHasher.d.ts +5 -0
- package/dist/node/NodePayloadHasher.d.ts.map +1 -0
- package/dist/node/PayloadHasher.d.cts +14 -10
- package/dist/node/PayloadHasher.d.cts.map +1 -1
- package/dist/node/PayloadHasher.d.mts +14 -10
- package/dist/node/PayloadHasher.d.mts.map +1 -1
- package/dist/node/PayloadHasher.d.ts +14 -10
- package/dist/node/PayloadHasher.d.ts.map +1 -1
- package/dist/node/createBrowserWorker.d.cts +2 -0
- package/dist/node/createBrowserWorker.d.cts.map +1 -0
- package/dist/node/createBrowserWorker.d.mts +2 -0
- package/dist/node/createBrowserWorker.d.mts.map +1 -0
- package/dist/node/createBrowserWorker.d.ts +2 -0
- package/dist/node/createBrowserWorker.d.ts.map +1 -0
- package/dist/node/createNodeWorker.d.cts +2 -0
- package/dist/node/createNodeWorker.d.cts.map +1 -0
- package/dist/node/createNodeWorker.d.mts +2 -0
- package/dist/node/createNodeWorker.d.mts.map +1 -0
- package/dist/node/createNodeWorker.d.ts +2 -0
- package/dist/node/createNodeWorker.d.ts.map +1 -0
- package/dist/node/index-browser.d.cts +1 -1
- package/dist/node/index-browser.d.cts.map +1 -1
- package/dist/node/index-browser.d.mts +1 -1
- package/dist/node/index-browser.d.mts.map +1 -1
- package/dist/node/index-browser.d.ts +1 -1
- package/dist/node/index-browser.d.ts.map +1 -1
- package/dist/node/index.cjs +60 -86
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +1 -1
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.d.mts.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +60 -86
- package/dist/node/index.js.map +1 -1
- package/package.json +2 -3
- package/src/BrowserPayloadHasher.ts +34 -0
- package/src/NodePayloadHasher.ts +8 -0
- package/src/PayloadHasher.ts +40 -82
- package/src/createBrowserWorker.ts +10 -0
- package/src/createNodeWorker.ts +15 -0
- package/src/index-browser.ts +1 -1
- package/src/index.ts +1 -1
- package/dist/browser/PayloadHasher-browser.d.cts +0 -69
- package/dist/browser/PayloadHasher-browser.d.cts.map +0 -1
- package/dist/browser/PayloadHasher-browser.d.mts +0 -69
- package/dist/browser/PayloadHasher-browser.d.mts.map +0 -1
- package/dist/browser/PayloadHasher-browser.d.ts +0 -69
- package/dist/browser/PayloadHasher-browser.d.ts.map +0 -1
- package/dist/node/PayloadHasher-browser.d.cts +0 -69
- package/dist/node/PayloadHasher-browser.d.cts.map +0 -1
- package/dist/node/PayloadHasher-browser.d.mts +0 -69
- package/dist/node/PayloadHasher-browser.d.mts.map +0 -1
- package/dist/node/PayloadHasher-browser.d.ts +0 -69
- package/dist/node/PayloadHasher-browser.d.ts.map +0 -1
- package/src/PayloadHasher-browser.ts +0 -248
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { asHash, Hash, hexFromArrayBuffer } from '@xylabs/hex'
|
|
2
|
-
import { EmptyObject, ObjectWrapper } from '@xylabs/object'
|
|
3
|
-
import { WasmSupport } from '@xyo-network/wasm'
|
|
4
|
-
import { Semaphore } from 'async-mutex'
|
|
5
|
-
import shajs from 'sha.js'
|
|
6
|
-
import { spawn, Worker } from 'threads'
|
|
7
|
-
|
|
8
|
-
import { removeEmptyFields } from './removeEmptyFields'
|
|
9
|
-
import { deepOmitPrefixedFields } from './removeFields'
|
|
10
|
-
import { sortFields } from './sortFields'
|
|
11
|
-
import { jsHashFunc, subtleHashFunc, wasmHashFunc } from './worker'
|
|
12
|
-
|
|
13
|
-
const wasmSupportStatic = new WasmSupport(['bigInt'])
|
|
14
|
-
const maxHashThreads = 8
|
|
15
|
-
const maxListenersPerThread = 1
|
|
16
|
-
|
|
17
|
-
export class PayloadHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {
|
|
18
|
-
static allowSubtle = true
|
|
19
|
-
|
|
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
|
|
27
|
-
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
static readonly subtleHashThreads: any[] = []
|
|
30
|
-
static readonly subtleSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
|
|
31
|
-
static warnIfUsingJsHash = true
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
-
static readonly wasmHashThreads: any[] = []
|
|
34
|
-
|
|
35
|
-
static readonly wasmInitialized = wasmSupportStatic.initialize()
|
|
36
|
-
static readonly wasmSemaphore = new Semaphore(maxHashThreads * maxListenersPerThread)
|
|
37
|
-
static readonly wasmSupport = wasmSupportStatic
|
|
38
|
-
|
|
39
|
-
static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
|
|
40
|
-
const hashes = Array.isArray(hash) ? hash : [hash]
|
|
41
|
-
return (await this.hashPairs(objs)).filter(([_, objHash]) => !hashes.includes(objHash))?.map((pair) => pair[0])
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static async filterIncludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
|
|
45
|
-
const hashes = Array.isArray(hash) ? hash : [hash]
|
|
46
|
-
return (await this.hashPairs(objs)).filter(([_, objHash]) => hashes.includes(objHash))?.map((pair) => pair[0])
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static async findByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash): Promise<T | undefined> {
|
|
50
|
-
return (await this.hashPairs(objs)).find(([_, objHash]) => objHash === hash)?.[0]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Asynchronously hashes a payload
|
|
55
|
-
* @param obj A payload
|
|
56
|
-
* @returns The payload hash
|
|
57
|
-
*/
|
|
58
|
-
static async hash<T extends EmptyObject>(obj: T): Promise<Hash> {
|
|
59
|
-
const stringToHash = this.stringifyHashFields(obj)
|
|
60
|
-
|
|
61
|
-
if (PayloadHasher.allowSubtle) {
|
|
62
|
-
try {
|
|
63
|
-
const enc = new TextEncoder()
|
|
64
|
-
const data = enc.encode(stringToHash)
|
|
65
|
-
const hashArray = await this.subtleHash(data)
|
|
66
|
-
return hexFromArrayBuffer(hashArray, { bitLength: 256 })
|
|
67
|
-
} catch {
|
|
68
|
-
PayloadHasher.allowSubtle = false
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
await this.wasmInitialized
|
|
73
|
-
if (this.wasmSupport.canUseWasm) {
|
|
74
|
-
try {
|
|
75
|
-
return this.wasmHash(stringToHash)
|
|
76
|
-
} catch {
|
|
77
|
-
this.wasmSupport.allowWasm = false
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return await this.jsHash(stringToHash)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
static hashFields<T extends EmptyObject>(obj: T): T {
|
|
84
|
-
return sortFields(removeEmptyFields(deepOmitPrefixedFields(obj, '_')))
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Creates an array of payload/hash tuples based on the payloads passed in
|
|
89
|
-
* @param objs Any array of payloads
|
|
90
|
-
* @returns An array of payload/hash tuples
|
|
91
|
-
*/
|
|
92
|
-
static async hashPairs<T extends EmptyObject>(objs: T[]): Promise<[T, Hash][]> {
|
|
93
|
-
return await Promise.all(objs.map<Promise<[T, string]>>(async (obj) => [obj, await PayloadHasher.hash(obj)]))
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Synchronously hashes a payload
|
|
98
|
-
* @param obj A payload
|
|
99
|
-
* @returns The payload hash
|
|
100
|
-
*/
|
|
101
|
-
static hashSync<T extends EmptyObject>(obj: T): Hash {
|
|
102
|
-
return asHash(shajs('sha256').update(this.stringifyHashFields(obj)).digest().toString('hex'), true)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Creates an array of payload hashes based on the payloads passed in
|
|
107
|
-
* @param objs Any array of payloads
|
|
108
|
-
* @returns An array of payload hashes
|
|
109
|
-
*/
|
|
110
|
-
static async hashes<T extends EmptyObject>(objs?: T[]): Promise<Hash[] | undefined> {
|
|
111
|
-
return objs ? await Promise.all(objs.map((obj) => this.hash(obj))) : undefined
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
static async jsHash(data: string) {
|
|
115
|
-
await this.jsSemaphore.acquire()
|
|
116
|
-
if (PayloadHasher.warnIfUsingJsHash) {
|
|
117
|
-
console.warn('Using jsHash [No subtle or wasm?]')
|
|
118
|
-
}
|
|
119
|
-
try {
|
|
120
|
-
if (this.jsHashThreads.length < maxHashThreads) {
|
|
121
|
-
let w: Worker
|
|
122
|
-
try {
|
|
123
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
124
|
-
w = new Worker(new URL('worker/jsHash.js', import.meta.url) as any)
|
|
125
|
-
} catch {
|
|
126
|
-
//we do this to make jsdom work
|
|
127
|
-
const code = jsHashFunc.toString().slice(6)
|
|
128
|
-
w = new Worker(
|
|
129
|
-
code,
|
|
130
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
131
|
-
{ fromSource: true } as any,
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
const worker = await spawn(w)
|
|
135
|
-
this.jsHashThreads.push(worker)
|
|
136
|
-
}
|
|
137
|
-
let threadToUse = this.lastJsThreadUsed === undefined ? 0 : this.lastJsThreadUsed + 1
|
|
138
|
-
if (threadToUse >= this.jsHashThreads.length) {
|
|
139
|
-
threadToUse = 0
|
|
140
|
-
}
|
|
141
|
-
this.lastJsThreadUsed = threadToUse
|
|
142
|
-
|
|
143
|
-
return await this.jsHashThreads[threadToUse].hash(data)
|
|
144
|
-
} finally {
|
|
145
|
-
this.jsSemaphore.release()
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Returns a clone of the payload that is JSON safe
|
|
151
|
-
* @param obj A payload
|
|
152
|
-
* @param meta Keeps underscore (meta) fields if set to true
|
|
153
|
-
* @returns Returns a clone of the payload that is JSON safe
|
|
154
|
-
*/
|
|
155
|
-
static json<T extends EmptyObject>(payload: T, meta = false): T {
|
|
156
|
-
return sortFields(removeEmptyFields(meta ? payload : deepOmitPrefixedFields(payload, '_')))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** @deprecated us json instead */
|
|
160
|
-
static jsonPayload<T extends EmptyObject>(payload: T, meta = false): T {
|
|
161
|
-
return this.json(payload, meta)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
static stringifyHashFields<T extends EmptyObject>(obj: T) {
|
|
165
|
-
return JSON.stringify(this.hashFields(obj))
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
static async subtleHash(data: Uint8Array): Promise<ArrayBuffer> {
|
|
169
|
-
await this.subtleSemaphore.acquire()
|
|
170
|
-
try {
|
|
171
|
-
if (this.subtleHashThreads.length < maxHashThreads) {
|
|
172
|
-
let w: Worker
|
|
173
|
-
try {
|
|
174
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
-
w = new Worker(new URL('worker/subtleHash.js', import.meta.url) as any)
|
|
176
|
-
} catch {
|
|
177
|
-
//we do this to make jsdom work
|
|
178
|
-
const code = subtleHashFunc.toString().slice(6)
|
|
179
|
-
w = new Worker(
|
|
180
|
-
code,
|
|
181
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
|
-
{ fromSource: true } as any,
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
const worker = await spawn(w)
|
|
186
|
-
this.subtleHashThreads.push(worker)
|
|
187
|
-
}
|
|
188
|
-
let threadToUse = this.lastSubtleThreadUsed === undefined ? 0 : this.lastSubtleThreadUsed + 1
|
|
189
|
-
if (threadToUse >= this.subtleHashThreads.length) {
|
|
190
|
-
threadToUse = 0
|
|
191
|
-
}
|
|
192
|
-
this.lastSubtleThreadUsed = threadToUse
|
|
193
|
-
|
|
194
|
-
return await this.subtleHashThreads[threadToUse].hash(data)
|
|
195
|
-
} finally {
|
|
196
|
-
this.subtleSemaphore.release()
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
static async wasmHash(data: string) {
|
|
201
|
-
await this.wasmSemaphore.acquire()
|
|
202
|
-
try {
|
|
203
|
-
if (this.wasmHashThreads.length < maxHashThreads) {
|
|
204
|
-
let w: Worker
|
|
205
|
-
try {
|
|
206
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
207
|
-
w = new Worker(new URL('worker/wasmHash.js', import.meta.url) as any)
|
|
208
|
-
} catch {
|
|
209
|
-
//we do this to make jsdom work
|
|
210
|
-
const code = wasmHashFunc.toString().slice(6)
|
|
211
|
-
w = new Worker(
|
|
212
|
-
code,
|
|
213
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
214
|
-
{ fromSource: true } as any,
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
const worker = await spawn(w)
|
|
218
|
-
this.wasmHashThreads.push(worker)
|
|
219
|
-
}
|
|
220
|
-
let threadToUse = this.lastWasmThreadUsed === undefined ? 0 : this.lastWasmThreadUsed + 1
|
|
221
|
-
if (threadToUse >= this.wasmHashThreads.length) {
|
|
222
|
-
threadToUse = 0
|
|
223
|
-
}
|
|
224
|
-
this.lastWasmThreadUsed = threadToUse
|
|
225
|
-
|
|
226
|
-
return await this.wasmHashThreads[threadToUse].hash(data)
|
|
227
|
-
} finally {
|
|
228
|
-
this.wasmSemaphore.release()
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
async hash(): Promise<Hash> {
|
|
233
|
-
return await PayloadHasher.hash(this.obj)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
hashSync(): Hash {
|
|
237
|
-
return PayloadHasher.hashSync(this.obj)
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Returns a clone of the payload that is JSON safe
|
|
242
|
-
* @param meta Keeps underscore (meta) fields if set to true
|
|
243
|
-
* @returns Returns a clone of the payload that is JSON safe
|
|
244
|
-
*/
|
|
245
|
-
jsonPayload(meta = false): T {
|
|
246
|
-
return PayloadHasher.jsonPayload(this.obj, meta)
|
|
247
|
-
}
|
|
248
|
-
}
|