mirror of https://github.com/mthenw/frontail.git
prepare to be used as a standalone binary package with pkg
parent
87bfcff493
commit
6cf8a3391f
|
@ -1,2 +1,2 @@
|
|||
lib/web/assets/tinycon.min.js
|
||||
lib/web/assets/ansi_up.js
|
||||
web/assets/tinycon.min.js
|
||||
web/assets/ansi_up.js
|
|
@ -7,4 +7,4 @@
|
|||
"env": {
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
node_modules
|
||||
test/fixtures/*.pem
|
||||
npm-debug.log
|
||||
dist
|
20
index.js
20
index.js
|
@ -10,6 +10,8 @@ const connectBuilder = require('./lib/connect_builder');
|
|||
const program = require('./lib/options_parser');
|
||||
const serverBuilder = require('./lib/server_builder');
|
||||
const daemonize = require('./lib/daemonize');
|
||||
const fs = require('fs');
|
||||
const untildify = require('untildify');
|
||||
|
||||
/**
|
||||
* Parse args
|
||||
|
@ -45,8 +47,8 @@ if (program.daemonize) {
|
|||
appBuilder.authorize(program.user, program.password);
|
||||
}
|
||||
appBuilder
|
||||
.static(path.join(__dirname, 'lib/web/assets'))
|
||||
.index(path.join(__dirname, 'lib/web/index.html'), files, filesNamespace, program.theme);
|
||||
.static(path.join(__dirname, 'web/assets'))
|
||||
.index(path.join(__dirname, 'web/index.html'), files, filesNamespace, program.theme);
|
||||
|
||||
const builder = serverBuilder();
|
||||
if (doSecure) {
|
||||
|
@ -90,7 +92,19 @@ if (program.daemonize) {
|
|||
*/
|
||||
let highlightConfig;
|
||||
if (program.uiHighlight) {
|
||||
highlightConfig = require(path.resolve(__dirname, program.uiHighlightPreset)); // eslint-disable-line
|
||||
let presetPath;
|
||||
|
||||
if (!program.uiHighlightPreset) {
|
||||
presetPath = path.join(__dirname, 'preset/default.json');
|
||||
} else {
|
||||
presetPath = path.resolve(untildify(program.uiHighlightPreset));
|
||||
}
|
||||
|
||||
if (fs.existsSync(presetPath)) {
|
||||
highlightConfig = JSON.parse(fs.readFileSync(presetPath));
|
||||
} else {
|
||||
throw new Error(`Preset file ${presetPath} doesn't exists`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,10 +27,12 @@ ConnectBuilder.prototype.index = function index(path, files, filesNamespace, the
|
|||
res.writeHead(200, {
|
||||
'Content-Type': 'text/html',
|
||||
});
|
||||
res.end(data.toString('utf-8')
|
||||
.replace(/__TITLE__/g, files)
|
||||
.replace(/__THEME__/g, theme)
|
||||
.replace(/__NAMESPACE__/g, filesNamespace),
|
||||
res.end(
|
||||
data
|
||||
.toString('utf-8')
|
||||
.replace(/__TITLE__/g, files)
|
||||
.replace(/__THEME__/g, theme)
|
||||
.replace(/__NAMESPACE__/g, filesNamespace),
|
||||
'utf-8'
|
||||
);
|
||||
});
|
||||
|
@ -41,10 +43,12 @@ ConnectBuilder.prototype.index = function index(path, files, filesNamespace, the
|
|||
|
||||
ConnectBuilder.prototype.session = function session(secret, key) {
|
||||
this.app.use(connect.cookieParser());
|
||||
this.app.use(connect.session({
|
||||
secret,
|
||||
key,
|
||||
}));
|
||||
this.app.use(
|
||||
connect.session({
|
||||
secret,
|
||||
key,
|
||||
})
|
||||
);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,17 +22,11 @@ module.exports = (script, params, opts) => {
|
|||
];
|
||||
|
||||
if (options.doAuthorization) {
|
||||
args.push(
|
||||
'-U', params.user,
|
||||
'-P', params.password
|
||||
);
|
||||
args.push('-U', params.user, '-P', params.password);
|
||||
}
|
||||
|
||||
if (options.doSecure) {
|
||||
args.push(
|
||||
'-k', params.key,
|
||||
'-c', params.certificate
|
||||
);
|
||||
args.push('-k', params.key, '-c', params.certificate);
|
||||
}
|
||||
|
||||
if (params.uiHideTopbar) {
|
||||
|
@ -44,7 +38,11 @@ module.exports = (script, params, opts) => {
|
|||
}
|
||||
|
||||
if (params.uiHighlight) {
|
||||
args.push('--ui-highlight', '--ui-highlight-preset', params.uiHighlightPreset);
|
||||
args.push('--ui-highlight');
|
||||
}
|
||||
|
||||
if (params.uiHighlightPreset) {
|
||||
args.push('--ui-highlight-preset', params.uiHighlightPreset);
|
||||
}
|
||||
|
||||
args = args.concat(params.args);
|
||||
|
|
|
@ -9,22 +9,51 @@ program
|
|||
.option('-l, --lines <lines>', 'number on lines stored in browser, default 2000', Number, 2000)
|
||||
.option('-t, --theme <theme>', 'name of the theme (default, dark)', String, 'default')
|
||||
.option('-d, --daemonize', 'run as daemon')
|
||||
.option('-U, --user <username>', 'Basic Authentication username, option works only along with -P option',
|
||||
String, false)
|
||||
.option('-P, --password <password>', 'Basic Authentication password, option works only along with -U option',
|
||||
String, false)
|
||||
.option('-k, --key <key.pem>', 'Private Key for HTTPS, option works only along with -c option',
|
||||
String, false)
|
||||
.option('-c, --certificate <cert.pem>', 'Certificate for HTTPS, option works only along with -k option',
|
||||
String, false)
|
||||
.option('--pid-path <path>', 'if run as daemon file that will store the process id, default /var/run/frontail.pid',
|
||||
String, '/var/run/frontail.pid')
|
||||
.option('--log-path <path>', 'if run as daemon file that will be used as a log, default /dev/null',
|
||||
String, '/dev/null')
|
||||
.option(
|
||||
'-U, --user <username>',
|
||||
'Basic Authentication username, option works only along with -P option',
|
||||
String,
|
||||
false
|
||||
)
|
||||
.option(
|
||||
'-P, --password <password>',
|
||||
'Basic Authentication password, option works only along with -U option',
|
||||
String,
|
||||
false
|
||||
)
|
||||
.option(
|
||||
'-k, --key <key.pem>',
|
||||
'Private Key for HTTPS, option works only along with -c option',
|
||||
String,
|
||||
false
|
||||
)
|
||||
.option(
|
||||
'-c, --certificate <cert.pem>',
|
||||
'Certificate for HTTPS, option works only along with -k option',
|
||||
String,
|
||||
false
|
||||
)
|
||||
.option(
|
||||
'--pid-path <path>',
|
||||
'if run as daemon file that will store the process id, default /var/run/frontail.pid',
|
||||
String,
|
||||
'/var/run/frontail.pid'
|
||||
)
|
||||
.option(
|
||||
'--log-path <path>',
|
||||
'if run as daemon file that will be used as a log, default /dev/null',
|
||||
String,
|
||||
'/dev/null'
|
||||
)
|
||||
.option('--ui-hide-topbar', 'hide topbar (log file name and search box)')
|
||||
.option('--ui-no-indent', 'don\'t indent log lines')
|
||||
.option('--ui-highlight', 'highlight words or lines if defined string found in logs, default preset')
|
||||
.option('--ui-highlight-preset <path>', 'custom preset for highlighting (see ./preset/default.json)', String,
|
||||
'./preset/default.json');
|
||||
.option('--ui-no-indent', "don't indent log lines")
|
||||
.option(
|
||||
'--ui-highlight',
|
||||
'highlight words or lines if defined string found in logs, default preset'
|
||||
)
|
||||
.option(
|
||||
'--ui-highlight-preset <path>',
|
||||
'custom preset for highlighting (see ./preset/default.json)'
|
||||
);
|
||||
|
||||
module.exports = program;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
|
@ -13,13 +13,14 @@
|
|||
"connect": "2.11.0",
|
||||
"cookie": "0.1.0",
|
||||
"daemon": "github:zipang/daemon.node#48d0977c26fb3a6a44ae99aae3471b9d5a761085",
|
||||
"socket.io": "1.4.8"
|
||||
"socket.io": "1.4.8",
|
||||
"untildify": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^3.6.0",
|
||||
"eslint-config-airbnb-base": "^8.0.0",
|
||||
"eslint-plugin-import": "^1.16.0",
|
||||
"jsdom": "^8.5.0",
|
||||
"jsdom": "^9.12.0",
|
||||
"mocha": "~2.3.2",
|
||||
"should": "~3.3.2",
|
||||
"sinon": "~1.7.3",
|
||||
|
@ -28,13 +29,32 @@
|
|||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "mocha -r should --reporter spec test/*.js"
|
||||
"test": "mocha -r should --reporter spec test/*.js",
|
||||
"pkg": "pkg --out-path=dist ."
|
||||
},
|
||||
"pkg": {
|
||||
"assets": [
|
||||
"preset/*.json",
|
||||
"web/**/*"
|
||||
],
|
||||
"targets": [
|
||||
"node8-alpine-x64",
|
||||
"node8-linux-x64",
|
||||
"node8-macos-x64",
|
||||
"node8-win-x64"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/mthenw/frontail.git"
|
||||
},
|
||||
"keywords": ["tail", "syslog", "realtime", "log", "devops"],
|
||||
"keywords": [
|
||||
"tail",
|
||||
"syslog",
|
||||
"realtime",
|
||||
"log",
|
||||
"devops"
|
||||
],
|
||||
"main": "index",
|
||||
"preferGlobal": true
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"words": {
|
||||
"err": "color: red;"
|
||||
},
|
||||
"lines": {
|
||||
"err": "font-weight: bold;"
|
||||
}
|
||||
"words": {
|
||||
"err": "color: red;"
|
||||
},
|
||||
"lines": {
|
||||
"err": "font-weight: bold;"
|
||||
}
|
||||
}
|
||||
|
|
11
test/app.js
11
test/app.js
|
@ -26,10 +26,11 @@ describe('browser application', () => {
|
|||
|
||||
beforeEach((done) => {
|
||||
io = new EventEmitter();
|
||||
const html = '<title></title><body><div class="topbar"></div>' +
|
||||
const html =
|
||||
'<title></title><body><div class="topbar"></div>' +
|
||||
'<div class="log"></div><input type="test" id="filter"/></body>';
|
||||
const ansiup = fs.readFileSync('./lib/web/assets/ansi_up.js', 'utf-8');
|
||||
const src = fs.readFileSync('./lib/web/assets/app.js', 'utf-8');
|
||||
const ansiup = fs.readFileSync('./web/assets/ansi_up.js', 'utf-8');
|
||||
const src = fs.readFileSync('./web/assets/app.js', 'utf-8');
|
||||
|
||||
jsdom.env({
|
||||
html,
|
||||
|
@ -122,9 +123,7 @@ describe('browser application', () => {
|
|||
io.emit('line', 'line1');
|
||||
|
||||
const line = window.document.querySelector('.line');
|
||||
line.parentNode.innerHTML.should.equal(
|
||||
'<div class="line" style="background: black"><p class="inner-line">line1</p></div>'
|
||||
);
|
||||
line.parentNode.innerHTML.should.equal('<div class="line" style="background: black"><p class="inner-line">line1</p></div>');
|
||||
});
|
||||
|
||||
it('should escape HTML', () => {
|
||||
|
|
|
@ -6,12 +6,18 @@ const path = require('path');
|
|||
|
||||
describe('connectBuilder', () => {
|
||||
it('should build connect app', () => {
|
||||
connectBuilder().build().should.have.property('use');
|
||||
connectBuilder().build().should.have.property('listen');
|
||||
connectBuilder()
|
||||
.build()
|
||||
.should.have.property('use');
|
||||
connectBuilder()
|
||||
.build()
|
||||
.should.have.property('listen');
|
||||
});
|
||||
|
||||
it('should build app requiring authorized user', (done) => {
|
||||
const app = connectBuilder().authorize('user', 'pass').build();
|
||||
const app = connectBuilder()
|
||||
.authorize('user', 'pass')
|
||||
.build();
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
|
@ -20,7 +26,9 @@ describe('connectBuilder', () => {
|
|||
});
|
||||
|
||||
it('should build app allowing user to login', (done) => {
|
||||
const app = connectBuilder().authorize('user', 'pass').build();
|
||||
const app = connectBuilder()
|
||||
.authorize('user', 'pass')
|
||||
.build();
|
||||
app.use((req, res) => {
|
||||
res.end('secret!');
|
||||
});
|
||||
|
@ -32,7 +40,9 @@ describe('connectBuilder', () => {
|
|||
});
|
||||
|
||||
it('should build app that setup session', (done) => {
|
||||
const app = connectBuilder().session('secret', 'sessionkey').build();
|
||||
const app = connectBuilder()
|
||||
.session('secret', 'sessionkey')
|
||||
.build();
|
||||
app.use((req, res) => {
|
||||
res.end();
|
||||
});
|
||||
|
@ -43,7 +53,9 @@ describe('connectBuilder', () => {
|
|||
});
|
||||
|
||||
it('should build app that serve static files', (done) => {
|
||||
const app = connectBuilder().static(path.join(__dirname, 'fixtures')).build();
|
||||
const app = connectBuilder()
|
||||
.static(path.join(__dirname, 'fixtures'))
|
||||
.build();
|
||||
|
||||
request(app)
|
||||
.get('/foo')
|
||||
|
@ -51,7 +63,9 @@ describe('connectBuilder', () => {
|
|||
});
|
||||
|
||||
it('should build app that serve index file', (done) => {
|
||||
const app = connectBuilder().index(path.join(__dirname, 'fixtures/index'), '/testfile').build();
|
||||
const app = connectBuilder()
|
||||
.index(path.join(__dirname, 'fixtures/index'), '/testfile')
|
||||
.build();
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
|
@ -89,7 +103,7 @@ describe('connectBuilder', () => {
|
|||
.expect(
|
||||
'<head><title>/testfile</title><link href="dark.css" rel="stylesheet" type="text/css"/></head>',
|
||||
done
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
it('should build app that sets default theme', (done) => {
|
||||
|
@ -102,6 +116,6 @@ describe('connectBuilder', () => {
|
|||
.expect(
|
||||
'<head><title>/testfile</title><link href="default.css" rel="stylesheet" type="text/css"/></head>',
|
||||
done
|
||||
);
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -129,7 +129,20 @@ describe('daemonize', () => {
|
|||
daemonize('script', optionsParser);
|
||||
|
||||
daemon.daemon.lastCall.args[1].should.containDeep(['--ui-highlight']);
|
||||
daemon.daemon.lastCall.args[1].should.containDeep(['--ui-highlight-preset', './preset/default.json']);
|
||||
});
|
||||
|
||||
it('with highlight preset option', () => {
|
||||
optionsParser.parse([
|
||||
'node',
|
||||
'/path/to/frontail',
|
||||
'--ui-highlight',
|
||||
'--ui-highlight-preset',
|
||||
'test.json',
|
||||
]);
|
||||
|
||||
daemonize('script', optionsParser);
|
||||
|
||||
daemon.daemon.lastCall.args[1].should.containDeep(['--ui-highlight-preset', 'test.json']);
|
||||
});
|
||||
|
||||
it('with file to tail', () => {
|
||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Loading…
Reference in New Issue