fix(core): proper browser support
not much really, fixed exports for webpack, fixed binary mode for websocket
This commit is contained in:
parent
5b9ddc1f7b
commit
8fb099cfeb
11 changed files with 65 additions and 56 deletions
|
@ -11,6 +11,11 @@
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"docs": "npx typedoc"
|
"docs": "npx typedoc"
|
||||||
},
|
},
|
||||||
|
"browser": {
|
||||||
|
"./utils/platform/crypto.js": "./utils/platform/crypto.web.js",
|
||||||
|
"./utils/platform/transport.js": "./utils/platform/transport.web.js",
|
||||||
|
"./storage/json-file.js": false
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^15.12.1",
|
"@types/node": "^15.12.1",
|
||||||
"@types/events": "^3.0.0",
|
"@types/events": "^3.0.0",
|
||||||
|
|
|
@ -8,24 +8,7 @@ export * from './websocket'
|
||||||
export * from './intermediate'
|
export * from './intermediate'
|
||||||
export * from './obfuscated'
|
export * from './obfuscated'
|
||||||
|
|
||||||
|
import { _defaultTransportFactory } from '../../utils/platform/transport'
|
||||||
|
|
||||||
/** Platform-defined default transport factory */
|
/** Platform-defined default transport factory */
|
||||||
export let defaultTransportFactory: TransportFactory
|
export const defaultTransportFactory: TransportFactory = _defaultTransportFactory
|
||||||
if (typeof process !== 'undefined') {
|
|
||||||
// we are in node, use tcp transport by default
|
|
||||||
const { TcpTransport } = require('./tcp')
|
|
||||||
defaultTransportFactory = () => new TcpTransport()
|
|
||||||
} else {
|
|
||||||
// we are in browser (probably), use websocket
|
|
||||||
// if no websocket, throw an error i guess ¯\_(ツ)_/¯
|
|
||||||
// (user can still implement something on their own)
|
|
||||||
if (typeof WebSocket === 'undefined') {
|
|
||||||
defaultTransportFactory = () => {
|
|
||||||
throw new Error(
|
|
||||||
'Neither TCP nor WebSocket are available. Please pass a Transport factory explicitly'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const { WebSocketTransport } = require('./websocket')
|
|
||||||
defaultTransportFactory = () => new WebSocketTransport()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -105,6 +105,8 @@ export abstract class BaseWebSocketTransport
|
||||||
'binary'
|
'binary'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this._socket.binaryType = 'arraybuffer'
|
||||||
|
|
||||||
this._socket.addEventListener('message', (evt) =>
|
this._socket.addEventListener('message', (evt) =>
|
||||||
this._packetCodec.feed(typedArrayToBuffer(evt.data))
|
this._packetCodec.feed(typedArrayToBuffer(evt.data))
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,7 +43,8 @@ export class JsonFileStorage extends JsonMemoryStorage {
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
if (!fs) throw new Error('Node fs module is not available!')
|
if (!fs || !fs.readFile)
|
||||||
|
throw new Error('Node fs module is not available!')
|
||||||
|
|
||||||
this._filename = filename
|
this._filename = filename
|
||||||
this._safe = params?.safe ?? true
|
this._safe = params?.safe ?? true
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
export let nodeCrypto: any = null
|
export { _randomBytes as randomBytes } from './platform/crypto'
|
||||||
if (typeof process !== 'undefined' && typeof require !== 'undefined') {
|
|
||||||
try {
|
|
||||||
nodeCrypto = require('crypto')
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// from https://github.com/feross/typedarray-to-buffer
|
// from https://github.com/feross/typedarray-to-buffer
|
||||||
// licensed under MIT
|
// licensed under MIT
|
||||||
|
@ -40,14 +35,6 @@ export function xorBufferInPlace(data: Buffer, key: Buffer): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function randomBytes(size: number): Buffer {
|
|
||||||
if (nodeCrypto) return nodeCrypto.randomBytes(size)
|
|
||||||
|
|
||||||
const ret = new Uint8Array(size)
|
|
||||||
crypto.getRandomValues(ret)
|
|
||||||
return typedArrayToBuffer(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function cloneBuffer(buf: Buffer, start = 0, end = buf.length): Buffer {
|
export function cloneBuffer(buf: Buffer, start = 0, end = buf.length): Buffer {
|
||||||
const ret = Buffer.alloc(end - start)
|
const ret = Buffer.alloc(end - start)
|
||||||
buf.copy(ret, 0, start, end)
|
buf.copy(ret, 0, start, end)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { CryptoProviderFactory } from './abstract'
|
|
||||||
import { nodeCrypto } from '../buffer-utils'
|
|
||||||
import { NodeCryptoProvider } from './node-crypto'
|
import { NodeCryptoProvider } from './node-crypto'
|
||||||
import { ForgeCryptoProvider } from './forge-crypto'
|
import { ForgeCryptoProvider } from './forge-crypto'
|
||||||
|
|
||||||
|
@ -8,9 +6,7 @@ export * from './password'
|
||||||
|
|
||||||
export { NodeCryptoProvider, ForgeCryptoProvider }
|
export { NodeCryptoProvider, ForgeCryptoProvider }
|
||||||
|
|
||||||
export let defaultCryptoProviderFactory: CryptoProviderFactory
|
import { _defaultCryptoProviderFactory } from '../platform/crypto'
|
||||||
if (nodeCrypto) {
|
import { CryptoProviderFactory } from './abstract'
|
||||||
defaultCryptoProviderFactory = () => new NodeCryptoProvider()
|
|
||||||
} else {
|
export const defaultCryptoProviderFactory: CryptoProviderFactory = _defaultCryptoProviderFactory
|
||||||
defaultCryptoProviderFactory = () => new ForgeCryptoProvider()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
import { BaseCryptoProvider, IEncryptionScheme, IHashMethod } from './abstract'
|
import { BaseCryptoProvider, IEncryptionScheme, IHashMethod } from './abstract'
|
||||||
import { MaybeAsync } from '../../types'
|
import { MaybeAsync } from '../../types'
|
||||||
import { nodeCrypto } from '../buffer-utils'
|
import { createCipheriv, createDecipheriv, createHash, createHmac, pbkdf2 } from 'crypto'
|
||||||
|
|
||||||
export class NodeCryptoProvider extends BaseCryptoProvider {
|
export class NodeCryptoProvider extends BaseCryptoProvider {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
if (!nodeCrypto)
|
|
||||||
throw new Error('Cannot use Node crypto functions outside NodeJS!')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createAesCtr(key: Buffer, iv: Buffer, encrypt: boolean): IEncryptionScheme {
|
createAesCtr(key: Buffer, iv: Buffer, encrypt: boolean): IEncryptionScheme {
|
||||||
const cipher = nodeCrypto[
|
const cipher = (
|
||||||
encrypt ? 'createCipheriv' : 'createDecipheriv'
|
encrypt ? createCipheriv : createDecipheriv
|
||||||
](`aes-${key.length * 8}-ctr`, key, iv)
|
)(`aes-${key.length * 8}-ctr`, key, iv)
|
||||||
|
|
||||||
const update = (data: Buffer) => cipher.update(data)
|
const update = (data: Buffer) => cipher.update(data)
|
||||||
|
|
||||||
|
@ -27,12 +25,12 @@ export class NodeCryptoProvider extends BaseCryptoProvider {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
encrypt(data: Buffer) {
|
encrypt(data: Buffer) {
|
||||||
const cipher = nodeCrypto.createCipheriv(methodName, key, null)
|
const cipher = createCipheriv(methodName, key, null)
|
||||||
cipher.setAutoPadding(false)
|
cipher.setAutoPadding(false)
|
||||||
return Buffer.concat([cipher.update(data), cipher.final()])
|
return Buffer.concat([cipher.update(data), cipher.final()])
|
||||||
},
|
},
|
||||||
decrypt(data: Buffer) {
|
decrypt(data: Buffer) {
|
||||||
const cipher = nodeCrypto.createDecipheriv(
|
const cipher = createDecipheriv(
|
||||||
methodName,
|
methodName,
|
||||||
key,
|
key,
|
||||||
null
|
null
|
||||||
|
@ -49,7 +47,7 @@ export class NodeCryptoProvider extends BaseCryptoProvider {
|
||||||
iterations: number
|
iterations: number
|
||||||
): MaybeAsync<Buffer> {
|
): MaybeAsync<Buffer> {
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
nodeCrypto.pbkdf2(
|
pbkdf2(
|
||||||
password,
|
password,
|
||||||
salt,
|
salt,
|
||||||
iterations,
|
iterations,
|
||||||
|
@ -62,18 +60,18 @@ export class NodeCryptoProvider extends BaseCryptoProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1(data: Buffer): Buffer {
|
sha1(data: Buffer): Buffer {
|
||||||
return nodeCrypto.createHash('sha1').update(data).digest()
|
return createHash('sha1').update(data).digest()
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256(data: Buffer): Buffer {
|
sha256(data: Buffer): Buffer {
|
||||||
return nodeCrypto.createHash('sha256').update(data).digest()
|
return createHash('sha256').update(data).digest()
|
||||||
}
|
}
|
||||||
|
|
||||||
createMd5(): IHashMethod {
|
createMd5(): IHashMethod {
|
||||||
return nodeCrypto.createHash('md5')
|
return createHash('md5') as any
|
||||||
}
|
}
|
||||||
|
|
||||||
hmacSha256(data: Buffer, key: Buffer): MaybeAsync<Buffer> {
|
hmacSha256(data: Buffer, key: Buffer): MaybeAsync<Buffer> {
|
||||||
return nodeCrypto.createHmac('sha256', key).update(data).digest()
|
return createHmac('sha256', key).update(data).digest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
packages/core/src/utils/platform/crypto.ts
Normal file
8
packages/core/src/utils/platform/crypto.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { NodeCryptoProvider } from '../crypto'
|
||||||
|
import { randomBytes } from 'crypto'
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const _defaultCryptoProviderFactory = () => new NodeCryptoProvider()
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const _randomBytes = randomBytes
|
12
packages/core/src/utils/platform/crypto.web.ts
Normal file
12
packages/core/src/utils/platform/crypto.web.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { ForgeCryptoProvider } from '../crypto'
|
||||||
|
import { typedArrayToBuffer } from '../buffer-utils'
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const _defaultCryptoProviderFactory = () => new ForgeCryptoProvider()
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export function _randomBytes(size: number): Buffer {
|
||||||
|
const ret = new Uint8Array(size)
|
||||||
|
crypto.getRandomValues(ret)
|
||||||
|
return typedArrayToBuffer(ret)
|
||||||
|
}
|
4
packages/core/src/utils/platform/transport.ts
Normal file
4
packages/core/src/utils/platform/transport.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { TcpTransport } from '../../network'
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const _defaultTransportFactory = () => new TcpTransport()
|
13
packages/core/src/utils/platform/transport.web.ts
Normal file
13
packages/core/src/utils/platform/transport.web.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { WebSocketTransport } from '../../network'
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const _defaultTransportFactory =
|
||||||
|
typeof WebSocket === 'undefined'
|
||||||
|
// if no websocket, throw an error i guess ¯\_(ツ)_/¯
|
||||||
|
// (user can still implement something on their own)
|
||||||
|
? () => {
|
||||||
|
throw new Error(
|
||||||
|
'Neither TCP nor WebSocket are available. Please pass a Transport factory explicitly'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: () => new WebSocketTransport()
|
Loading…
Reference in a new issue