UNPKG

hyperdrive-daemon-client

Version:

A client library and CLI tool for interacting with the Hyperdrive daemon.

358 lines (306 loc) 8.73 kB
const grpc = require('@grpc/grpc-js') const datEncoding = require('dat-encoding') const { Profile, HyperdriveOptions, DriveStats, MountStats, CoreStats, FileStats, DownloadProgress, NetworkConfiguration, DriveInfo } = require('./rpc/daemon/common_pb') const { Stat, Mount, DiffEntry } = require('./rpc/daemon/drive_pb.js') const CHUNK_SIZE = 3.9e6 function fromProfile (opts) { if (!opts) return {} return { drive: fromHyperdriveOptions(opts.drive), name: opts.getName() } } function toProfile (opts) { if (!opts) return null const profile = new Profile() profile.setDrive(toHyperdriveOptions(opts.drive)) profile.setName(opts.name) return profile } function fromHyperdriveOptions (opts) { if (!opts) return {} const extracted = { key: opts.getKey() || null, discoveryKey: opts.getDiscoverykey() || null, version: opts.getVersion() || null, hash: opts.getHash() || null, writable: opts.getWritable() || false, seed: opts.getSeed() || false } if (extracted.key) extracted.key = Buffer.from(extracted.key) if (extracted.discoveryKey) extracted.discoveryKey = Buffer.from(extracted.discoveryKey) if (extracted.hash) extracted.hash = Buffer.from(extracted.hash) return extracted } function toHyperdriveOptions (opts) { if (!opts) return null if (opts.key && typeof opts.key === 'string') { opts.key = datEncoding.decode(opts.key) } const hdopts = new HyperdriveOptions() hdopts.setKey(opts.key) hdopts.setDiscoverykey(opts.discoveryKey) hdopts.setVersion(opts.version) hdopts.setHash(opts.hash) hdopts.setWritable(opts.writable) hdopts.setSeed(opts.seed) return hdopts } function fromMount (mount) { if (!mount) return null const key = mount.getKey() const hash = mount.getHash() return { key: key ? Buffer.from(key) : null, hash: hash ? Buffer.from(hash) : null, version: mount.getVersion(), hypercore: mount.getHypercore() } } function toMount (mountOpts) { if (!mountOpts) return null const mnt = new Mount() mnt.setKey(mountOpts.key) mnt.setVersion(mountOpts.version) mnt.setHash(mountOpts.hash) mnt.setHypercore(mountOpts.hypercore) return mnt } function fromStat (stat) { if (!stat) return {} return { mode: stat.getMode(), uid: stat.getUid(), gid: stat.getGid(), size: stat.getSize(), mtime: stat.getMtime(), ctime: stat.getCtime(), linkname: stat.getLinkname(), mount: fromMount(stat.getMount()), metadata: fromMetadata(stat.getMetadataMap()) } } function toStat (statOpts) { if (!statOpts) return null const stat = new Stat() stat.setMode(statOpts.mode) stat.setUid(statOpts.uid) stat.setGid(statOpts.gid) stat.setSize(statOpts.size) stat.setMtime(statOpts.mtime ? statOpts.mtime.getTime() : null) stat.setCtime(statOpts.ctime ? statOpts.ctime.getTime() : null) stat.setLinkname(statOpts.linkname) stat.setMount(toMount(statOpts.mount)) if (statOpts.metadata) { setMetadata(stat.getMetadataMap(), statOpts.metadata) } return stat } function setMetadata (map, metadataObj) { if (!map || !metadataObj) return null for (let key of Object.keys(metadataObj)) { if (metadataObj[key]) { map.set(key, metadataObj[key]) } } } function fromMetadata (map) { const metadata = {} if (!map || !map.getLength()) return metadata map.forEach((value, key) => { metadata[key] = Buffer.from(value) }) return metadata } function fromDriveStats (driveStats) { if (!driveStats) return null return driveStats.getStatsList().map(st => getMountStats(st)) function getMountStats (mountStats) { return { path: mountStats.getPath(), metadata: getCoreStats(mountStats.getMetadata()), content: getCoreStats(mountStats.getContent()) } } function getCoreStats (coreStats) { if (!coreStats) return {} return { key: Buffer.from(coreStats.getKey()), peers: coreStats.getPeers(), uploadedBytes: coreStats.getUploadedbytes(), downloadedBytes: coreStats.getDownloadedbytes(), uploadedBytesCumulative: coreStats.getUploadedbytescumulative(), downloadedBytesCumulative: coreStats.getDownloadedbytescumulative(), totalBlocks: coreStats.getTotalblocks(), downloadedBlocks: coreStats.getDownloadedblocks() } } } function toDriveStats (stats) { if (!stats) return null const driveStats = new DriveStats() const mountStatsList = [] for (const ms of stats) { const mountStats = new MountStats() mountStats.setPath(ms.path) const metadataStats = new CoreStats() setCoreStats(metadataStats, ms.metadata) mountStats.setMetadata(metadataStats) if (ms.content) { const contentStats = new CoreStats() setCoreStats(contentStats, ms.content) mountStats.setContent(contentStats) } mountStatsList.push(mountStats) } driveStats.setStatsList(mountStatsList) return driveStats function setCoreStats (coreStats, stats) { coreStats.setKey(stats.key) coreStats.setPeers(stats.peerCount) coreStats.setUploadedbytes(stats.uploadedBytes) coreStats.setDownloadedbytes(stats.downloadedBytes) coreStats.setUploadedbytescumulative(stats.uploadedBytesCumulative) coreStats.setDownloadedbytescumulative(stats.downloadedBytesCumulative) coreStats.setTotalblocks(stats.totalBlocks) coreStats.setDownloadedblocks(stats.downloadedBlocks) } } function fromDiffEntry (diffEntry) { if (!diffEntry) return {} const diff = {} const mnt = diffEntry.getMount() const stat = diffEntry.getStat() if (mnt) diff.mount = fromMount(mnt) if (stat) diff.stat = fromStat(stat) return diff } function toDiffEntry (rawEntry) { const diffEntry = new DiffEntry() if (rawEntry.stat) { diffEntry.setStat(toStat(rawEntry.stat)) } if (rawEntry.mount) { diffEntry.setMount(toMount(rawEntry.mount)) } return diffEntry } function toDownloadProgress (stats) { const p = new DownloadProgress() p.setTotalbytes(stats.totalBytes) p.setDownloadedbytes(stats.downloadedBytes) p.setTotalblocks(stats.totalBlocks) p.setDownloadedblocks(stats.downloadedBlocks) return p } function fromDownloadProgress (rsp) { return { totalBytes: rsp.getTotalbytes(), totalBlocks: rsp.getTotalblocks(), downloadedBytes: rsp.getDownloadedbytes(), downloadedBlocks: rsp.getDownloadedblocks() } } function setFileStats (map, statsObj) { if (!map || !statsObj) return null for (let [path, stats] of statsObj) { map.set(path, toFileStats(stats)) } function toFileStats (stats) { const s = new FileStats() s.setSize(stats.size) s.setBlocks(stats.blocks) s.setDownloadedbytes(stats.downloadedBytes) s.setDownloadedblocks(stats.downloadedBlocks) return s } } function fromFileStats (map) { const stats = new Map() if (!map || !map.getLength()) return stats map.forEach((value, key) => { stats.set(key, fromFileStat(value)) }) return stats function fromFileStat (stat) { return { size: stat.getSize(), blocks: stat.getBlocks(), downloadedBytes: stat.getDownloadedbytes(), downloadedBlocks: stat.getDownloadedblocks() } } } function toNetworkConfiguration (config) { const networkConfig = new NetworkConfiguration() networkConfig.setAnnounce(config.announce) networkConfig.setLookup(config.lookup) networkConfig.setRemember(config.remember) networkConfig.setKey(config.key) return networkConfig } function fromNetworkConfiguration (networkConfig) { if (!networkConfig) return {} return { lookup: networkConfig.getLookup(), announce: networkConfig.getAnnounce(), remember: networkConfig.getRemember(), key: Buffer.from(networkConfig.getKey()) } } function toChunks (content) { const chunks = [] for (let i = 0; i * CHUNK_SIZE < content.length; i++) { const offset = i * CHUNK_SIZE const len = Math.min(CHUNK_SIZE, content.length - offset) const chunk = Buffer.allocUnsafe(len) content.copy(chunk, 0, offset, offset + len) chunks.push(chunk) } return chunks } function toRPCMetadata (obj) { const metadata = new grpc.Metadata() for (let key of Object.getOwnPropertyNames(obj)) { metadata.set(key, obj[key]) } return metadata } module.exports = { fromProfile, toProfile, fromHyperdriveOptions, toHyperdriveOptions, fromStat, toStat, fromMount, toMount, fromDriveStats, toDriveStats, fromDiffEntry, toDiffEntry, fromDownloadProgress, toDownloadProgress, fromFileStats, setFileStats, toChunks, setMetadata, fromMetadata, toNetworkConfiguration, fromNetworkConfiguration, toRPCMetadata }