rtail 0.2.0 → 2.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +508 -73
  3. package/bin/rtail.js +91 -0
  4. package/package.json +15 -67
  5. package/.jscsrc +0 -28
  6. package/.jshintrc +0 -11
  7. package/.npmignore +0 -4
  8. package/.scss-lint.yml +0 -11
  9. package/cli/lib/webapp.js +0 -53
  10. package/cli/rtail-client.js +0 -156
  11. package/cli/rtail-server.js +0 -144
  12. package/dist/bundle.min.js +0 -18
  13. package/dist/css/bundle.min.css +0 -199
  14. package/dist/images/common/btn-fav-off.svg +0 -16
  15. package/dist/images/common/btn-fav-on.svg +0 -16
  16. package/dist/images/common/favicon-16x16.png +0 -0
  17. package/dist/images/common/favicon-32x32.png +0 -0
  18. package/dist/images/common/favicon-96x96.png +0 -0
  19. package/dist/images/common/icn-filter.svg +0 -16
  20. package/dist/images/common/icn-resume.svg +0 -16
  21. package/dist/images/common/logo-rtail.svg +0 -26
  22. package/dist/images/dark/btn-github.svg +0 -16
  23. package/dist/images/dark/btn-info.svg +0 -20
  24. package/dist/images/dark/btn-json-collapse.svg +0 -16
  25. package/dist/images/dark/btn-json-expand.svg +0 -16
  26. package/dist/images/dark/btn-settings.svg +0 -16
  27. package/dist/images/dark/icn-close-date.svg +0 -16
  28. package/dist/images/dark/icn-font-decrease.svg +0 -19
  29. package/dist/images/dark/icn-font-increase.svg +0 -19
  30. package/dist/images/dark/icn-font-reset.svg +0 -18
  31. package/dist/images/dark/icn-search.svg +0 -16
  32. package/dist/images/dark/icn-sort-asc.svg +0 -18
  33. package/dist/images/dark/icn-sort-desc.svg +0 -18
  34. package/dist/images/dark/icn-theme-dark.svg +0 -18
  35. package/dist/images/dark/icn-theme-light.svg +0 -26
  36. package/dist/images/dark/logo-lukibear.svg +0 -74
  37. package/dist/images/dark/logo-rtail-info.svg +0 -26
  38. package/dist/images/light/btn-github.svg +0 -16
  39. package/dist/images/light/btn-info.svg +0 -20
  40. package/dist/images/light/btn-json-collapse.svg +0 -16
  41. package/dist/images/light/btn-json-expand.svg +0 -16
  42. package/dist/images/light/btn-settings.svg +0 -16
  43. package/dist/images/light/icn-close-date.svg +0 -16
  44. package/dist/images/light/icn-font-decrease.svg +0 -19
  45. package/dist/images/light/icn-font-increase.svg +0 -19
  46. package/dist/images/light/icn-font-reset.svg +0 -18
  47. package/dist/images/light/icn-search.svg +0 -16
  48. package/dist/images/light/icn-sort-asc.svg +0 -18
  49. package/dist/images/light/icn-sort-desc.svg +0 -18
  50. package/dist/images/light/icn-theme-dark.svg +0 -18
  51. package/dist/images/light/icn-theme-light.svg +0 -26
  52. package/dist/images/light/logo-lukibear.svg +0 -74
  53. package/dist/images/light/logo-rtail-info.svg +0 -26
  54. package/dist/index.html +0 -1
  55. package/scripts/npm-publish.sh +0 -21
  56. package/scripts/set-version.sh +0 -7
  57. package/test/rtail-client.test.js +0 -131
  58. package/test/rtail-server.test.js +0 -138
  59. package/test/runner.js +0 -31
  60. package/test/util.js +0 -65
