@xyo-network/hash 5.3.22 → 5.3.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/hash",
3
- "version": "5.3.22",
3
+ "version": "5.3.24",
4
4
  "description": "Primary SDK for using XYO Protocol 2.0",
5
5
  "homepage": "https://xyo.network",
6
6
  "bugs": {
@@ -44,45 +44,37 @@
44
44
  "types": "dist/neutral/index.d.ts",
45
45
  "files": [
46
46
  "dist",
47
- "src",
48
47
  "!**/*.bench.*",
49
48
  "!**/*.spec.*",
50
49
  "!**/*.test.*",
51
50
  "README.md"
52
51
  ],
53
- "scripts": {
54
- "bundle": "yarn subtleHashBundle && yarn wasmHashBundle",
55
- "package-build": "echo build && package-build-only && yarn bundle && yarn publint",
56
- "package-compile": "echo compile && package-compile-only && yarn bundle && yarn publint",
57
- "subtleHashBundle": "esbuild src/worker/subtleHash.ts --bundle --outfile=dist/browser/worker/subtleHash-bundle.mjs --target=chrome120,firefox120,safari14,edge120",
58
- "wasmHashBundle": "esbuild src/worker/wasmHash.ts --bundle --outfile=dist/browser/worker/wasmHash-bundle.mjs --target=chrome120,firefox120,safari14,edge120"
59
- },
60
52
  "dependencies": {
61
- "@xylabs/threads": "~5.0.91",
62
- "@xyo-network/wasm": "~5.3.22",
63
- "hash-wasm": "~4.12.0"
53
+ "@xylabs/threads": "~5.0.93",
54
+ "hash-wasm": "~4.12.0",
55
+ "@xyo-network/wasm": "~5.3.24"
64
56
  },
65
57
  "devDependencies": {
66
58
  "@opentelemetry/api": "^1.9.1",
67
59
  "@types/node": "^25.5.0",
68
- "@xylabs/hex": "^5.0.91",
69
- "@xylabs/platform": "^5.0.91",
70
- "@xylabs/sdk-js": "^5.0.91",
71
- "@xylabs/ts-scripts-common": "~7.6.8",
72
- "@xylabs/ts-scripts-yarn3": "~7.6.8",
73
- "@xylabs/tsconfig": "~7.6.8",
74
- "@xylabs/vitest-extended": "~5.0.91",
60
+ "@xylabs/hex": "^5.0.93",
61
+ "@xylabs/platform": "^5.0.93",
62
+ "@xylabs/sdk-js": "^5.0.93",
63
+ "@xylabs/threads": "~5.0.93",
64
+ "@xylabs/ts-scripts-common": "~7.6.16",
65
+ "@xylabs/ts-scripts-pnpm": "~7.6.16",
66
+ "@xylabs/tsconfig": "~7.6.16",
67
+ "@xylabs/vitest-extended": "~5.0.93",
75
68
  "acorn": "^8.16.0",
76
69
  "axios": "^1.14.0",
77
- "cosmiconfig": "^9.0.1",
78
- "esbuild": "~0.27.4",
79
- "eslint": "^10.1.0",
70
+ "esbuild": "~0.28.0",
71
+ "hash-wasm": "~4.12.0",
80
72
  "publint": "~0.3.18",
81
- "rollup": "^4.60.1",
82
73
  "typescript": "~5.9.3",
83
74
  "vite": "^8.0.3",
84
75
  "vitest": "~4.1.2",
85
- "zod": "^4.3.6"
76
+ "zod": "^4.3.6",
77
+ "@xyo-network/wasm": "~5.3.24"
86
78
  },
87
79
  "peerDependencies": {
88
80
  "@xylabs/sdk-js": "^5",
@@ -90,5 +82,12 @@
90
82
  },
91
83
  "publishConfig": {
92
84
  "access": "public"
85
+ },
86
+ "scripts": {
87
+ "bundle": "pnpm subtleHashBundle && pnpm wasmHashBundle",
88
+ "package-build": "echo build && package-build-only && pnpm bundle && pnpm publint",
89
+ "package-compile": "echo compile && package-compile-only && pnpm bundle && pnpm publint",
90
+ "subtleHashBundle": "esbuild src/worker/subtleHash.ts --bundle --outfile=dist/browser/worker/subtleHash-bundle.mjs --target=chrome120,firefox120,safari17,edge120",
91
+ "wasmHashBundle": "esbuild src/worker/wasmHash.ts --bundle --outfile=dist/browser/worker/wasmHash-bundle.mjs --target=chrome120,firefox120,safari17,edge120"
93
92
  }
94
- }
93
+ }
@@ -1,28 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/sdk-js'
2
-
3
- import { createBrowserWorker } from './createBrowserWorker.ts'
4
- import { createNodeWorker } from './createNodeWorker.ts'
5
- import { ObjectHasher } from './ObjectHasher.ts'
6
-
7
- ObjectHasher.createBrowserWorker = createBrowserWorker
8
- ObjectHasher.createNodeWorker = createNodeWorker
9
-
10
- export class BrowserObjectHasher<T extends EmptyObject = EmptyObject> extends ObjectHasher<T> {
11
- static override readonly createBrowserWorker = createBrowserWorker
12
- static override readonly createNodeWorker = createNodeWorker
13
- static override readonly subtleHashWorkerUrl = (() => {
14
- try {
15
- return new URL('worker/subtleHash-bundle.mjs', import.meta.url)
16
- } catch {
17
- return
18
- }
19
- })()
20
-
21
- static override readonly wasmHashWorkerUrl = (() => {
22
- try {
23
- return new URL('worker/wasmHash-bundle.mjs', import.meta.url)
24
- } catch {
25
- return
26
- }
27
- })()
28
- }
@@ -1,10 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/sdk-js'
2
-
3
- import { createNodeWorker } from './createNodeWorker.ts'
4
- import { ObjectHasher } from './ObjectHasher.ts'
5
-
6
- ObjectHasher.createNodeWorker = createNodeWorker
7
-
8
- export class NodeObjectHasher<T extends EmptyObject = EmptyObject> extends ObjectHasher<T> {
9
- static override readonly createNodeWorker = createNodeWorker
10
- }
@@ -1,213 +0,0 @@
1
- /* eslint-disable sonarjs/public-static-readonly */
2
-
3
- import type { EmptyObject, Hash } from '@xylabs/sdk-js'
4
- import {
5
- asHash, assertEx,
6
- hexFromArrayBuffer, ObjectWrapper, omitBy, subtle,
7
- } from '@xylabs/sdk-js'
8
- import type { ModuleThread, Worker } from '@xylabs/threads/master'
9
- import { Pool, spawn } from '@xylabs/threads/master'
10
- import { WasmSupport } from '@xyo-network/wasm'
11
- import { sha256 } from 'hash-wasm'
12
-
13
- import { removeEmptyFields } from './removeEmptyFields.ts'
14
- import { sortFields } from './sortFields.ts'
15
- import { subtleHashFunc, wasmHashFunc } from './worker/index.ts'
16
-
17
- export type WorkerFunction = ((...args: unknown[]) => unknown) | (() => unknown)
18
- export type WorkerModule<Keys extends string> = {
19
- [key in Keys]: WorkerFunction
20
- }
21
-
22
- const wasmSupportStatic = new WasmSupport(['bigInt'])
23
-
24
- const omitByPredicate = (prefix: string) => (_: unknown, key: string) => {
25
- assertEx(typeof key === 'string', () => `Invalid key type [${String(key)}, ${typeof key}]`)
26
- return String(key).startsWith(prefix)
27
- }
28
-
29
- export class ObjectHasher<T extends EmptyObject = EmptyObject> extends ObjectWrapper<T> {
30
- static allowHashPooling = true
31
- static allowSubtle = true
32
- static createBrowserWorker?: (url?: URL) => Worker | undefined
33
- static createNodeWorker?: (func?: () => unknown) => Worker | undefined
34
-
35
- static readonly subtleHashWorkerUrl?: URL
36
-
37
- static warnIfUsingJsHash = true
38
-
39
- static readonly wasmHashWorkerUrl?: URL
40
-
41
- static readonly wasmInitialized = wasmSupportStatic.initialize()
42
- static readonly wasmSupport = wasmSupportStatic
43
-
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- private static _subtleHashPool?: Pool<ModuleThread<WorkerModule<any>>> | null
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- private static _wasmHashPool?: Pool<ModuleThread<WorkerModule<any>>> | null
48
-
49
- private static get subtleHashPool() {
50
- if (!this.allowHashPooling || this._subtleHashPool === null) {
51
- return null
52
- }
53
- try {
54
- return (this._subtleHashPool
55
- = this._subtleHashPool ?? (this.subtleHashWorkerUrl ? this.createWorkerPool(this.subtleHashWorkerUrl, subtleHashFunc) : null))
56
- } catch {
57
- console.warn('Creating subtle hash worker failed')
58
- this._subtleHashPool = null
59
- return null
60
- }
61
- }
62
-
63
- private static get wasmHashPool() {
64
- if (!this.allowHashPooling || this._wasmHashPool === null) {
65
- return null
66
- }
67
- try {
68
- return (this._wasmHashPool
69
- = this._wasmHashPool ?? (this.wasmHashWorkerUrl ? this.createWorkerPool(this.wasmHashWorkerUrl, wasmHashFunc) : null))
70
- } catch {
71
- console.warn('Creating wasm hash worker failed')
72
- this._wasmHashPool = null
73
- return null
74
- }
75
- }
76
-
77
- static createWorker(url?: URL, func?: () => unknown): Worker {
78
- if (url) console.debug(`createWorker: ${url}`)
79
- return assertEx(this.createBrowserWorker?.(url) ?? this.createNodeWorker?.(func), () => 'Unable to create worker')
80
- }
81
-
82
- static async filterExcludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
83
- const hashes = Array.isArray(hash) ? hash : [hash]
84
- return (await this.hashPairs(objs)).filter(([_, objHash]) => !hashes.includes(objHash))?.map(pair => pair[0])
85
- }
86
-
87
- static async filterIncludeByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash[] | Hash): Promise<T[]> {
88
- const hashes = Array.isArray(hash) ? hash : [hash]
89
- return (await this.hashPairs(objs)).filter(([_, objHash]) => hashes.includes(objHash))?.map(pair => pair[0])
90
- }
91
-
92
- static async findByHash<T extends EmptyObject>(objs: T[] = [], hash: Hash): Promise<T | undefined> {
93
- return (await this.hashPairs(objs)).find(([_, objHash]) => objHash === hash)?.[0]
94
- }
95
-
96
- /**
97
- * Asynchronously hashes a payload
98
- * @param obj A payload
99
- * @returns The payload hash
100
- */
101
- static async hash<T extends EmptyObject>(obj: T): Promise<Hash> {
102
- const stringToHash = this.stringifyHashFields(obj)
103
- const enc = new TextEncoder()
104
- const data = enc.encode(stringToHash)
105
-
106
- if (ObjectHasher.allowSubtle) {
107
- try {
108
- const hashArray = await this.subtleHash(data)
109
- return hexFromArrayBuffer(hashArray, { bitLength: 256 }) as Hash
110
- } catch {
111
- ObjectHasher.allowSubtle = false
112
- }
113
- }
114
-
115
- await this.wasmInitialized
116
- if (this.wasmSupport.canUseWasm) {
117
- try {
118
- return await this.wasmHash(data)
119
- } catch {
120
- this.wasmSupport.allowWasm = false
121
- }
122
- }
123
- throw new Error('No subtle or wasm hashing available')
124
- }
125
-
126
- static async hashBytes(bytes: ArrayBuffer | Uint8Array): Promise<Hash> {
127
- const bytesArray = new Uint8Array(bytes)
128
- if (ObjectHasher.allowSubtle) {
129
- const hashArray = await this.subtleHash(bytesArray)
130
- return hexFromArrayBuffer(hashArray, { bitLength: 256 }) as Hash
131
- } else {
132
- await this.wasmInitialized
133
- if (this.wasmSupport.canUseWasm) {
134
- return await this.wasmHash(bytesArray)
135
- }
136
- throw new Error('No subtle or wasm hashing available')
137
- }
138
- }
139
-
140
- static hashFields<T extends EmptyObject>(obj: T): T {
141
- return sortFields(removeEmptyFields(omitBy(obj, omitByPredicate('_')))) as T
142
- }
143
-
144
- /**
145
- * Creates an array of payload/hash tuples based on the payloads passed in
146
- * @param objs Any array of payloads
147
- * @returns An array of payload/hash tuples
148
- */
149
- static async hashPairs<T extends EmptyObject>(objs: T[]): Promise<[T, Hash][]> {
150
- return await Promise.all(objs.map<Promise<[T, Hash]>>(async obj => [obj, await ObjectHasher.hash(obj)]))
151
- }
152
-
153
- /**
154
- * Creates an array of payload hashes based on the payloads passed in
155
- * @param objs Any array of payloads
156
- * @returns An array of payload hashes
157
- */
158
- static async hashes<T extends EmptyObject>(objs?: T[]): Promise<Hash[] | undefined> {
159
- return objs ? await Promise.all(objs.map(obj => this.hash(obj))) : undefined
160
- }
161
-
162
- /**
163
- * Returns a clone of the payload that is JSON safe
164
- * @param obj A payload
165
- * @param meta Keeps underscore (meta) fields if set to true
166
- * @returns Returns a clone of the payload that is JSON safe
167
- */
168
- static json<T extends EmptyObject>(payload: T, meta = false): T {
169
- return sortFields(removeEmptyFields(meta ? payload : omitBy(payload, omitByPredicate('_')))) as T
170
- }
171
-
172
- /** @deprecated us json instead */
173
- static jsonPayload<T extends EmptyObject>(payload: T, meta = false): T {
174
- return this.json(payload, meta)
175
- }
176
-
177
- static stringifyHashFields<T extends EmptyObject>(obj: T) {
178
- return JSON.stringify(this.hashFields(obj))
179
- }
180
-
181
- static async subtleHash(data: Uint8Array<ArrayBuffer>): Promise<ArrayBuffer> {
182
- const pool = this.subtleHashPool
183
- return pool === null ? await subtle.digest('SHA-256', data) : pool.queue(async thread => await thread.hash(data))
184
- }
185
-
186
- static async wasmHash(data: Uint8Array): Promise<Hash> {
187
- const pool = this.wasmHashPool
188
- return pool === null ? asHash(await sha256(data), true) : pool.queue(async thread => await thread.hash(data))
189
- }
190
-
191
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
192
- private static createWorkerPool<T extends WorkerModule<any>>(url?: URL, func?: () => unknown, size = 8) {
193
- if (url) console.debug(`createWorkerPool: ${url}`)
194
- const createFunc = () => spawn<T>(this.createWorker(url, func))
195
- return Pool(createFunc, size)
196
- }
197
-
198
- async hash(): Promise<Hash> {
199
- return await ObjectHasher.hash(this.obj)
200
- }
201
-
202
- /**
203
- * Returns a clone of the payload that is JSON safe
204
- * @param meta Keeps underscore (meta) fields if set to true
205
- * @returns Returns a clone of the payload that is JSON safe
206
- */
207
- json(meta = false): T {
208
- return ObjectHasher.json(this.obj, meta)
209
- }
210
- }
211
-
212
- /** @deprecated use PayloadBuilder or ObjectHasher instead */
213
- export class PayloadHasher<T extends object> extends ObjectHasher<T> {}
@@ -1,10 +0,0 @@
1
- import { Worker } from '@xylabs/threads/master'
2
-
3
- export const createBrowserWorker = (url?: URL): Worker => {
4
- try {
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- return new Worker(url as any)
7
- } catch {
8
- throw new Error('Unable to create worker')
9
- }
10
- }
@@ -1,14 +0,0 @@
1
- import { Worker } from '@xylabs/threads/master'
2
-
3
- export const createNodeWorker = (func?: () => unknown): Worker => {
4
- try {
5
- const code = func?.toString().slice(6) ?? ''
6
- return new Worker(
7
- code,
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- { fromSource: true } as any,
10
- )
11
- } catch {
12
- throw new Error('Unable to create worker')
13
- }
14
- }
@@ -1,17 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/sdk-js'
2
- import { typeOf } from '@xylabs/sdk-js'
3
-
4
- export const hasEmptyFields = <T extends EmptyObject>(obj: T): boolean => {
5
- if (obj == null || Array.isArray(obj)) return false
6
-
7
- if (obj == undefined || Object.keys(obj).length === 0) return true
8
-
9
- for (const [value] of Object.values(obj)) {
10
- if (typeOf(value) === 'object') {
11
- if (hasEmptyFields(value as Record<string, unknown>)) return true
12
- } else if (value === undefined) {
13
- return true
14
- }
15
- }
16
- return false
17
- }
@@ -1,3 +0,0 @@
1
- export { BrowserObjectHasher as ObjectHasher } from './BrowserObjectHasher.ts'
2
- export * from './removeEmptyFields.ts'
3
- export * from './sortFields.ts'
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './hasEmptyFields.ts'
2
- export { NodeObjectHasher as ObjectHasher } from './NodeObjectHasher.ts'
3
- export * from './removeEmptyFields.ts'
4
- export * from './sortFields.ts'
@@ -1,20 +0,0 @@
1
- import type { AnyObject, EmptyObject } from '@xylabs/sdk-js'
2
- import { typeOf } from '@xylabs/sdk-js'
3
-
4
- export const removeEmptyFields = <T extends EmptyObject>(obj: T): T => {
5
- if (obj == null) return obj
6
-
7
- if (Array.isArray(obj)) {
8
- return obj.map(value => (typeof value === 'object' ? removeEmptyFields(value) : value)) as T
9
- }
10
-
11
- const newObject: AnyObject = {}
12
- for (const [key, value] of Object.entries(obj)) {
13
- if (typeOf(value) === 'object') {
14
- newObject[key] = removeEmptyFields(value as Record<string, unknown>)
15
- } else if (value !== undefined) {
16
- newObject[key] = value
17
- }
18
- }
19
- return newObject as T
20
- }
package/src/sortFields.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { AnyObject, EmptyObject } from '@xylabs/sdk-js'
2
- import { isObject } from '@xylabs/sdk-js'
3
-
4
- // if an object, sub-sort
5
- const subSort = (value: unknown) => {
6
- return isObject(value) ? sortFields(value) : value
7
- }
8
-
9
- export const sortFields = <T extends EmptyObject>(obj: T) => {
10
- const result: AnyObject = {}
11
- const keys = Object.keys(obj) as (keyof T)[]
12
- // eslint-disable-next-line sonarjs/no-alphabetical-sort
13
- for (const key of keys.toSorted()) {
14
- result[key] = subSort(obj[key])
15
- }
16
- return result as T
17
- }
@@ -1,5 +0,0 @@
1
- export declare global {
2
- var xyo: {
3
- hashing?: boolean
4
- }
5
- }
@@ -1,2 +0,0 @@
1
- export * from './subtleHashNode.ts'
2
- export * from './wasmHashNode.ts'
@@ -1,8 +0,0 @@
1
- import { subtle } from '@xylabs/sdk-js'
2
- import { expose } from '@xylabs/threads/worker'
3
-
4
- expose({
5
- async hash(data: ArrayBuffer) {
6
- return await subtle.digest('SHA-256', data)
7
- },
8
- })
@@ -1,11 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-require-imports */
2
- export const subtleHashFunc = () => {
3
- const { subtle } = require('@xylabs/platform')
4
- const { expose } = require('@xylabs/threads/worker')
5
-
6
- expose({
7
- async hash(data: ArrayBuffer) {
8
- return await subtle.digest('SHA-256', data)
9
- },
10
- })
11
- }
@@ -1,9 +0,0 @@
1
- import { asHash } from '@xylabs/sdk-js'
2
- import { expose } from '@xylabs/threads/worker'
3
- import { sha256 } from 'hash-wasm'
4
-
5
- expose({
6
- async hash(data: string) {
7
- return asHash(await sha256(data), true)
8
- },
9
- })
@@ -1,13 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-require-imports */
2
- export const wasmHashFunc = () => {
3
- const { sha256 } = require('hash-wasm')
4
- const { asHash } = require('@xylabs/hex')
5
-
6
- const { expose } = require('@xylabs/threads/worker')
7
-
8
- expose({
9
- async hash(data: string) {
10
- return asHash(await sha256(data), true)
11
- },
12
- })
13
- }