├── .gitignore ├── bin └── cli.js ├── index.js ├── package.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var minimist = require('minimist') 4 | var http = require('http') 5 | var hyperHttp = require('hyperdrive-http') 6 | var mirror = require('..') 7 | 8 | var argv = minimist(process.argv.slice(2), { 9 | boolean: ['webrtc', 'sparse', 'temp'], 10 | alias: { 11 | webrtc: 'w', 12 | temp: 'm' 13 | }, 14 | default: { 15 | webrtc: false, 16 | sparse: false, 17 | temp: false 18 | } 19 | }) 20 | 21 | argv.link = argv._[0] 22 | 23 | if (!argv.link) { 24 | console.error('Link required') 25 | process.exit(1) 26 | } 27 | 28 | process.title = 'hypermirror' 29 | 30 | // set debug before requiring other modules 31 | if (argv.debug) { 32 | var debugArgs = argv.debug 33 | if (typeof argv.debug === 'boolean') debugArgs = '*' // default 34 | process.env.DEBUG = debugArgs 35 | } 36 | var debug = require('debug')('hypermirror') // require this after setting process.env.DEBUG 37 | debug('options', argv) 38 | 39 | mirror(argv.link, argv, function (err, archive) { 40 | if (err) return console.error(err) 41 | archive.readFile('dat.json', 'utf8', (err, data) => { 42 | if (err) return console.error(err) 43 | debug('dat.json:', data) 44 | }) 45 | console.log('mirroring archive:\n', 'dat://' + archive.key.toString('hex')) 46 | 47 | var server = http.createServer().listen(() => { 48 | console.log(`http archive at: http://localhost:${server.address().port}`) 49 | }) 50 | server.on('request', hyperHttp(archive)) 51 | }) 52 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const hyperdrive = require('hyperdrive') 2 | const swarm = require('hyperdiscovery') 3 | const signalhub = require('signalhub') 4 | const WebrtcSwarm = require('webrtc-swarm') 5 | const pump = require('pump') 6 | const getDatKey = require('dat-link-resolve') 7 | const debug = require('debug')('hypermirror') 8 | 9 | module.exports = mirror 10 | 11 | function mirror (link, opts, cb) { 12 | if (!cb) return mirror(link, {}, opts) 13 | if (!opts) opts = {} 14 | 15 | const db = opts.temp ? require('random-access-memory') : './hypermirror-data' 16 | 17 | getDatKey(link, (err, key) => { 18 | if (err) return cb(err) 19 | getArchive(key, cb) 20 | }) 21 | 22 | function getArchive (key, cb) { 23 | const archive = hyperdrive(db, key, { sparse: opts.sparse }) 24 | archive.on('ready', () => { 25 | if (opts.webrtc) { 26 | webRtcSwarm() 27 | swarm(archive) 28 | } else { 29 | swarm(archive) 30 | } 31 | 32 | if (archive.content) return done() 33 | archive.metadata.get(0, () => { 34 | done() 35 | }) 36 | }) 37 | 38 | function done () { 39 | // why only work if webrtc connects fist? 40 | archive.content.get(0, () => { 41 | cb(null, archive) 42 | }) 43 | } 44 | 45 | function webRtcSwarm () { 46 | const swarmKey = archive.discoveryKey.toString('hex').slice(40) 47 | const webSwarm = new WebrtcSwarm(signalhub(swarmKey, ['https://signalhub-jccqtwhdwc.now.sh/', 'http://gateway.mauve.moe:3300']), { 48 | wrtc: require('wrtc') 49 | }) 50 | 51 | webSwarm.on('peer', function (conn, info) { 52 | debug('Webrtc peer', info) 53 | pump(conn, archive.replicate({ live: true }), conn) 54 | }) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hypermirror", 3 | "version": "2.1.0", 4 | "description": "mirror hypercore and hyperdrive feeds", 5 | "main": "index.js", 6 | "bin": { 7 | "hypermirror": "bin/cli.js" 8 | }, 9 | "scripts": { 10 | "test": "standard" 11 | }, 12 | "author": "Joe Hand (http://joeahand.com/)", 13 | "license": "MIT", 14 | "dependencies": { 15 | "dat-link-resolve": "^2.3.0", 16 | "debug": "^4.1.1", 17 | "hyperdiscovery": "^8.0.0", 18 | "hyperdrive": "^9.14.2", 19 | "hyperdrive-http": "^4.4.0", 20 | "minimist": "^1.2.0", 21 | "pump": "^3.0.0", 22 | "random-access-memory": "^3.1.1", 23 | "signalhub": "^4.9.0", 24 | "webrtc-swarm": "^2.9.0", 25 | "wrtc": "^0.3.5" 26 | }, 27 | "devDependencies": {}, 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/joehand/hypermirror.git" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/joehand/hypermirror/issues" 34 | }, 35 | "homepage": "https://github.com/joehand/hypermirror#readme" 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # HyperMirror 2 | 3 | Mirrors hyperdrives locally with support for: 4 | 5 | * **WebRTC** - Allowing a node service to act as a gateway between Dat's p2p network and Web-based clients. 6 | * **http** - View files locally via http server, especially useful in sparse mode. 7 | 8 | WebRTC, Nice for testing! 9 | 10 | ## Install 11 | 12 | ``` 13 | npm install -g hypermirror 14 | ``` 15 | 16 | ## Usage 17 | 18 | `hypermirror ` 19 | 20 | ### Options 21 | 22 | * `--webrtc` to mirror a Dat across Dat CLI and dat.land. 23 | * `--sparse` to keep dat sparse, otherwise all data is downloaded. 24 | * `--temp` or `-m` to keep hyperdrives in memory, otherwise they are written to `/hypermirror-data` 25 | 26 | Use `DEBUG=hypermirror` to view debug information. 27 | 28 | ## API 29 | 30 | ### `mirror(link, [opts], [cb])` 31 | 32 | cb is called with `cb(err, feed)` where `feed` is either the hypercore feed or the hyperdrive archive. 33 | 34 | See CLI for example usage. 35 | 36 | Options can include: 37 | 38 | ```js 39 | { 40 | temp: false, // keep in memory 41 | webrtc: false, // use wrtc to share via webrtc 42 | sparse: false // only download data as requested 43 | } 44 | ``` 45 | 46 | ## License 47 | 48 | MIT 49 | --------------------------------------------------------------------------------