Adding plugin for dev

This commit is contained in:
Chris Cowan 2015-05-11 16:35:07 -07:00
parent 1281e1317e
commit f0edc44902
5 changed files with 232 additions and 7 deletions

View file

@ -1,15 +1,16 @@
module.exports = function (grunt) {
grunt.registerTask('kibana_server', function (keepalive) {
var done = this.async();
var config = require('../src/server/config');
config.quiet = !grunt.option('debug') && !grunt.option('verbose');
var server = require('../src/server');
var kibana = require('../');
var devStatics = require('./utils/dev_statics');
var quiet = !grunt.option('debug') && !grunt.option('verbose');
var settings = { 'logging.quiet': quiet };
server.start(function (err) {
if (err) return done(err);
grunt.log.ok('Server started on port', config.kibana.port);
kibana.start(settings, [devStatics]).then(function (server) {
grunt.log.ok('Server started: ' + server.info.uri);
if (keepalive !== 'keepalive') done();
});
}).catch(done);
});
};

View file

@ -0,0 +1,83 @@
var root = require('requirefrom')('');
var kibana = root('');
var path = require('path');
var glob = require('glob');
var join = path.join;
var rel = join.bind(null, __dirname);
var ROOT = rel('../../../');
var SRC = join(ROOT, 'src');
var NODE_MODULES = join(ROOT, 'node_modules');
var APP = join(SRC, 'kibana');
var TEST = join(ROOT, 'test');
var istanbul = require('./lib/istanbul');
var amdWrapper = require('./lib/amd_wrapper');
var kibanaSrcFilter = require('./lib/kibana_src_filter');
module.exports = new kibana.Plugin({
name: 'dev_statics',
init: function (server, options) {
server.ext('onPreHandler', istanbul({ root: SRC, displayRoot: SRC, filter: kibanaSrcFilter }));
server.ext('onPreHandler', istanbul({ root: APP, displayRoot: SRC, filter: kibanaSrcFilter }));
server.route({
path: '/test/{paths*}',
method: 'GET',
handler: {
directory: {
path: TEST
}
}
});
server.route({
path: '/amd-wrap/{paths*}',
method: 'GET',
handler: amdWrapper({ root: ROOT })
});
server.route({
path: '/src/{paths*}',
method: 'GET',
handler: {
directory: {
path: SRC
}
}
});
server.route({
path: '/node_modules/{paths*}',
method: 'GET',
handler: {
directory: {
path: NODE_MODULES
}
}
});
server.route({
path: '/specs',
method: 'GET',
handler: function (request, reply) {
var unit = join(ROOT, '/test/unit/');
glob(join(unit, 'specs/**/*.js'), function (er, files) {
var moduleIds = files
.filter(function (filename) {
return path.basename(filename).charAt(0) !== '_';
})
.map(function (filename) {
return path.relative(unit, filename).replace(/\\/g, '/').replace(/\.js$/, '');
});
return reply(moduleIds);
});
}
});
}
});

View file

@ -0,0 +1,44 @@
module.exports = function (opts) {
var root = opts.root || '/';
var path = require('path');
var fs = require('fs');
var random = require('lodash').sample;
var pathPrefix = opts.pathPrefix || '/amd-wrap/';
var rap = [
'yo yo yo',
'check it',
'yeeaahh!',
'grocery bag...'
];
return function (request, reply) {
// only allow prefixed requests
if (request.path.substring(0, pathPrefix.length) !== pathPrefix) return reply.continue();
// strip the prefix and form the filename
var filename = path.join(root, request.path.replace('/amd-wrap/', ''));
fs.readFile(filename, 'utf8', function (err, contents) {
// file does not exist
if (err) {
if (err.code === 'ENOENT') {
return reply.continue();
}
return reply(err);
}
// respond with the wrapped code
var source = [
'define(function (require, exports, module) { console.log("' + random(rap) + '");',
contents,
'\n});'
].join('\n');
return reply(source).code(200).type('application/javascript');
});
};
};

View file

@ -0,0 +1,92 @@
var Istanbul = require('istanbul');
var i = new Istanbul.Instrumenter({
embedSource: true,
preserveComments: true,
noAutoWrap: true
});
module.exports = function instrumentationMiddleware(opts) {
var fs = require('fs');
var path = require('path');
// for root directory that files will be served from
var root = opts.root || '/';
// the root directory used to create a relative file path
// for display in coverage reports
var displayRoot = opts.displayRoot || null;
// filter the files in root that can be instrumented
var filter = opts.filter || function (filename) {
// by default only instrument *.js files
return /\.js$/.test(filename);
};
// cache filename resolution
var fileMap = {};
function filenameForReq(request) {
if (request.query.instrument == null) return false;
// expected absolute path to the file
var filename = path.join(root, request.path);
// shortcut for dev where we could be reloading on every save
if (fileMap[filename] !== void 0) return fileMap[filename];
var ret = filename;
if (!fs.existsSync(filename) || !opts.filter(filename)) {
ret = false;
}
// cache the return value for next time
fileMap[filename] = ret;
return ret;
}
return function (request, reply) {
// resolve the request to a readable filename
var filename = filenameForReq(request);
// the file either doesn't exist of it was filtered out by opts.filter
if (!filename) return reply.continue();
fs.stat(filename, function (err, stat) {
if (err && err.code !== 'ENOENT') return reply(err).takeover();
if (err || !stat.isFile()) {
// file was deleted, clear cache and move on
delete fileMap[filename];
return reply.continue();
}
var etag = '"' + stat.size + '-' + Number(stat.mtime) + '"';
if (request.headers['if-none-match'] === etag) {
return reply('').code(304).takeover();
}
fs.readFile(filename, 'utf8', function (err, content) {
if (err) {
return reply(err).takeover();
}
var source = i.instrumentSync(
content,
// make file names easier to read
displayRoot ? path.relative(displayRoot, filename) : filename
);
return reply(source)
.code(200)
.type('application/javascript')
.etag(etag)
.takeover();
});
});
};
};

View file

@ -0,0 +1,5 @@
module.exports = function (filename) {
return filename.match(/.*\/src\/.*\.js$/)
&& !filename.match(/.*\/src\/kibana\/bower_components\/.*\.js$/)
&& !filename.match(/.*\/src\/kibana\/utils\/(event_emitter|rison)\.js$/);
};