Files
firebase-tools/lib/config.js
2015-10-12 10:43:25 -07:00

107 lines
2.9 KiB
JavaScript

'use strict';
var cjson = require('cjson');
var FirebaseError = require('./error');
var _ = require('lodash');
var resolveProjectPath = require('./resolveProjectPath');
var path = require('path');
var fs = require('fs');
var loadCJSON = require('./loadCJSON');
var parseBoltRules = require('./parseBoltRules');
var detectProjectRoot = require('./detectProjectRoot');
var Config = function(src, options) {
this.options = options || {};
this._src = src;
this.data = {};
this.defaults = {};
if (this._src.firebase) {
this.defaults.project = this._src.firebase;
}
Config.TARGETS.forEach(function(target) {
if (this._src[target]) {
this.data[target] = this._materialize(target);
}
}, this);
// use 'public' as signal for legacy hosting since it's a required key
if (!this.data.hosting && this._src.public) {
this.data.hosting = {};
Config.LEGACY_HOSTING_KEYS.forEach(function(key) {
if (this._src[key]) {
this.data.hosting[key] = this._src[key];
}
}, this);
}
};
Config.FILENAME = 'firebase.json';
Config.TARGETS = ['hosting', 'rules'];
Config.LEGACY_HOSTING_KEYS = ['public', 'rewrites', 'redirects', 'headers', 'ignore'];
Config.prototype._materialize = function(target) {
if (_.isString(this._src[target])) {
return this._parseFile(target, this._src[target]);
} else if (_.isObject(this._src[target])) {
return this._src[target];
}
throw new FirebaseError('Parse Error: "' + target + '" must be object or import path', {exit: 1});
};
Config.prototype._parseFile = function(target, filePath) {
var fullPath = resolveProjectPath(this.options.cwd, filePath);
var ext = path.extname(filePath);
if (!fs.existsSync(fullPath)) {
throw new FirebaseError('Parse Error: Imported file ' + filePath + ' does not exist', {exit: 1});
}
switch (ext) {
case '.json':
var data = loadCJSON(fullPath);
// if e.g. rules.json has {"rules": {}} use that
if (_.size(data) === 1 && data[target]) {
data = data[target];
}
return data;
/* istanbul ignore-next */
case '.bolt':
return parseBoltRules(fullPath);
default:
throw new FirebaseError('Parse Error: ' + filePath + ' is not of a supported config file type', {exit: 1});
}
};
Config.prototype.get = function(key, fallback) {
return _.get(this.data, key, fallback);
};
Config.prototype.has = function(key) {
return _.has(this.data, key);
};
Config.load = function(options, allowMissing) {
var pd = detectProjectRoot(options.cwd);
if (pd) {
try {
var data = cjson.load(path.join(pd, Config.FILENAME));
return new Config(data, options);
} catch (e) {
throw new FirebaseError('There was an error loading firebase.json:\n\n' + e.message, {
exit: 1
});
}
}
if (allowMissing) {
return null;
}
throw new FirebaseError('Not in a Firebase app directory (could not locate firebase.json)', {exit: 1});
};
module.exports = Config;