forked from flanchan/doushio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
3.8 KiB
165 lines
3.8 KiB
6 years ago
|
var async = require('async'),
|
||
|
config = require('./config'),
|
||
|
crypto = require('crypto'),
|
||
|
etc = require('./etc'),
|
||
|
fs = require('fs'),
|
||
|
make_client = require('./make_client').make_maybe_minified,
|
||
|
pathJoin = require('path').join,
|
||
|
stream = require('stream'),
|
||
|
tmp_file = require('tmp').file,
|
||
|
util = require('util');
|
||
|
|
||
|
const PUBLIC_JS = pathJoin('www', 'js');
|
||
|
|
||
|
function HashingStream(out) {
|
||
|
stream.Writable.call(this);
|
||
|
|
||
|
this._hash = crypto.createHash('MD5');
|
||
|
this._outStream = out;
|
||
|
}
|
||
|
util.inherits(HashingStream, stream.Writable);
|
||
|
|
||
|
HashingStream.prototype._write = function (chunk, encoding, cb) {
|
||
|
this._hash.update(chunk);
|
||
|
this._outStream.write(chunk, encoding, cb);
|
||
|
};
|
||
|
|
||
|
HashingStream.prototype.end = function (cb) {
|
||
|
if (arguments.length > 1)
|
||
|
throw new Error("TODO multi-arg HashingStream.end");
|
||
|
var self = this;
|
||
|
stream.Writable.prototype.end.call(this, function () {
|
||
|
self._outStream.end(function () {
|
||
|
if (cb)
|
||
|
cb();
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
function end_and_move_js(stream, dir, prefix, cb) {
|
||
|
stream.end(function () {
|
||
|
var fnm;
|
||
|
if (config.DEBUG) {
|
||
|
fnm = prefix + '-debug.js';
|
||
|
}
|
||
|
else {
|
||
|
var hash = stream._hash.digest('hex').slice(0, 10);
|
||
|
fnm = prefix + '-' + hash + '.min.js';
|
||
|
}
|
||
|
var tmp = stream._tmpFilename;
|
||
|
etc.move(tmp, pathJoin(dir, fnm), function (err) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
cb(null, fnm);
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
|
||
|
function make_hashing_stream(cb) {
|
||
|
// ideally the stream would be returned immediately and handle
|
||
|
// this step internally...
|
||
|
var opts = {dir: '.build', postfix: '.gen.js', mode: 0644};
|
||
|
tmp_file(opts, function (err, tmp, fd) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
var out = fs.createWriteStream(null, {fd: fd});
|
||
|
out.once('error', cb);
|
||
|
|
||
|
if (config.DEBUG) {
|
||
|
out._tmpFilename = tmp;
|
||
|
cb(null, out);
|
||
|
}
|
||
|
else {
|
||
|
var stream = new HashingStream(out);
|
||
|
stream._tmpFilename = tmp;
|
||
|
cb(null, stream);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function build_vendor_js(cb) {
|
||
|
var deps = require('./deps');
|
||
|
make_hashing_stream(function (err, stream) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
async.eachSeries(deps.VENDOR_DEPS, function (file, cb) {
|
||
|
fs.readFile(file, function (err, buf) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
stream.write(buf, cb);
|
||
|
});
|
||
|
}, function (err) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
end_and_move_js(stream, PUBLIC_JS, 'vendor', cb);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function build_client_js(cb) {
|
||
|
var deps = require('./deps');
|
||
|
make_hashing_stream(function (err, stream) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
make_client(deps.CLIENT_DEPS, stream, function (err) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
end_and_move_js(stream, PUBLIC_JS, 'client', cb);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function build_mod_client_js(cb) {
|
||
|
var deps = require('./deps');
|
||
|
make_hashing_stream(function (err, stream) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
make_client(deps.MOD_CLIENT_DEPS, stream, function (err) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
end_and_move_js(stream, 'state', 'mod', cb);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function commit_assets(metadata, cb) {
|
||
|
tmp_file({dir: '.build', postfix: '.json'}, function (err, tmp, fd) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
var stream = fs.createWriteStream(null, {fd: fd});
|
||
|
stream.once('error', cb);
|
||
|
stream.end(JSON.stringify(metadata) + '\n', function () {
|
||
|
etc.move(tmp, pathJoin('state', 'scripts.json'), cb);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function rebuild(cb) {
|
||
|
etc.checked_mkdir('state', function (err) {
|
||
|
etc.checked_mkdir('.build', function (err) {
|
||
|
if (err) return cb(err);
|
||
|
async.parallel({
|
||
|
vendor: build_vendor_js,
|
||
|
client: build_client_js,
|
||
|
mod: build_mod_client_js,
|
||
|
}, function (err, hashes) {
|
||
|
if (err)
|
||
|
return cb(err);
|
||
|
commit_assets(hashes, cb);
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
exports.rebuild = rebuild;
|
||
|
|
||
|
exports.refresh_deps = function () {
|
||
|
delete require.cache[pathJoin(__dirname, 'deps.js')];
|
||
|
};
|
||
|
|
||
|
if (require.main === module) {
|
||
|
rebuild(function (err) {
|
||
|
if (err) throw err;
|
||
|
});
|
||
|
}
|