@exodus/bytes 1.0.0-rc.0
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/LICENSE +21 -0
- package/README.md +3 -0
- package/array.js +17 -0
- package/assert.js +22 -0
- package/base64.js +204 -0
- package/hex.js +78 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Exodus Movement
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/array.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { assertTypedArray } from './assert.js'
|
|
2
|
+
|
|
3
|
+
const { Buffer } = globalThis // Buffer is optional
|
|
4
|
+
|
|
5
|
+
export function fromTypedArray(arr, format) {
|
|
6
|
+
assertTypedArray(arr)
|
|
7
|
+
switch (format) {
|
|
8
|
+
case 'uint8':
|
|
9
|
+
if (arr.constructor === Uint8Array) return arr // fast path
|
|
10
|
+
return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength)
|
|
11
|
+
case 'buffer':
|
|
12
|
+
if (arr.constructor === Buffer && Buffer.isBuffer(arr)) return arr
|
|
13
|
+
return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
throw new TypeError('Unexpected format')
|
|
17
|
+
}
|
package/assert.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function assert(x, msg) {
|
|
2
|
+
if (!x) throw new Error(msg || 'Assertion failed')
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function assertEmptyRest(rest) {
|
|
6
|
+
if (Object.keys(rest).length > 0) throw new TypeError('Unexpected extra options')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line sonarjs/no-nested-template-literals
|
|
10
|
+
const makeMessage = (name, extra) => `Expected${name ? ` ${name} to be` : ''} an Uint8Array${extra}`
|
|
11
|
+
|
|
12
|
+
const TypedArray = Object.getPrototypeOf(Uint8Array)
|
|
13
|
+
|
|
14
|
+
export function assertTypedArray(arr) {
|
|
15
|
+
assert(arr instanceof TypedArray, 'Expected a TypedArray instance')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function assertUint8(arr, { name, length, ...rest } = {}) {
|
|
19
|
+
assertEmptyRest(rest)
|
|
20
|
+
if (arr instanceof Uint8Array && (length === undefined || arr.length === length)) return
|
|
21
|
+
throw new TypeError(makeMessage(name, length === undefined ? '' : ` of size ${Number(length)}`))
|
|
22
|
+
}
|
package/base64.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { assert, assertUint8 } from './assert.js'
|
|
2
|
+
import { fromTypedArray } from './array.js'
|
|
3
|
+
|
|
4
|
+
// See https://datatracker.ietf.org/doc/html/rfc4648
|
|
5
|
+
|
|
6
|
+
// base64: A-Za-z0-9+/ and =
|
|
7
|
+
// base64url: A-Za-z0-9_-
|
|
8
|
+
|
|
9
|
+
const { Buffer, atob } = globalThis // Buffer is optional, only used when native
|
|
10
|
+
const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
|
|
11
|
+
const { toBase64: web64 } = Uint8Array.prototype // Modern engines have this
|
|
12
|
+
|
|
13
|
+
export function toBase64(x) {
|
|
14
|
+
assertUint8(x)
|
|
15
|
+
if (web64 && x.toBase64 === web64) return x.toBase64() // Modern
|
|
16
|
+
if (!haveNativeBuffer) return toBase64js(x, BASE64, true) // Fallback
|
|
17
|
+
if (x.constructor === Buffer && Buffer.isBuffer(x)) return x.toString('base64') // Older Node.js
|
|
18
|
+
return Buffer.from(x.buffer, x.byteOffset, x.byteLength).toString('base64') // Older Node.js
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// NOTE: base64url omits padding
|
|
22
|
+
export function toBase64url(x) {
|
|
23
|
+
assertUint8(x)
|
|
24
|
+
if (web64 && x.toBase64 === web64) return x.toBase64({ alphabet: 'base64url', omitPadding: true }) // Modern
|
|
25
|
+
if (!haveNativeBuffer) return toBase64js(x, BASE64URL, false) // Fallback
|
|
26
|
+
if (x.constructor === Buffer && Buffer.isBuffer(x)) return x.toString('base64url') // Older Node.js
|
|
27
|
+
return Buffer.from(x.buffer, x.byteOffset, x.byteLength).toString('base64url') // Older Node.js
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Unlike Buffer.from(), throws on invalid input (non-base64 symbols and incomplete chunks)
|
|
31
|
+
// Unlike Buffer.from() and Uint8Array.fromBase64(), does not allow spaces
|
|
32
|
+
// NOTE: Always operates in strict mode for last chunk
|
|
33
|
+
|
|
34
|
+
// Accepts both padded and non-padded variants, only strict base64
|
|
35
|
+
export function fromBase64(str, format = 'uint8') {
|
|
36
|
+
if (typeof str !== 'string') throw new TypeError('Input is not a string')
|
|
37
|
+
|
|
38
|
+
// These checks should be needed only for Buffer path, not Uint8Array.fromBase64 path, but JSC lacks proper checks
|
|
39
|
+
assert(str.length % 4 !== 1, 'Invalid base64 length') // JSC misses this in fromBase64
|
|
40
|
+
if (str.endsWith('=')) {
|
|
41
|
+
assert(str.length % 4 === 0, 'Invalid padded length') // JSC misses this too
|
|
42
|
+
assert(str[str.length - 3] !== '=', 'Excessive padding') // no more than two = at the end
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return fromTypedArray(fromBase64common(str, false), format)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Accepts both only non-padded strict base64url
|
|
49
|
+
export function fromBase64url(str, format = 'uint8') {
|
|
50
|
+
if (typeof str !== 'string') throw new TypeError('Input is not a string')
|
|
51
|
+
|
|
52
|
+
// These checks should be needed only for Buffer path, not Uint8Array.fromBase64 path, but JSC lacks proper checks
|
|
53
|
+
assert(str.length % 4 !== 1, 'Invalid base64 length') // JSC misses this in fromBase64
|
|
54
|
+
assert(!str.endsWith('='), 'Did not expect padding in base64url input') // inclusion is checked separately
|
|
55
|
+
|
|
56
|
+
return fromTypedArray(fromBase64common(str, true), format)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let fromBase64common
|
|
60
|
+
if (Uint8Array.fromBase64) {
|
|
61
|
+
// NOTICE: this is actually slower than our JS impl in older JavaScriptCore and (slightly) in SpiderMonkey, but faster on V8 and new JavaScriptCore
|
|
62
|
+
fromBase64common = (str, isBase64url) => {
|
|
63
|
+
const alphabet = isBase64url ? 'base64url' : 'base64'
|
|
64
|
+
assert(!/\s/u.test(str), `Invalid character in ${alphabet} input`) // all other chars are checked natively
|
|
65
|
+
const padded = str.length % 4 > 0 ? `${str}${'='.repeat(4 - (str.length % 4))}` : str
|
|
66
|
+
return Uint8Array.fromBase64(padded, { alphabet, lastChunkHandling: 'strict' })
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
fromBase64common = (str, isBase64url) => {
|
|
70
|
+
if (isBase64url) {
|
|
71
|
+
assert(!/[^0-9a-z_-]/iu.test(str), 'Invalid character in base64url input')
|
|
72
|
+
} else {
|
|
73
|
+
assert(!/[^0-9a-z=+/]/iu.test(str), 'Invalid character in base64 input')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let arr
|
|
77
|
+
if (!haveNativeBuffer && atob) {
|
|
78
|
+
// atob is faster than manual parsing on Hermes
|
|
79
|
+
const raw = atob(isBase64url ? str.replaceAll('-', '+').replaceAll('_', '/') : str)
|
|
80
|
+
arr = new Uint8Array(raw.length)
|
|
81
|
+
for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i)
|
|
82
|
+
} else {
|
|
83
|
+
// base64url is already checked to have no padding via a regex above
|
|
84
|
+
if (!isBase64url) {
|
|
85
|
+
const at = str.indexOf('=')
|
|
86
|
+
if (at >= 0) assert(!/[^=]/iu.test(str.slice(at)), 'Invalid padding')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
arr = haveNativeBuffer ? Buffer.from(str, 'base64') : fromBase64js(str)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (arr.length % 3 !== 0) {
|
|
93
|
+
// Check last chunk to be strict if it was incomplete
|
|
94
|
+
const expected = toBase64(arr.subarray(-(arr.length % 3)))
|
|
95
|
+
const end = str.length % 4 === 0 ? str.slice(-4) : str.slice(-(str.length % 4)).padEnd(4, '=')
|
|
96
|
+
const actual = isBase64url ? end.replaceAll('-', '+').replaceAll('_', '/') : end
|
|
97
|
+
if (expected !== actual) throw new Error('Invalid last chunk')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return arr
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const BASE64 = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/']
|
|
105
|
+
const BASE64URL = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_']
|
|
106
|
+
|
|
107
|
+
const BASE64_PAIRS = []
|
|
108
|
+
const BASE64URL_PAIRS = []
|
|
109
|
+
|
|
110
|
+
// We construct output by concatenating chars, this seems to be fine enough on modern JS engines
|
|
111
|
+
function toBase64js(arr, alphabet, padding) {
|
|
112
|
+
assertUint8(arr)
|
|
113
|
+
const fullChunks = Math.floor(arr.length / 3)
|
|
114
|
+
const fullChunksBytes = fullChunks * 3
|
|
115
|
+
let o = ''
|
|
116
|
+
let i = 0
|
|
117
|
+
|
|
118
|
+
const pairs = alphabet === BASE64URL ? BASE64URL_PAIRS : BASE64_PAIRS
|
|
119
|
+
if (pairs.length === 0) {
|
|
120
|
+
for (let i = 0; i < 64; i++) {
|
|
121
|
+
for (let j = 0; j < 64; j++) pairs.push(`${alphabet[i]}${alphabet[j]}`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Fast path for complete blocks
|
|
126
|
+
// This whole loop can be commented out, the algorithm won't change, it's just an optimization of the next loop
|
|
127
|
+
for (; i < fullChunksBytes; i += 3) {
|
|
128
|
+
const a = arr[i]
|
|
129
|
+
const b = arr[i + 1]
|
|
130
|
+
const c = arr[i + 2]
|
|
131
|
+
o += pairs[(a << 4) | (b >> 4)] + pairs[((b & 0x0f) << 8) | c]
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// If we have something left, process it with a full algo
|
|
135
|
+
let carry = 0
|
|
136
|
+
let shift = 2 // First byte needs to be shifted by 2 to get 6 bits
|
|
137
|
+
const length = arr.length
|
|
138
|
+
for (; i < length; i++) {
|
|
139
|
+
const x = arr[i]
|
|
140
|
+
o += alphabet[carry | (x >> shift)] // shift >= 2, so this fits
|
|
141
|
+
if (shift === 6) {
|
|
142
|
+
shift = 0
|
|
143
|
+
o += alphabet[x & 0x3f]
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
carry = (x << (6 - shift)) & 0x3f
|
|
147
|
+
shift += 2 // Each byte prints 6 bits and leaves 2 bits
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (shift !== 2) o += alphabet[carry] // shift 2 means we have no carry left
|
|
151
|
+
if (padding) o += ['', '==', '='][length - fullChunksBytes]
|
|
152
|
+
|
|
153
|
+
return o
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Assumes no chars after =, checked
|
|
157
|
+
let fromBase64jsMap
|
|
158
|
+
|
|
159
|
+
function fromBase64js(str) {
|
|
160
|
+
const map = fromBase64jsMap || new Array(256)
|
|
161
|
+
if (!fromBase64jsMap) {
|
|
162
|
+
fromBase64jsMap = map
|
|
163
|
+
BASE64.forEach((c, i) => (map[c.charCodeAt(0)] = i))
|
|
164
|
+
map['-'.charCodeAt(0)] = map['+'.charCodeAt(0)] // for base64url
|
|
165
|
+
map['_'.charCodeAt(0)] = map['/'.charCodeAt(0)] // for base64url
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let inputLength = str.length
|
|
169
|
+
while (str[inputLength - 1] === '=') inputLength--
|
|
170
|
+
|
|
171
|
+
const arr = new Uint8Array(Math.floor((inputLength * 3) / 4))
|
|
172
|
+
const tailLength = inputLength % 4
|
|
173
|
+
const mainLength = inputLength - tailLength // multiples of 4
|
|
174
|
+
|
|
175
|
+
let at = 0
|
|
176
|
+
let i = 0
|
|
177
|
+
let tmp
|
|
178
|
+
|
|
179
|
+
while (i < mainLength) {
|
|
180
|
+
tmp =
|
|
181
|
+
(map[str.charCodeAt(i)] << 18) |
|
|
182
|
+
(map[str.charCodeAt(i + 1)] << 12) |
|
|
183
|
+
(map[str.charCodeAt(i + 2)] << 6) |
|
|
184
|
+
map[str.charCodeAt(i + 3)]
|
|
185
|
+
arr[at++] = tmp >> 16
|
|
186
|
+
arr[at++] = (tmp >> 8) & 0xff
|
|
187
|
+
arr[at++] = tmp & 0xff
|
|
188
|
+
i += 4
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (tailLength === 3) {
|
|
192
|
+
tmp =
|
|
193
|
+
(map[str.charCodeAt(i)] << 10) |
|
|
194
|
+
(map[str.charCodeAt(i + 1)] << 4) |
|
|
195
|
+
(map[str.charCodeAt(i + 2)] >> 2)
|
|
196
|
+
arr[at++] = (tmp >> 8) & 0xff
|
|
197
|
+
arr[at++] = tmp & 0xff
|
|
198
|
+
} else if (tailLength === 2) {
|
|
199
|
+
tmp = (map[str.charCodeAt(i)] << 2) | (map[str.charCodeAt(i + 1)] >> 4)
|
|
200
|
+
arr[at++] = tmp & 0xff
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return arr
|
|
204
|
+
}
|
package/hex.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { assertTypedArray, assert } from './assert.js'
|
|
2
|
+
import { fromTypedArray } from './array.js'
|
|
3
|
+
|
|
4
|
+
const { Buffer } = globalThis // Buffer is optional, only used when native
|
|
5
|
+
const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
|
|
6
|
+
const { toHex: webHex } = Uint8Array.prototype // Modern engines have this
|
|
7
|
+
|
|
8
|
+
let hexArray
|
|
9
|
+
let dehexArray
|
|
10
|
+
|
|
11
|
+
export function toHex(arr) {
|
|
12
|
+
assertTypedArray(arr)
|
|
13
|
+
if (!(arr instanceof Uint8Array)) arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength)
|
|
14
|
+
if (webHex && arr.toHex === webHex) return arr.toHex()
|
|
15
|
+
if (haveNativeBuffer) {
|
|
16
|
+
if (arr.constructor === Buffer && Buffer.isBuffer(arr)) return arr.toString('hex')
|
|
17
|
+
return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength).toString('hex')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!hexArray) hexArray = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))
|
|
21
|
+
const length = arr.length // this helps Hermes
|
|
22
|
+
|
|
23
|
+
if (length > 3000) {
|
|
24
|
+
// Limit concatenation to avoid excessive GC
|
|
25
|
+
// Thresholds checked on Hermes
|
|
26
|
+
const concat = []
|
|
27
|
+
for (let i = 0; i < length; ) {
|
|
28
|
+
const step = i + 500
|
|
29
|
+
const end = step > length ? length : step
|
|
30
|
+
let chunk = ''
|
|
31
|
+
for (; i < end; i++) chunk += hexArray[arr[i]]
|
|
32
|
+
concat.push(chunk)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const res = concat.join('')
|
|
36
|
+
concat.length = 0
|
|
37
|
+
return res
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let out = ''
|
|
41
|
+
for (let i = 0; i < length; i++) out += hexArray[arr[i]]
|
|
42
|
+
return out
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Unlike Buffer.from(), throws on invalid input
|
|
46
|
+
let fromHex
|
|
47
|
+
if (Uint8Array.fromHex) {
|
|
48
|
+
fromHex = (str, format = 'uint8') => fromTypedArray(Uint8Array.fromHex(str), format)
|
|
49
|
+
} else {
|
|
50
|
+
fromHex = (str, format = 'uint8') => {
|
|
51
|
+
if (typeof str !== 'string') throw new TypeError('Input is not a string')
|
|
52
|
+
assert(str.length % 2 === 0, 'Input is not a hex string')
|
|
53
|
+
|
|
54
|
+
// We don't use native Buffer impl, as rechecking input make it slower than pure js
|
|
55
|
+
// This path is used only on older engines though
|
|
56
|
+
|
|
57
|
+
if (!dehexArray) {
|
|
58
|
+
dehexArray = new Array(103) // f is 102
|
|
59
|
+
for (let i = 0; i < 16; i++) {
|
|
60
|
+
const s = i.toString(16)
|
|
61
|
+
dehexArray[s.charCodeAt(0)] = dehexArray[s.toUpperCase().charCodeAt(0)] = i
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const arr = new Uint8Array(str.length / 2)
|
|
66
|
+
let j = 0
|
|
67
|
+
const length = arr.length // this helps Hermes
|
|
68
|
+
for (let i = 0; i < length; i++) {
|
|
69
|
+
const a = dehexArray[str.charCodeAt(j++)] * 16 + dehexArray[str.charCodeAt(j++)]
|
|
70
|
+
if (!a && Number.isNaN(a)) throw new Error('Input is not a hex string')
|
|
71
|
+
arr[i] = a
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return fromTypedArray(arr, format)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { fromHex }
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@exodus/bytes",
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
|
+
"description": "Various operations on Uint8Array data",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"lint": "eslint .",
|
|
7
|
+
"test:v8": "npm run test:d8 --",
|
|
8
|
+
"test:javascriptcore": "npm run test:jsc --",
|
|
9
|
+
"test:d8": "exodus-test --engine=d8:bundle",
|
|
10
|
+
"test:jsc": "exodus-test --engine=jsc:bundle",
|
|
11
|
+
"test:spidermonkey": "exodus-test --engine=spidermonkey:bundle",
|
|
12
|
+
"test:hermes": "exodus-test --engine=hermes:bundle",
|
|
13
|
+
"test:quickjs": "exodus-test --engine=quickjs:bundle",
|
|
14
|
+
"test:electron:bundle": "exodus-test --engine=electron:bundle",
|
|
15
|
+
"test:electron:as-node": "exodus-test --engine=electron-as-node:test",
|
|
16
|
+
"test:chrome:puppeteer": "exodus-test --engine=chrome:puppeteer",
|
|
17
|
+
"test:chromium:playwright": "exodus-test --engine=chromium:playwright",
|
|
18
|
+
"test:webkit:playwright": "exodus-test --engine=webkit:playwright",
|
|
19
|
+
"test:firefox:puppeteer": "exodus-test --engine=firefox:puppeteer",
|
|
20
|
+
"test:firefox:playwright": "exodus-test --engine=firefox:playwright",
|
|
21
|
+
"test": "exodus-test",
|
|
22
|
+
"jsvu": "jsvu",
|
|
23
|
+
"playwright": "exodus-test --playwright",
|
|
24
|
+
"benchmark": "exodus-test --concurrency=1 benchmarks/*.bench.js",
|
|
25
|
+
"coverage": "exodus-test --coverage"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/ExodusMovement/bytes.git"
|
|
30
|
+
},
|
|
31
|
+
"author": "Exodus Movement, Inc.",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/ExodusMovement/bytes/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/ExodusMovement/bytes#readme",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": "^20.19.0 || >=22.13.0"
|
|
39
|
+
},
|
|
40
|
+
"type": "module",
|
|
41
|
+
"files": [
|
|
42
|
+
"/assert.js",
|
|
43
|
+
"/base64.js",
|
|
44
|
+
"/array.js",
|
|
45
|
+
"/hex.js"
|
|
46
|
+
],
|
|
47
|
+
"exports": {
|
|
48
|
+
"./base64.js": "./base64.js",
|
|
49
|
+
"./array.js": "./array.js",
|
|
50
|
+
"./hex.js": "./hex.js"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@exodus/eslint-config": "^5.24.0",
|
|
55
|
+
"@exodus/prettier": "^1.0.0",
|
|
56
|
+
"@exodus/test": "^1.0.0-rc.105",
|
|
57
|
+
"@scure/base": "^1.2.6",
|
|
58
|
+
"@types/node": "^24.0.10",
|
|
59
|
+
"base-x": "^5.0.1",
|
|
60
|
+
"base32.js": "^0.1.0",
|
|
61
|
+
"base64-js": "^1.5.1",
|
|
62
|
+
"buffer": "^6.0.3",
|
|
63
|
+
"electron": "36.5.0",
|
|
64
|
+
"eslint": "^8.44.0",
|
|
65
|
+
"jsvu": "^3.0.0"
|
|
66
|
+
},
|
|
67
|
+
"prettier": "@exodus/prettier",
|
|
68
|
+
"packageManager": "pnpm@10.12.1+sha256.889bac470ec93ccc3764488a19d6ba8f9c648ad5e50a9a6e4be3768a5de387a3"
|
|
69
|
+
}
|