secure-scuttlebot classic
at main 9.5 kB view raw
1#! /usr/bin/env node 2 3process.env.CHLORIDE_JS = process.env.CHLORIDE_JS || '1' 4 5var fs = require('fs') 6var path = require('path') 7var pull = require('pull-stream') 8var toPull = require('stream-to-pull-stream') 9var File = require('pull-file') 10var spawn = require('cross-spawn') 11var explain = require('explain-error') 12var minimist = require('minimist') 13var muxrpcli = require('muxrpcli') 14var cmdAliases = require('./lib/cli-cmd-aliases') 15var ProgressBar = require('./lib/progress') 16var cliHelp = require('./lib/cli-help') 17var homeDir = require('os-homedir') 18var packageJson = require('./package.json') 19 20//get config as cli options after --, options before that are 21//options to the command. 22var argv = process.argv.slice(2) 23var i = argv.indexOf('--') 24var conf = i === -1 ? [] : argv.slice(i+1) 25argv = i === -1 ? argv : argv.slice(0, i) 26 27var overrides = minimist(conf) 28var envAppName = process.env.ssb_appname 29var appName = envAppName || overrides.appname || overrides.ssb_appname || 'ssb' 30var baseHome = homeDir() || 'browser' 31var basePath = overrides.path || path.join(baseHome, '.' + appName) 32var manifestForHelp = {} 33var manifestPathForHelp = path.join(basePath, 'manifest.json') 34if (fs.existsSync(manifestPathForHelp)) { 35 try { 36 manifestForHelp = JSON.parse(fs.readFileSync(manifestPathForHelp)) 37 } catch (err) { 38 manifestForHelp = {} 39 } 40} 41var helpCatalog = cliHelp.createCatalog(manifestForHelp) 42 43var helpFlags = ['--help', '-h'] 44 45function printCliHelp () { 46 var name = packageJson.name || 'ssb-server' 47 console.log(name + ' ' + packageJson.version) 48 console.log('Usage:') 49 console.log(' ' + name + ' start [--verbose]') 50 console.log(' ' + name + ' <rpc.command> [arguments]') 51 console.log(' ' + name + ' help [command]') 52 console.log('') 53 console.log('Options:') 54 console.log(' --help, -h show this message') 55 console.log(' --verbose show verbose RPC errors') 56 console.log(' -- <key>=<value> pass overrides to ssb-config') 57 console.log('') 58 console.log('Top-level commands (request detailed help for any of them):') 59 var topLevelCommands = helpCatalog.names.filter(function (name) { 60 return name.indexOf('.') === -1 61 }) 62 var preview = topLevelCommands.slice(0, 12) 63 console.log(' ' + preview.join(', ')) 64 if (topLevelCommands.length > preview.length) { 65 console.log(' ...and ' + (topLevelCommands.length - preview.length) + ' more. Use `' + name + ' help <command>` to see specifics.') 66 } else { 67 console.log(' (Call `' + name + ' help <command>` for the detailed universe of commands.)') 68 } 69 console.log(' Call `' + name + ' list-commands` to dump every command name.') 70 console.log('') 71 console.log('Examples:') 72 console.log(' ' + name + ' start') 73 console.log(' ' + name + ' friends.hops alice') 74 console.log(' ' + name + ' start -- --port 8008') 75 console.log('') 76 console.log('Run `' + name + ' help <command>` for more detail on a specific command.') 77} 78 79function printCommandHelp (requestedCommand) { 80 var resolved = requestedCommand 81 var entry = helpCatalog.get(resolved) 82 if (!entry && cmdAliases[resolved]) { 83 resolved = cmdAliases[resolved] 84 entry = helpCatalog.get(resolved) 85 } 86 87 if (!entry) { 88 console.log('No help data is currently available for `' + requestedCommand + '`.') 89 console.log('Start the server to generate ' + manifestPathForHelp + ' and re-run `' + packageJson.name + ' help ' + requestedCommand + '`.') 90 return 91 } 92 93 console.log('Help for `' + resolved + '`' + (resolved !== requestedCommand ? ' (matched from alias ' + requestedCommand + ')' : '') + ':') 94 if (entry.description) 95 console.log(' ' + entry.description) 96 if (entry.type) 97 console.log('Type: ' + entry.type) 98 var argNames = Object.keys(entry.args || {}) 99 if (argNames.length) { 100 console.log('Arguments:') 101 argNames.forEach(function (argName) { 102 var arg = entry.args[argName] || {} 103 var type = arg.type || 'value' 104 var desc = arg.description || '' 105 console.log(' --' + argName + ' <' + type + '>' + (desc ? ' - ' + desc : '')) 106 }) 107 } 108 console.log('Example: ' + entry.example) 109} 110 111function printCommandList () { 112 console.log('All available commands:') 113 helpCatalog.names.forEach(function (name) { 114 console.log(' ' + name) 115 }) 116} 117 118if (argv[0] === 'help') { 119 if (argv[1]) 120 printCommandHelp(argv[1]) 121 else 122 printCliHelp() 123 process.exit(0) 124} 125 126if (argv[0] === 'list-commands') { 127 printCommandList() 128 process.exit(0) 129} 130 131if (argv.length === 0 || helpFlags.indexOf(argv[0]) !== -1) { 132 printCliHelp() 133 process.exit(0) 134} 135 136var Config = require('ssb-config/inject') 137var config = Config(process.env.ssb_appname, overrides) 138 139if (config.ws !== false) { 140 if (!config.ws || typeof config.ws !== 'object') config.ws = {} 141 if (typeof config.ws.port !== 'number') config.ws.port = 8989 142 if (typeof config.ws.host !== 'string') config.ws.host = '127.0.0.1' 143} 144 145if (config.keys.curve === 'k256') 146 throw new Error('k256 curves are no longer supported,'+ 147 'please delete' + path.join(config.path, 'secret')) 148 149var manifestFile = path.join(config.path, 'manifest.json') 150 151if (argv[0] == 'server') { 152 console.log('WARNING-DEPRECATION: `sbot server` has been renamed to `ssb-server start`') 153 argv[0] = 'start' 154} 155 156if (argv[0] == 'start') { 157 console.log(packageJson.name, packageJson.version, config.path, 'logging.level:'+config.logging.level) 158 console.log('my key ID:', config.keys.public) 159 160 // special start command: 161 // import ssbServer and start the server 162 163 var createSsbServer = require('./') 164 .use(require('ssb-private1')) 165 .use(require('ssb-onion')) 166 .use(require('ssb-unix-socket')) 167 .use(require('ssb-no-auth')) 168 .use(require('ssb-plugins')) 169 .use(require('ssb-master')) 170 .use(require('ssb-gossip')) 171 .use(require('ssb-replicate')) 172 .use(require('./plugins/friends')) 173 .use(require('ssb-blobs')) 174 .use(require('./plugins/invite')) 175 .use(require('./plugins/decent-ui')) 176 .use(require('ssb-local')) 177 .use(require('ssb-logging')) 178 .use(require('ssb-query')) 179 .use(require('ssb-links')) 180 .use(require('ssb-ws')) 181 .use(require('./lib/frontend')) 182 .use(require('ssb-ebt')) 183 .use(require('ssb-ooo')) 184 // add third-party plugins 185 186 require('ssb-plugins').loadUserPlugins(createSsbServer, config) 187 188 // start server 189 var server = createSsbServer(config) 190 191 // write RPC manifest to ~/.ssb/manifest.json 192 fs.writeFileSync(manifestFile, JSON.stringify(server.getManifest(), null, 2)) 193 194 if(process.stdout.isTTY && (config.logging.level != 'info')) 195 ProgressBar(server.progress) 196} else { 197 // normal command: 198 // create a client connection to the server 199 200 // read manifest.json 201 var manifest 202 try { 203 manifest = JSON.parse(fs.readFileSync(manifestFile)) 204 } catch (err) { 205 throw explain(err, 206 'no manifest file' 207 + '- should be generated first time server is run' 208 ) 209 } 210 211 var opts = { 212 manifest: manifest, 213 port: config.port, 214 host: config.host || 'localhost', 215 caps: config.caps, 216 key: config.key || config.keys.id 217 } 218 219 var Client = require('ssb-client') 220 221 // connect 222 Client(config.keys, opts, function (err, rpc) { 223 if(err) { 224 if (/could not connect/.test(err.message)) { 225 console.error('Error: Could not connect to ssb-server ' + opts.host + ':' + opts.port) 226 console.error('Use the "start" command to start it.') 227 console.error('Use --verbose option to see full error') 228 if(config.verbose) throw err 229 process.exit(1) 230 } 231 throw err 232 } 233 234 // add aliases 235 for (var k in cmdAliases) { 236 rpc[k] = rpc[cmdAliases[k]] 237 manifest[k] = manifest[cmdAliases[k]] 238 } 239 240 // add some extra commands 241// manifest.version = 'async' 242 manifest.config = 'sync' 243// rpc.version = function (cb) { 244// console.log(packageJson.version) 245// cb() 246// } 247 rpc.config = function (cb) { 248 console.log(JSON.stringify(config, null, 2)) 249 cb() 250 } 251 252 if (process.argv[2] === 'blobs.add') { 253 var filename = process.argv[3] 254 var source = 255 filename ? File(process.argv[3]) 256 : !process.stdin.isTTY ? toPull.source(process.stdin) 257 : (function () { 258 console.error('USAGE:') 259 console.error(' blobs.add <filename> # add a file') 260 console.error(' source | blobs.add # read from stdin') 261 process.exit(1) 262 })() 263 pull( 264 source, 265 rpc.blobs.add(function (err, hash) { 266 if (err) 267 throw err 268 console.log(hash) 269 process.exit() 270 }) 271 ) 272 return 273 } 274 275 if (process.argv[2] === 'git-ssb') { 276 var gitArgs = process.argv.slice(3) 277 var gitPath 278 try { 279 gitPath = require.resolve('git-ssb/bin/git-ssb') 280 } catch (e) { 281 console.error('Error: vendored git-ssb not found in this ssb-server install.') 282 console.error('Try running: npm install git-ssb --save') 283 process.exit(1) 284 } 285 286 var child = spawn(process.execPath, [gitPath].concat(gitArgs), {stdio: 'inherit'}) 287 288 child.on('exit', function (code, signal) { 289 if (typeof code === 'number') 290 process.exit(code) 291 else if (signal) 292 process.exit(1) 293 else 294 process.exit(0) 295 }) 296 return 297 } 298 299 // run commandline flow 300 muxrpcli(argv, manifest, rpc, config.verbose) 301 }) 302}