package/bin/rtail.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ /*!
5
+ * The npm entry point: find this machine's binary and become it.
6
+ *
7
+ * rtail is a Go program. npm is one of the ways to get it, because the people
8
+ * who pipe logs into it are often already standing in a project with a
9
+ * package.json — but nothing here implements the client, and this file is the
10
+ * only JavaScript left in the install.
11
+ *
12
+ * ** Why a launcher at all. **
13
+ *
14
+ * The binaries ship as one package per platform (`@rtail/darwin-arm64` and
15
+ * friends), each declaring `os` and `cpu`, listed here as optional
16
+ * dependencies. npm installs the one that matches and silently skips the
17
+ * rest, so a Linux box downloads a Linux binary and nothing else. That is the
18
+ * arrangement esbuild uses, and it is the only one that needs no install-time
19
+ * download: no postinstall script, no curl, nothing that breaks behind a
20
+ * proxy or under `--ignore-scripts`.
21
+ *
22
+ * The cost is this file. A platform package can declare its own `bin`, and
23
+ * for a local install npm would link it — but `npm i -g rtail` links the bins
24
+ * of the named package only, never a transitive dependency's, so a global
25
+ * install would leave no `rtail` on PATH. Hence a launcher in the package the
26
+ * user actually named.
27
+ *
28
+ * Anyone who would rather not have Node in the path at all can take the
29
+ * binary straight from a release tarball, `go install`, or the container.
30
+ */
31
+
32
+ const { spawnSync } = require('node:child_process')
33
+
34
+ // Go and Node spell the same architectures differently.
35
+ const PLATFORMS = {
36
+ 'darwin-arm64': '@rtail/darwin-arm64',
37
+ 'darwin-x64': '@rtail/darwin-x64',
38
+ 'linux-arm64': '@rtail/linux-arm64',
39
+ 'linux-x64': '@rtail/linux-x64',
40
+ 'win32-x64': '@rtail/win32-x64'
41
+ }
42
+
43
+ const key = `${process.platform}-${process.arch}`
44
+ const pkg = PLATFORMS[key]
45
+
46
+ if (!pkg) {
47
+ console.error(
48
+ `rtail: no prebuilt binary for ${key}.\n` +
49
+ 'Build one with `go install github.com/kilianc/rtail/v2/cmd/rtail@latest`,\n' +
50
+ 'or open an issue at https://github.com/kilianc/rtail/issues if this\n' +
51
+ 'platform should be published.'
52
+ )
53
+ process.exit(1)
54
+ }
55
+
56
+ const exe = 'win32' === process.platform ? 'rtail.exe' : 'rtail'
57
+
58
+ let binary
59
+
60
+ try {
61
+ binary = require.resolve(`${pkg}/bin/${exe}`)
62
+ } catch {
63
+ // The optional dependency was skipped — almost always --no-optional, or a
64
+ // lockfile copied from a machine of a different shape.
65
+ console.error(
66
+ `rtail: ${pkg} is not installed.\n` +
67
+ 'It is an optional dependency carrying the binary for this platform.\n' +
68
+ `Reinstall without --no-optional, or \`npm install ${pkg}\` directly.`
69
+ )
70
+ process.exit(1)
71
+ }
72
+
73
+ /*!
74
+ * stdio is inherited, which is the whole point.
75
+ *
76
+ * rtail is a pipe. Its stdin is the producer's stdout and its own stdout is
77
+ * whatever came next in the shell, so the file descriptors are handed over
78
+ * untouched rather than copied through this process — which also means no
79
+ * buffering, no mangling of a partial line, and a SIGINT at the terminal
80
+ * reaching the binary directly.
81
+ */
82
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' })
83
+
84
+ if (result.error) {
85
+ console.error(`rtail: ${result.error.message}`)
86
+ process.exit(1)
87
+ }
88
+
89
+ // A child killed by a signal has a null status; 128 + signal is the shell's
90
+ // convention for reporting that, and exiting 0 would claim it succeeded.
91
+ process.exit(null === result.status ? 1 : result.status)
package/package.json CHANGED
@@ -1,76 +1,24 @@
1
1
  {
2
2
  "name": "rtail",
3
- "version": "0.2.0",
3
+ "version": "2.0.0-rc.2",
4
4
  "description": "Terminal output to the browser in seconds, using UNIX pipes.",
5
- "keywords": [
6
- "tail",
7
- "log",
8
- "logs",
9
- "logio",
10
- "logging",
11
- "udp"
12
- ],
13
- "bin": {
14
- "rtail": "./cli/rtail-client.js",
15
- "rtail-server": "./cli/rtail-server.js"
5
+ "keywords": ["log", "logging", "logio", "logs", "tail", "udp"],
6
+ "bin": { "rtail": "bin/rtail.js" },
7
+ "files": ["bin"],
8
+ "engines": { "node": ">=20" },
9
+ "optionalDependencies": {
10
+ "@rtail/linux-x64": "2.0.0-rc.2",
11
+ "@rtail/linux-arm64": "2.0.0-rc.2",
12
+ "@rtail/darwin-x64": "2.0.0-rc.2",
13
+ "@rtail/darwin-arm64": "2.0.0-rc.2",
14
+ "@rtail/win32-x64": "2.0.0-rc.2"
16
15
  },
17
16
  "repository": {
18
17
  "type": "git",
19
- "url": "git@github.com:kilianc/rtail.git"
20
- },
21
- "dependencies": {
22
- "chrono-node": "^1.0.6",
23
- "debug": "^2.1.0",
24
- "express": "^4.10.0",
25
- "json5": "^0.4.0",
26
- "moniker": "^0.1.2",
27
- "request": "^2.58.0",
28
- "socket.io": "^1.1.0",
29
- "split": "^1.0.0",
30
- "strip-ansi": "^3.0.0",
31
- "through2-map": "^2.0.0",
32
- "update-notifier": "^0.5.0",
33
- "yargs": "^3.14.0"
34
- },
35
- "devDependencies": {
36
- "angular": "^1.3.15",
37
- "angular-animate": "^1.4.0",
38
- "angular-localforage": "^1.2.2",
39
- "angular-moment": "^0.10.1",
40
- "angular-rt-popup": "^1.0.5",
41
- "angular-ui-router": "^0.2.15",
42
- "ansi_up": "^1.2.1",
43
- "autoprefixer-core": "^5.1.11",
44
- "chai": "^3.0.0",
45
- "del": "^1.1.1",
46
- "gulp": "^3.9.0",
47
- "gulp-ejs": "^1.1.0",
48
- "gulp-livereload": "^3.8.0",
49
- "gulp-load-plugins": "^0.10.0",
50
- "gulp-minify-css": "^1.1.1",
51
- "gulp-minify-html": "^1.0.2",
52
- "gulp-ng-annotate": "^1.0.0",
53
- "gulp-postcss": "^5.1.6",
54
- "gulp-sass": "^2.0.1",
55
- "gulp-sourcemaps": "^1.5.2",
56
- "gulp-uglify": "^1.2.0",
57
- "gulp-useref": "^1.1.2",
58
- "gulp-util": "^3.0.4",
59
- "highlight.js": "isagalaev/highlight.js",
60
- "istanbul": "^0.3.17",
61
- "istanbul-harmony": "^0.3.16",
62
- "jquery": "^2.1.4",
63
- "localforage": "^1.2.2",
64
- "mocha": "^2.2.5",
65
- "moment": "^2.10.3",
66
- "node-sass": "^3.1.1",
67
- "run-sequence": "^1.1.0"
68
- },
69
- "scripts": {
70
- "app": "DEBUG=rtail:*,api:* gulp app",
71
- "test": "NODE_ENV=test node --harmony test/runner.js",
72
- "test:watch": "NODE_ENV=test nodemon --harmony test/runner.js"
18
+ "url": "git+https://github.com/kilianc/rtail.git"
73
19
  },
20
+ "homepage": "https://github.com/kilianc/rtail#readme",
21
+ "bugs": "https://github.com/kilianc/rtail/issues",
74
22
  "author": "Kilian Ciuffolo <me@nailik.org>",
75
- "license": "MIT"
23
+ "license": "Apache-2.0"
76
24
  }
package/.jscsrc DELETED
@@ -1,28 +0,0 @@
1
- {
2
- "preset": "airbnb",
3
- "esnext": true,
4
- "verbose": true,
5
- "disallowCapitalizedComments": true,
6
- "disallowMultipleLineBreaks": true,
7
- "disallowMultipleSpaces": true,
8
- "disallowSemicolons": true,
9
- "disallowSpacesInAnonymousFunctionExpression": null,
10
- "disallowSpacesInFunctionExpression": null,
11
- "disallowYodaConditions": null,
12
- "requireCamelCaseOrUpperCaseIdentifiers": null,
13
- "requirePaddingNewLinesAfterUseStrict": true,
14
- "requireSpacesInAnonymousFunctionExpression": {
15
- "beforeOpeningRoundBrace": true,
16
- "beforeOpeningCurlyBrace": true
17
- },
18
- "safeContextKeyword": ["self", "doc", "ctx"],
19
- "validateIndentation": 2,
20
- "plugins": [
21
- "jscs-jsdoc"
22
- ],
23
- "jsDoc": {
24
- "checkAnnotations": "closurecompiler",
25
- "checkTypes": "strictNativeCase",
26
- "enforceExistence": "exceptExports"
27
- }
28
- }
package/.jshintrc DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "asi": true,
3
- "esnext": true,
4
- "expr": true,
5
- "mocha": true,
6
- "node": true,
7
- "noyield": true,
8
- "strict": true,
9
- "unused": true,
10
- "validthis": true
11
- }
package/.npmignore DELETED
@@ -1,4 +0,0 @@
1
- !dist
2
- app
3
- gulpfile.js
4
- wercker.yml
package/.scss-lint.yml DELETED
@@ -1,11 +0,0 @@
1
- linters:
2
- ImportantRule:
3
- enabled: false
4
- Compass::*:
5
- enabled: false
6
- SelectorDepth:
7
- enabled: false
8
- NestingDepth:
9
- enabled: false
10
- PropertyCount:
11
- enabled: false
package/cli/lib/webapp.js DELETED
@@ -1,53 +0,0 @@
1
- /*!
2
- * webapp.js
3
- * Created by Kilian Ciuffolo on Nov 11, 2014
4
- * (c) 2014-2015
5
- */
6
-
7
- 'use strict'
8
-
9
- const debug = require('debug')('rtail:webapp')
10
- const get = require('request').defaults({ encoding: null })
11
-
12
- // serve frontend from s3
13
- module.exports = function webapp(opts) {
14
- let cache = Object.create(null)
15
- let cacheTTL = opts.cacheTTL
16
- let s3 = opts.s3
17
-
18
- /*!
19
- * middleware
20
- */
21
- return function (req, res) {
22
- if (cache[req.path]) {
23
- return serveCache(req, res)
24
- }
25
-
26
- debug('caching %s', req.path)
27
-
28
- get(s3 + req.path, function (err, s3res, body) {
29
- cache[req.path] = {
30
- headers: s3res.headers,
31
- body: body
32
- }
33
-
34
- serveCache(req, res)
35
- })
36
- }
37
-
38
- /*!
39
- * wipes out cache every cachettl ms
40
- */
41
- setInterval(function () {
42
- cache = Object.create(null)
43
- }, cacheTTL)
44
-
45
- /*!
46
- * serves req from cache
47
- */
48
- function serveCache(req, res) {
49
- debug('serving from cache %s', req.path)
50
- res.writeHead(200, cache[req.path].headers)
51
- res.end(cache[req.path].body)
52
- }
53
- }
@@ -1,156 +0,0 @@
1
- #!/bin/sh
2
- ":" //# comment; exec /usr/bin/env node --harmony "$0" "$@"
3
-
4
- /*!
5
- * rtail-client.js
6
- * Created by Kilian Ciuffolo on Oct 26, 2014
7
- * (c) 2014-2015
8
- */
9
-
10
- 'use strict'
11
-
12
- const dgram = require('dgram')
13
- const split = require('split')
14
- const chrono = require('chrono-node')
15
- const JSON5 = require('json5')
16
- const yargs = require('yargs')
17
- const map = require('through2-map')
18
- const stripAnsi = require('strip-ansi')
19
- const moniker_ = require('moniker').choose
20
- const updateNotifier = require('update-notifier')
21
- const pkg = require('../package')
22
-
23
- /*!
24
- * inform the user of updates
25
- */
26
- updateNotifier({
27
- packageName: pkg.name,
28
- packageVersion: pkg.version
29
- }).notify()
30
-
31
- /*!
32
- * parsing argv
33
- */
34
- let argv = yargs
35
- .usage('Usage: cmd | rtail [OPTIONS]')
36
- .example('server | rtail > server.log', 'localhost + file')
37
- .example('server | rtail --id api.domain.com', 'Name the log stream')
38
- .example('server | rtail --host example.com', 'Sends to example.com')
39
- .example('server | rtail --port 43567', 'Uses custom port')
40
- .example('server | rtail --mute', 'No stdout')
41
- .example('server | rtail --no-tty', 'Strips ansi colors')
42
- .example('server | rtail --no-date-parse', 'Disable date parsing/stripping')
43
- .option('host', {
44
- alias: 'h',
45
- type: 'string',
46
- default: '127.0.0.1',
47
- describe: 'The server host'
48
- })
49
- .option('port', {
50
- alias: 'p',
51
- type: 'string',
52
- default: 9999,
53
- describe: 'The server port'
54
- })
55
- .option('id', {
56
- alias: 'name',
57
- type: 'string',
58
- default: function moniker() { return moniker_() } ,
59
- describe: 'The log stream id'
60
- })
61
- .option('mute', {
62
- alias: 'm',
63
- type: 'boolean',
64
- describe: 'Don\'t pipe stdin with stdout'
65
- })
66
- .option('tty', {
67
- type: 'boolean',
68
- default: true,
69
- describe: 'Keeps ansi colors'
70
- })
71
- .option('parse-date', {
72
- type: 'boolean',
73
- default: true,
74
- describe: 'Looks for dates to use as timestamp'
75
- })
76
- .help('help')
77
- .version(pkg.version, 'version')
78
- .alias('version', 'v')
79
- .strict()
80
- .argv
81
-
82
- /*!
83
- * setup pipes
84
- */
85
- if (!argv.mute) {
86
- if (!process.stdout.isTTY || !argv.tty) {
87
- process.stdin
88
- .pipe(map(function (chunk) {
89
- return stripAnsi(chunk.toString('utf8'))
90
- }))
91
- .pipe(process.stdout)
92
- } else {
93
- process.stdin.pipe(process.stdout)
94
- }
95
- }
96
-
97
- /*!
98
- * initialize socket
99
- */
100
- let isClosed = false
101
- let isSending = 0
102
- let socket = dgram.createSocket('udp4')
103
- let baseMessage = { id: argv.id }
104
-
105
- socket.bind(function () {
106
- socket.setBroadcast(true)
107
- })
108
-
109
- /*!
110
- * broadcast lines to browser
111
- */
112
- process.stdin
113
- .pipe(split(null, null, { trailing: false }))
114
- .on('data', function (line) {
115
- let timestamp = null
116
-
117
- try {
118
- // try to JSON parse
119
- line = JSON5.parse(line)
120
- } catch (err) {
121
- // look for timestamps if not an object
122
- timestamp = argv.parseDate ? chrono.parse(line)[0] : null
123
- }
124
-
125
- if (timestamp) {
126
- // escape for regexp and remove from line
127
- timestamp.text = timestamp.text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
128
- line = line.replace(new RegExp(' *[^ ]?' + timestamp.text + '[^ ]? *'), '')
129
- // use timestamp as line timestamp
130
- baseMessage.timestamp = Date.parse(timestamp.start.date())
131
- } else {
132
- baseMessage.timestamp = Date.now()
133
- }
134
-
135
- // update default message
136
- baseMessage.content = line
137
-
138
- // prepare binary message
139
- let buffer = new Buffer(JSON.stringify(baseMessage))
140
-
141
- // set semaphore
142
- isSending ++
143
-
144
- socket.send(buffer, 0, buffer.length, argv.port, argv.host, function () {
145
- isSending --
146
- if (isClosed && !isSending) socket.close()
147
- })
148
- })
149
-
150
- /*!
151
- * drain pipe and exit
152
- */
153
- process.stdin.on('end', function () {
154
- isClosed = true
155
- if (!isSending) socket.close()
156
- })
@@ -1,144 +0,0 @@
1
- #!/bin/sh
2
- ":" //# comment; exec /usr/bin/env node --harmony "$0" "$@"
3
-
4
- /*!
5
- * server.js
6
- * Created by Kilian Ciuffolo on Oct 26, 2014
7
- * (c) 2014-2015
8
- */
9
-
10
- 'use strict'
11
-
12
- const dgram = require('dgram')
13
- const app = require('express')()
14
- const serve = require('express').static
15
- const http = require('http').Server(app)
16
- const io = require('socket.io')()
17
- const yargs = require('yargs')
18
- const debug = require('debug')('rtail:server')
19
- const webapp = require('./lib/webapp')
20
- const updateNotifier = require('update-notifier')
21
- const pkg = require('../package')
22
-
23
- /*!
24
- * inform the user of updates
25
- */
26
- updateNotifier({
27
- packageName: pkg.name,
28
- packageVersion: pkg.version
29
- }).notify()
30
-
31
- /*!
32
- * parsing argv
33
- */
34
- let argv = yargs
35
- .usage('Usage: rtail-server [OPTIONS]')
36
- .example('rtail-server --web-port 8080', 'Use custom HTTP port')
37
- .example('rtail-server --udp-port 8080', 'Use custom UDP port')
38
- .example('rtail-server --web-version stable', 'Always uses latest stable webapp')
39
- .example('rtail-server --web-version unstable', 'Always uses latest develop webapp')
40
- .example('rtail-server --web-version 0.1.3', 'Use webapp v0.1.3')
41
- .option('udp-host', {
42
- alias: 'uh',
43
- default: '127.0.0.1',
44
- describe: 'The listening UDP hostname'
45
- })
46
- .option('udp-port', {
47
- alias: 'up',
48
- default: 9999,
49
- describe: 'The listening UDP port'
50
- })
51
- .option('web-host', {
52
- alias: 'wh',
53
- default: '127.0.0.1',
54
- describe: 'The listening HTTP hostname'
55
- })
56
- .option('web-port', {
57
- alias: 'wp',
58
- default: 8888,
59
- describe: 'The listening HTTP port'
60
- })
61
- .option('web-version', {
62
- type: 'string',
63
- describe: 'Define web app version to serve'
64
- })
65
- .help('help')
66
- .alias('help', 'h')
67
- .version(pkg.version, 'version')
68
- .alias('version', 'v')
69
- .strict()
70
- .argv
71
-
72
- /*!
73
- * UDP sockets setup
74
- */
75
- let streams = {}
76
- let socket = dgram.createSocket('udp4')
77
-
78
- socket.on('message', function (data, remote) {
79
- // try to decode JSON
80
- try { data = JSON.parse(data) }
81
- catch (err) { return debug('invalid data sent') }
82
-
83
- if (!streams[data.id]) {
84
- streams[data.id] = []
85
- io.sockets.emit('streams', Object.keys(streams))
86
- }
87
-
88
- let message = {
89
- timestamp: data.timestamp,
90
- streamid: data.id,
91
- host: remote.address,
92
- port: remote.port,
93
- content: data.content,
94
- type: typeof data.content
95
- }
96
-
97
- // limit backlog to 100 lines
98
- streams[data.id].length >= 100 && streams[data.id].shift()
99
- streams[data.id].push(message)
100
-
101
- debug(JSON.stringify(message))
102
- io.sockets.to(data.id).emit('line', message)
103
- })
104
-
105
- /*!
106
- * socket.io
107
- */
108
- io.on('connection', function (socket) {
109
- socket.emit('streams', Object.keys(streams))
110
- socket.on('select stream', function (stream) {
111
- socket.leave(socket.rooms[0])
112
- if (!stream) return
113
- socket.join(stream)
114
- socket.emit('backlog', streams[stream])
115
- })
116
- })
117
-
118
- /*!
119
- * serve static webapp from S3
120
- */
121
- if (!argv.webVersion) {
122
- app.use(serve(__dirname + '/../dist'))
123
- } else if ('development' === argv.webVersion) {
124
- app.use('/app', serve(__dirname + '/../app'))
125
- app.use('/node_modules', serve(__dirname + '/../node_modules'))
126
- io.path('/app/socket.io')
127
- } else {
128
- app.use(webapp({
129
- s3: 'http://rtail.s3-website-us-east-1.amazonaws.com/' + argv.webVersion,
130
- ttl: 6000 * 60 * 60
131
- }))
132
-
133
- debug('serving webapp from: http://rtail.s3-website-us-east-1.amazonaws.com/%s', argv.webVersion)
134
- }
135
-
136
- /*!
137
- * listen!
138
- */
139
- io.attach(http, { serveClient: false })
140
- socket.bind(argv.udpPort, argv.udpHost)
141
- http.listen(argv.webPort, argv.webHost)
142
-
143
- debug('UDP server listening: %s:%s', argv.udpHost, argv.udpPort)
144
- debug('HTTP server listening: http://%s:%s', argv.webHost, argv.webPort)