@transia/isomorphic 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +124 -0
  3. package/dist/internal/normalizeInput.d.ts +9 -0
  4. package/dist/internal/normalizeInput.d.ts.map +1 -0
  5. package/dist/internal/normalizeInput.js +13 -0
  6. package/dist/internal/normalizeInput.js.map +1 -0
  7. package/dist/internal/types.d.ts +31 -0
  8. package/dist/internal/types.d.ts.map +1 -0
  9. package/dist/internal/types.js +3 -0
  10. package/dist/internal/types.js.map +1 -0
  11. package/dist/internal/wrapCryptoCreateHash.d.ts +11 -0
  12. package/dist/internal/wrapCryptoCreateHash.d.ts.map +1 -0
  13. package/dist/internal/wrapCryptoCreateHash.js +32 -0
  14. package/dist/internal/wrapCryptoCreateHash.js.map +1 -0
  15. package/dist/internal/wrapNoble.d.ts +9 -0
  16. package/dist/internal/wrapNoble.d.ts.map +1 -0
  17. package/dist/internal/wrapNoble.js +31 -0
  18. package/dist/internal/wrapNoble.js.map +1 -0
  19. package/dist/ripemd160/browser.d.ts +5 -0
  20. package/dist/ripemd160/browser.d.ts.map +1 -0
  21. package/dist/ripemd160/browser.js +13 -0
  22. package/dist/ripemd160/browser.js.map +1 -0
  23. package/dist/ripemd160/index.d.ts +5 -0
  24. package/dist/ripemd160/index.d.ts.map +1 -0
  25. package/dist/ripemd160/index.js +13 -0
  26. package/dist/ripemd160/index.js.map +1 -0
  27. package/dist/sha256/browser.d.ts +5 -0
  28. package/dist/sha256/browser.d.ts.map +1 -0
  29. package/dist/sha256/browser.js +13 -0
  30. package/dist/sha256/browser.js.map +1 -0
  31. package/dist/sha256/index.d.ts +5 -0
  32. package/dist/sha256/index.d.ts.map +1 -0
  33. package/dist/sha256/index.js +13 -0
  34. package/dist/sha256/index.js.map +1 -0
  35. package/dist/sha512/browser.d.ts +5 -0
  36. package/dist/sha512/browser.d.ts.map +1 -0
  37. package/dist/sha512/browser.js +13 -0
  38. package/dist/sha512/browser.js.map +1 -0
  39. package/dist/sha512/index.d.ts +5 -0
  40. package/dist/sha512/index.d.ts.map +1 -0
  41. package/dist/sha512/index.js +13 -0
  42. package/dist/sha512/index.js.map +1 -0
  43. package/dist/utils/browser.d.ts +8 -0
  44. package/dist/utils/browser.d.ts.map +1 -0
  45. package/dist/utils/browser.js +56 -0
  46. package/dist/utils/browser.js.map +1 -0
  47. package/dist/utils/index.d.ts +9 -0
  48. package/dist/utils/index.d.ts.map +1 -0
  49. package/dist/utils/index.js +85 -0
  50. package/dist/utils/index.js.map +1 -0
  51. package/dist/utils/shared.d.ts +4 -0
  52. package/dist/utils/shared.d.ts.map +1 -0
  53. package/dist/utils/shared.js +24 -0
  54. package/dist/utils/shared.js.map +1 -0
  55. package/dist/utils/types.d.ts +34 -0
  56. package/dist/utils/types.d.ts.map +1 -0
  57. package/dist/utils/types.js +3 -0
  58. package/dist/utils/types.js.map +1 -0
  59. package/dist/ws/browser.d.ts +52 -0
  60. package/dist/ws/browser.d.ts.map +1 -0
  61. package/dist/ws/browser.js +71 -0
  62. package/dist/ws/browser.js.map +1 -0
  63. package/dist/ws/index.d.ts +6 -0
  64. package/dist/ws/index.d.ts.map +1 -0
  65. package/dist/ws/index.js +14 -0
  66. package/dist/ws/index.js.map +1 -0
  67. package/package.json +52 -0
  68. package/ripemd160/package.json +7 -0
  69. package/sha256/package.json +7 -0
  70. package/sha512/package.json +7 -0
  71. package/src/internal/normalizeInput.ts +11 -0
  72. package/src/internal/types.ts +33 -0
  73. package/src/internal/wrapCryptoCreateHash.ts +32 -0
  74. package/src/internal/wrapNoble.ts +28 -0
  75. package/src/ripemd160/browser.ts +8 -0
  76. package/src/ripemd160/index.ts +7 -0
  77. package/src/sha256/browser.ts +8 -0
  78. package/src/sha256/index.ts +7 -0
  79. package/src/sha512/browser.ts +8 -0
  80. package/src/sha512/index.ts +7 -0
  81. package/src/utils/browser.ts +54 -0
  82. package/src/utils/index.ts +93 -0
  83. package/src/utils/shared.ts +21 -0
  84. package/src/utils/types.ts +37 -0
  85. package/src/ws/browser.ts +105 -0
  86. package/src/ws/index.ts +10 -0
  87. package/utils/package.json +7 -0
  88. package/ws/package.json +11 -0
