2018-06-28 10:06:25 +02:00
|
|
|
'use strict'
|
|
|
|
|
2019-02-21 16:07:35 +00:00
|
|
|
const { struct, superstruct } = require('superstruct')
|
|
|
|
const kind = require('kind-of')
|
|
|
|
const { optional, list } = struct
|
2018-06-28 10:06:25 +02:00
|
|
|
|
2019-02-21 16:07:35 +00:00
|
|
|
const transports = ['tcp', 'utp', 'webrtcstar', 'webrtcdirect', 'websockets', 'websocketstar']
|
|
|
|
// Define custom types
|
|
|
|
const s = superstruct({
|
|
|
|
types: {
|
|
|
|
tcp: v => kind(v) === 'tcp',
|
|
|
|
utp: v => kind(v) === 'utp',
|
|
|
|
webrtcstar: v => kind(v) === 'webrtcstar',
|
|
|
|
webrtcdirect: v => kind(v) === 'webrtcdirect',
|
|
|
|
websockets: v => kind(v) === 'websockets',
|
|
|
|
websocketstar: v => kind(v) === 'websocketstar',
|
|
|
|
transport: value => {
|
|
|
|
const [error] = list([s.union([ ...transports, 'function' ])]).validate(value)
|
|
|
|
if (error) return error.message
|
2018-06-28 16:06:42 +01:00
|
|
|
|
2019-02-21 16:07:35 +00:00
|
|
|
return value.length > 0
|
|
|
|
? true
|
|
|
|
: 'You need to provide at least one transport.'
|
|
|
|
}
|
|
|
|
}
|
2018-06-28 10:06:25 +02:00
|
|
|
})
|
|
|
|
|
2019-02-21 16:07:35 +00:00
|
|
|
const optionsSchema = s(
|
|
|
|
{
|
|
|
|
connectionManager: 'object?',
|
|
|
|
datastore: 'object?',
|
|
|
|
peerInfo: 'object',
|
|
|
|
peerBook: 'object?',
|
|
|
|
modules: s({
|
|
|
|
connEncryption: optional(list([s('object|function')])),
|
|
|
|
// this is hacky to simulate optional because interface doesnt work correctly with it
|
|
|
|
// change to optional when fixed upstream
|
|
|
|
connProtector: s.union(['undefined', s.interface({ protect: 'function' })]),
|
|
|
|
contentRouting: optional(list(['object'])),
|
|
|
|
dht: optional(s('null|function|object')),
|
|
|
|
peerDiscovery: optional(list([s('object|function')])),
|
|
|
|
peerRouting: optional(list(['object'])),
|
|
|
|
streamMuxer: optional(list([s('object|function')])),
|
|
|
|
transport: 'transport'
|
|
|
|
}),
|
|
|
|
config: s({
|
|
|
|
peerDiscovery: 'object?',
|
|
|
|
relay: s({
|
|
|
|
enabled: 'boolean',
|
|
|
|
hop: optional(s({
|
|
|
|
enabled: 'boolean',
|
|
|
|
active: 'boolean'
|
|
|
|
},
|
|
|
|
{ enabled: false, active: false }))
|
|
|
|
}, { enabled: true, hop: {} }),
|
|
|
|
dht: s({
|
|
|
|
kBucketSize: 'number',
|
|
|
|
enabled: 'boolean?',
|
|
|
|
randomWalk: optional(s({
|
|
|
|
enabled: 'boolean?',
|
|
|
|
queriesPerPeriod: 'number?',
|
|
|
|
interval: 'number?',
|
|
|
|
timeout: 'number?'
|
|
|
|
}, { enabled: true, queriesPerPeriod: 1, interval: 30000, timeout: 10000 })),
|
|
|
|
validators: 'object?',
|
|
|
|
selectors: 'object?'
|
|
|
|
}, { enabled: true, kBucketSize: 20, enabledDiscovery: true }),
|
|
|
|
EXPERIMENTAL: s({
|
|
|
|
pubsub: 'boolean'
|
|
|
|
}, { pubsub: false })
|
|
|
|
}, { relay: {}, dht: {}, EXPERIMENTAL: {} })
|
|
|
|
},
|
|
|
|
{ config: {}, modules: {} }
|
|
|
|
)
|
|
|
|
|
|
|
|
module.exports.validate = (opts) => {
|
|
|
|
const [error, options] = optionsSchema.validate(opts)
|
2018-06-28 10:06:25 +02:00
|
|
|
|
2019-02-21 16:07:35 +00:00
|
|
|
// Improve errors throwed, reduce stack by throwing here and add reason to the message
|
|
|
|
if (error) {
|
|
|
|
throw new Error(`${error.message}${error.reason ? ' - ' + error.reason : ''}`)
|
|
|
|
} else {
|
|
|
|
// Throw when dht is enabled but no dht module provided
|
|
|
|
if (options.config.dht.enabled) {
|
|
|
|
s('function|object')(options.modules.dht)
|
|
|
|
}
|
2018-06-28 10:06:25 +02:00
|
|
|
}
|
|
|
|
|
2018-06-28 16:06:42 +01:00
|
|
|
return options
|
2018-06-28 10:06:25 +02:00
|
|
|
}
|