asset-rack
Version:
Static Web Framework for Nodejs
322 lines (294 loc) • 9.66 kB
JavaScript
// Generated by CoffeeScript 1.6.3
(function() {
var BufferStream, ConfigRack, EventEmitter, async, extend, fs, jade, pathutil, pkgcloud, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
async = require('async');
pkgcloud = require('pkgcloud');
fs = require('fs');
jade = require('jade');
pathutil = require('path');
_ref = require('./util'), BufferStream = _ref.BufferStream, extend = _ref.extend;
EventEmitter = require('events').EventEmitter;
exports.Rack = (function(_super) {
__extends(Rack, _super);
function Rack(assets, options) {
var asset, _i, _len,
_this = this;
Rack.__super__.constructor.call(this);
if (options == null) {
options = {};
}
this.maxAge = options.maxAge;
this.allowNoHashCache = options.allowNoHashCache;
this.on('complete', function() {
return _this.completed = true;
});
this.on('newListener', function(event, listener) {
if (event === 'complete' && _this.completed === true) {
return listener();
}
});
this.on('error', function(error) {
console.log(error);
_this.hasError = true;
return _this.currentError = error;
});
for (_i = 0, _len = assets.length; _i < _len; _i++) {
asset = assets[_i];
asset.rack = this;
}
this.assets = [];
async.forEachSeries(assets, function(asset, next) {
asset.on('error', function(error) {
return next(error);
});
asset.on('complete', function() {
if (_this.completed) {
return;
}
if (asset.contents != null) {
_this.assets.push(asset);
}
if (asset.assets != null) {
_this.assets = _this.assets.concat(asset.assets);
}
return next();
});
return asset.emit('start');
}, function(error) {
if (error != null) {
return _this.emit('error', error);
}
return _this.emit('complete');
});
}
Rack.prototype.handle = function(request, response, next) {
var asset, check, handle, _i, _len, _ref1,
_this = this;
response.locals({
assets: this
});
if (request.url.slice(0, 11) === '/asset-rack') {
return this.handleAdmin(request, response, next);
}
if (this.hasError) {
_ref1 = this.assets;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
asset = _ref1[_i];
check = asset.checkUrl(request.path);
if (check) {
return asset.respond(request, response);
}
}
return response.redirect('/asset-rack/error');
}
handle = function() {
var _j, _len1, _ref2;
_ref2 = _this.assets;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
asset = _ref2[_j];
check = asset.checkUrl(request.path);
if (check) {
return asset.respond(request, response);
}
}
return next();
};
if (this.completed) {
return handle();
} else {
return this.on('complete', handle);
}
};
Rack.prototype.handleError = function(request, response, next) {
var errorPath,
_this = this;
if (process.env.NODE_ENV === 'production') {
return next();
}
errorPath = pathutil.join(__dirname, 'admin/templates/error.jade');
return fs.readFile(errorPath, 'utf8', function(error, contents) {
var compiled;
if (error != null) {
return next(error);
}
compiled = jade.compile(contents, {
filename: errorPath
});
return response.send(compiled({
stack: _this.currentError.stack.split('\n')
}));
});
};
Rack.prototype.handleAdmin = function(request, response, next) {
var adminPath, path, split,
_this = this;
if (process.env.NODE_ENV === 'production') {
return next();
}
split = request.url.split('/');
if (split.length > 2) {
path = request.url.replace('/asset-rack/', '');
if (path === 'error') {
return this.handleError(request, response, next);
}
return response.sendfile(pathutil.join(__dirname, 'admin', path));
} else {
adminPath = pathutil.join(__dirname, 'admin/templates/admin.jade');
return fs.readFile(adminPath, 'utf8', function(error, contents) {
var compiled;
if (error != null) {
return next(error);
}
compiled = jade.compile(contents, {
filename: adminPath
});
return response.send(compiled({
assets: _this.assets
}));
});
}
};
Rack.prototype.writeConfigFile = function(filename) {
var asset, config, _i, _len, _ref1;
config = {};
_ref1 = this.assets;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
asset = _ref1[_i];
config[asset.url] = asset.specificUrl;
}
return fs.writeFileSync(filename, JSON.stringify(config));
};
Rack.prototype.deploy = function(options, next) {
var deploy,
_this = this;
options.keyId = options.accessKey;
options.key = options.secretKey;
deploy = function() {
var assets, client;
client = pkgcloud.storage.createClient(options);
assets = _this.assets;
if (options.provider === 'rackspace') {
assets = _this.assets.concat(_this.assets[0]);
}
return async.forEachSeries(assets, function(asset, next) {
var clientOptions, headers, key, stream, url, value, _ref1;
stream = null;
headers = {};
if (asset.gzip) {
stream = new BufferStream(asset.gzipContents);
headers['content-encoding'] = 'gzip';
} else {
stream = new BufferStream(asset.contents);
}
url = asset.specificUrl.slice(1, asset.specificUrl.length);
_ref1 = asset.headers;
for (key in _ref1) {
value = _ref1[key];
headers[key] = value;
}
if (options.provider === 'amazon') {
headers['x-amz-acl'] = 'public-read';
}
clientOptions = {
container: options.container,
remote: url,
headers: headers,
stream: stream
};
return client.upload(clientOptions, function(error) {
if (error != null) {
return next(error);
}
return next();
});
}, function(error) {
if (error != null) {
if (next != null) {
return next(error);
}
throw error;
}
if (options.configFile != null) {
_this.writeConfigFile(options.configFile);
}
if (next != null) {
return next();
}
});
};
if (this.completed) {
return deploy();
} else {
return this.on('complete', deploy);
}
};
Rack.prototype.tag = function(url) {
var asset, _i, _len, _ref1;
_ref1 = this.assets;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
asset = _ref1[_i];
if (asset.url === url) {
return asset.tag();
}
}
throw new Error("No asset found for url: " + url);
};
Rack.prototype.url = function(url) {
var asset, _i, _len, _ref1;
_ref1 = this.assets;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
asset = _ref1[_i];
if (url === asset.url) {
return asset.specificUrl;
}
}
};
Rack.extend = extend;
return Rack;
})(EventEmitter);
ConfigRack = (function() {
function ConfigRack(options) {
if (options.configFile == null) {
throw new Error('options.configFile is required');
}
if (options.hostname == null) {
throw new Error('options.hostname is required');
}
this.assetMap = require(options.configFile);
this.hostname = options.hostname;
}
ConfigRack.prototype.handle = function(request, response, next) {
var specificUrl, url, _ref1;
response.locals({
assets: this
});
_ref1 = this.assetMap;
for (url in _ref1) {
specificUrl = _ref1[url];
if (request.path === url || request.path === specificUrl) {
return response.redirect("//" + this.hostname + specificUrl);
}
}
return next();
};
ConfigRack.prototype.tag = function(url) {
var tag;
switch (pathutil.extname(url)) {
case '.js':
tag = "\n<script type=\"text/javascript\" ";
return tag += "src=\"//" + this.hostname + this.assetMap[url] + "\"></script>";
case '.css':
return "\n<link rel=\"stylesheet\" href=\"//" + this.hostname + this.assetMap[url] + "\">";
}
};
ConfigRack.prototype.url = function(url) {
return "//" + this.hostname + this.assetMap[url];
};
return ConfigRack;
})();
exports.fromConfigFile = function(options) {
return new ConfigRack(options);
};
}).call(this);