@@ -0,0 +1,93 @@
1
+ import { randomBytes as cryptoRandomBytes } from 'crypto'
2
+ import type { BytesToHexFn, HexToBytesFn, RandomBytesFn } from './types'
3
+ import { HexToStringFn, StringToHexFn } from './types'
4
+ import { HEX_REGEX } from './shared'
5
+
6
+ const OriginalBuffer = Symbol('OriginalBuffer')
7
+
8
+ /**
9
+ * An extended Uint8Array that incorporates a reference to the original Node.js Buffer.
10
+ *
11
+ * When converting a Node.js Buffer to a Uint8Array, there's an optimization that shares
12
+ * the memory of the original Buffer with the resulting Uint8Array instead of copying data.
13
+ * The Uint8ArrayWithReference interface is used to attach a reference to the original Buffer, ensuring
14
+ * its persistence in memory (preventing garbage collection) as long as the Uint8Array exists.
15
+ * This strategy upholds the ownership semantics of the slice of the ArrayBuffer.
16
+ */
17
+ interface Uint8ArrayWithReference extends Uint8Array {
18
+ [OriginalBuffer]: Buffer
19
+ }
20
+
21
+ /**
22
+ * Converts a Node.js Buffer to a Uint8Array for uniform behavior with browser implementations.
23
+ *
24
+ * Choices:
25
+ * 1. Directly returning the Buffer:
26
+ * - Operation: Return Buffer as is (a Buffer *IS* an instanceof Uint8Array).
27
+ * - Pros: Most memory and performance efficient.
28
+ * - Cons: Violates strict Uint8Array typing and may lead to issues where Buffer-specific features are [ab]used.
29
+ *
30
+ * 2. Using `new Uint8Array(buffer)` or `Uint8Array.from(buffer)`:
31
+ * - Operation: Copies the buffer's data into a new Uint8Array.
32
+ * - Pros: Ensures data isolation; memory-safe.
33
+ * - Cons: Less performant due to data duplication.
34
+ *
35
+ * 3. Using buf.buffer slice:
36
+ * - Operation: Shares memory between Buffer and Uint8Array.
37
+ * - Pros: Performant.
38
+ * - Cons: Risks with shared memory and potential for invalid references.
39
+ *
40
+ * 4. Using buf.buffer slice and keeping a Buffer reference for ownership semantics:
41
+ * - Operation: Shares memory and associates the original Buffer with the resulting Uint8Array.
42
+ * - Pros: Performant while ensuring the original Buffer isn't garbage collected.
43
+ * - Cons: Risks with shared memory but mitigates potential for invalid references.
44
+ *
45
+ * The chosen method (4) prioritizes performance by sharing memory while ensuring buffer ownership.
46
+ *
47
+ * @param {Buffer} buffer - The Node.js Buffer to convert.
48
+ * @returns {Uint8Array} Resulting Uint8Array sharing the same memory as the Buffer and maintaining a reference to it.
49
+ */
50
+ function toUint8Array(buffer: Buffer): Uint8Array {
51
+ const u8Array = new Uint8Array(
52
+ buffer.buffer.slice(
53
+ buffer.byteOffset,
54
+ buffer.byteOffset + buffer.byteLength,
55
+ ),
56
+ ) as Uint8ArrayWithReference
57
+ u8Array[OriginalBuffer] = buffer
58
+ return u8Array
59
+ }
60
+
61
+ /* eslint-disable func-style -- Typed to ensure uniformity between node and browser implementations and docs */
62
+ export const bytesToHex: typeof BytesToHexFn = (bytes) => {
63
+ const buf = Buffer.from(bytes)
64
+ return buf.toString('hex').toUpperCase()
65
+ }
66
+
67
+ export const hexToBytes: typeof HexToBytesFn = (hex) => {
68
+ if (!HEX_REGEX.test(hex)) {
69
+ throw new Error('Invalid hex string')
70
+ }
71
+ return toUint8Array(Buffer.from(hex, 'hex'))
72
+ }
73
+
74
+ export const randomBytes: typeof RandomBytesFn = (size) => {
75
+ return toUint8Array(cryptoRandomBytes(size))
76
+ }
77
+
78
+ export const hexToString: typeof HexToStringFn = (
79
+ hex: string,
80
+ encoding = 'utf8',
81
+ ): string => {
82
+ if (!HEX_REGEX.test(hex)) {
83
+ throw new Error('Invalid hex string')
84
+ }
85
+ return new TextDecoder(encoding).decode(hexToBytes(hex))
86
+ }
87
+
88
+ export const stringToHex: typeof StringToHexFn = (string: string): string => {
89
+ return bytesToHex(new TextEncoder().encode(string))
90
+ }
91
+ /* eslint-enable func-style */
92
+
93
+ export * from './shared'
@@ -0,0 +1,21 @@
1
+ import { concatBytes } from '@noble/hashes/utils'
2
+
3
+ export const HEX_REGEX = /^[A-F0-9]*$/iu
4
+
5
+ export function concat(views: Uint8Array[]): Uint8Array {
6
+ return concatBytes(...views)
7
+ }
8
+
9
+ export function equal(buf1: Uint8Array, buf2: Uint8Array): boolean {
10
+ if (buf1.byteLength !== buf2.byteLength) {
11
+ return false
12
+ }
13
+ const dv1 = new Int8Array(buf1)
14
+ const dv2 = new Int8Array(buf2)
15
+ for (let i = 0; i !== buf1.byteLength; i++) {
16
+ if (dv1[i] !== dv2[i]) {
17
+ return false
18
+ }
19
+ }
20
+ return true
21
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Convert a UInt8Array to hex. The returned hex will be in all caps.
3
+ *
4
+ * @param bytes - {Uint8Array} to convert to hex
5
+ */
6
+ export declare function BytesToHexFn(bytes: Uint8Array | number[]): string
7
+
8
+ /**
9
+ * Convert hex to a Uint8Array.
10
+ *
11
+ * @param hex - {string} to convert to a Uint8Array
12
+ */
13
+ export declare function HexToBytesFn(hex: string): Uint8Array
14
+
15
+ /**
16
+ * Create a Uint8Array of the supplied size.
17
+ *
18
+ * @param size - number of bytes to generate
19
+ */
20
+ export declare function RandomBytesFn(size: number): Uint8Array
21
+
22
+ /**
23
+ * Converts hex to its string equivalent. Useful to read the Domain field and some Memos.
24
+ *
25
+ * @param hex - The hex to convert to a string.
26
+ * @param encoding - The encoding to use. Defaults to 'utf8' (UTF-8). 'ascii' is also allowed.
27
+ * @returns The converted string.
28
+ */
29
+ export declare function HexToStringFn(hex: string, encoding?: string): string
30
+
31
+ /**
32
+ * Converts a utf-8 to its hex equivalent. Useful for Memos.
33
+ *
34
+ * @param string - The string to convert to Hex.
35
+ * @returns The Hex equivalent of the string.
36
+ */
37
+ export declare function StringToHexFn(string: string): string
@@ -0,0 +1,105 @@
1
+ /* eslint-disable max-classes-per-file -- Needs to be a wrapper for ws */
2
+ import { EventEmitter } from 'eventemitter3'
3
+
4
+ // Define the global WebSocket class found on the native browser
5
+ declare class WebSocket {
6
+ public onclose?: (closeEvent: CloseEvent) => void
7
+ public onopen?: (openEvent: Event) => void
8
+ public onerror?: (error: Error) => void
9
+ public onmessage?: (message: MessageEvent) => void
10
+ public readyState: number
11
+ public constructor(url: string)
12
+ public close(code?: number, reason?: Uint8Array): void
13
+ public send(message: string): void
14
+ }
15
+
16
+ interface WSWrapperOptions {
17
+ perMessageDeflate: boolean
18
+ handshakeTimeout: number
19
+ protocolVersion: number
20
+ origin: string
21
+ maxPayload: number
22
+ followRedirects: boolean
23
+ maxRedirects: number
24
+ }
25
+
26
+ /**
27
+ * Provides `EventEmitter` interface for native browser `WebSocket`,
28
+ * same, as `ws` package provides.
29
+ */
30
+ export default class WSWrapper extends EventEmitter {
31
+ public static CONNECTING = 0
32
+ public static OPEN = 1
33
+ public static CLOSING = 2
34
+
35
+ public static CLOSED = 3
36
+ private readonly ws: WebSocket
37
+
38
+ /**
39
+ * Constructs a browser-safe websocket.
40
+ *
41
+ * @param url - URL to connect to.
42
+ * @param _protocols - Not used.
43
+ * @param _websocketOptions - Not used.
44
+ */
45
+ public constructor(
46
+ url: string,
47
+ _protocols: string | string[] | WSWrapperOptions | undefined,
48
+ _websocketOptions: WSWrapperOptions,
49
+ ) {
50
+ super()
51
+
52
+ this.ws = new WebSocket(url)
53
+
54
+ this.ws.onclose = (closeEvent: CloseEvent): void => {
55
+ let reason: Uint8Array | undefined
56
+ if (closeEvent.reason) {
57
+ const enc = new TextEncoder()
58
+ reason = enc.encode(closeEvent.reason)
59
+ }
60
+ this.emit('close', closeEvent.code, reason)
61
+ }
62
+
63
+ this.ws.onopen = (): void => {
64
+ this.emit('open')
65
+ }
66
+
67
+ this.ws.onerror = (error): void => {
68
+ this.emit('error', error)
69
+ }
70
+
71
+ this.ws.onmessage = (message: MessageEvent): void => {
72
+ this.emit('message', message.data)
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Get the ready state of the websocket.
78
+ *
79
+ * @returns The Websocket's ready state.
80
+ */
81
+ public get readyState(): number {
82
+ return this.ws.readyState
83
+ }
84
+
85
+ /**
86
+ * Closes the websocket.
87
+ *
88
+ * @param code - Close code.
89
+ * @param reason - Close reason.
90
+ */
91
+ public close(code?: number, reason?: Buffer): void {
92
+ if (this.readyState === 1) {
93
+ this.ws.close(code, reason)
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Sends a message over the Websocket connection.
99
+ *
100
+ * @param message - Message to send.
101
+ */
102
+ public send(message: string): void {
103
+ this.ws.send(message)
104
+ }
105
+ }
@@ -0,0 +1,10 @@
1
+ import WebSocket from 'ws'
2
+
3
+ export default class Socket extends WebSocket {
4
+ constructor(...args) {
5
+ super(args[0], args[1], args[2])
6
+ this.setMaxListeners(Infinity)
7
+ }
8
+ }
9
+
10
+ export type ClientOptions = WebSocket.ClientOptions
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@xrplf/isomorphic/utils",
3
+ "private": true,
4
+ "main": "../dist/utils",
5
+ "types": "../dist/utils",
6
+ "browser": "../dist/utils/browser.js"
7
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@xrplf/isomorphic/ws",
3
+ "private": true,
4
+ "main": "../dist/ws",
5
+ "types": "../dist/ws",
6
+ "browser": "../dist/ws/browser.js",
7
+ "dependencies": {
8
+ "ws": "^8.13.0",
9
+ "eventemitter3": "^5.0.1"
10
+ }
11
+ }