Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
fix bug 4404935, including work from pr580 and pr670
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichun Zhan committed Nov 8, 2012
1 parent 14e96cc commit df6149b
Show file tree
Hide file tree
Showing 38 changed files with 517 additions and 64 deletions.
25 changes: 19 additions & 6 deletions docs/dev_guide/intro/mojito_configuring.rst
@@ -1,5 +1,3 @@


================== ==================
Configuring Mojito Configuring Mojito
================== ==================
Expand All @@ -13,10 +11,13 @@ configured differently, but uses same general file format consisting of JSON.
File Format File Format
----------- -----------


All configuration files in Mojito have a general top-level structure and are in JSON format. JSON
At the top level of each configuration file is an array. Each item of the array is an ####
object that configures one component of Mojito, such as logging, assets, mojits, static
resources, etc. By default, configuration files in Mojito have a general top-level structure and are
in JSON format. At the top level of each configuration file is an array. Each item of
the array is an object that configures one component of Mojito, such as logging, assets,
mojits, static resources, etc.


Each configuration object is required to have a ``settings`` property that specifies Each configuration object is required to have a ``settings`` property that specifies
conditions for applying the configuration settings. These conditions could be used to conditions for applying the configuration settings. These conditions could be used to
Expand All @@ -38,6 +39,17 @@ Below is the skeleton of a configuration file. See `Application Configuration`_
... ...
] ]
YAML
####

Mojito also supports configuration files in YAML format. The YAML file extension could
be ``.yaml`` or ``.yml``. Mojito allows comments in the YAML files. When both JSON file
and YAML files are present, the YAML file is used and a warning is issued. For the data
types of the YAML elements, please see the JSON configuration tables in
:ref:`Application Configuration <configure_mj-app>`, :ref:`Routing <configure_mj-routing>`,
and :ref:`Mojit Configuration <configure_mj-mojit>`.

.. _configure_mj-app: .. _configure_mj-app:


Application Configuration Application Configuration
Expand Down Expand Up @@ -818,6 +830,7 @@ function in the controller of the ``Foo`` mojit.
} }
] ]
.. _configure_mj-routing:


Routing Routing
======= =======
Expand Down
Expand Up @@ -29,7 +29,7 @@ YUI.add('flickrModel', function (Y, NAME) {
// Execute against YQL // Execute against YQL
Y.YQL(select, function(rawYql) { Y.YQL(select, function(rawYql) {
// Handle empty response. // Handle empty response.
if (null === rawYql || 0 === rawYql.query.count) { if (null === rawYql || !rawYql.query.count || !rawYql.query.results) {
callback([]); callback([]);
} }
// Process data. // Process data.
Expand Down
80 changes: 57 additions & 23 deletions lib/app/addons/rs/config.server.js
Expand Up @@ -25,7 +25,8 @@ YUI.add('addon-rs-config', function(Y, NAME) {
var libfs = require('fs'), var libfs = require('fs'),
libpath = require('path'), libpath = require('path'),
existsSync = libfs.existsSync || libpath.existsSync, existsSync = libfs.existsSync || libpath.existsSync,
libycb = require('ycb'); libycb = require('ycb'),
libyaml = require('js-yaml');


function RSAddonConfig() { function RSAddonConfig() {
RSAddonConfig.superclass.constructor.apply(this, arguments); RSAddonConfig.superclass.constructor.apply(this, arguments);
Expand Down Expand Up @@ -61,33 +62,66 @@ YUI.add('addon-rs-config', function(Y, NAME) {
return Y.mojito.util.copy(this._ycbDims); return Y.mojito.util.copy(this._ycbDims);
}, },



/** /**
* Reads and parses a JSON file. * Same as readConfigSync except the result is cached for future calls.
* @method readConfigJSON * @method readConfigSimple
* @param {string} fullPath path to JSON file * @param {string} fullPath path to JSON or YAML file
* @return {user-defined} contents of JSON file * @return {user-defined} contents of file as an object
*/ */
// TODO: async interface readConfigSimple: function(fullPath) {
readConfigJSON: function(fullPath) { var json;
var json,
contents;
if (!existsSync(fullPath)) {
return {};
}
json = this._jsonCache[fullPath]; json = this._jsonCache[fullPath];
if (!json) { if (!json) {
try { json = this.readConfigSync(fullPath);
contents = libfs.readFileSync(fullPath, 'utf-8');
json = Y.JSON.parse(contents);
} catch (e) {
throw new Error('Error parsing JSON file: ' + fullPath);
}
this._jsonCache[fullPath] = json; this._jsonCache[fullPath] = json;
} }

return Y.mojito.util.copy(json); return Y.mojito.util.copy(json);
}, },


/**
* Reads and parses a JSON or YAML structured file.
* @method readConfigSync
* @param {string} fullPath path to JSON or YAML file
* @return {user-defined} contents of file as an object
*/
readConfigSync: function (filePath) {

var extensions = ['.yml', '.yaml', '.json'],
i,
json = false,
raw,
obj = {};

if (libpath.extname(filePath)) {
filePath = filePath.slice(0, libpath.extname(filePath).length * -1);
}

for (i = extensions.length - 1; i >= 0; i -= 1) {
try {
raw = libfs.readFileSync(filePath + extensions[i], 'utf8');
try {
if (i === 2) { // json
obj = JSON.parse(raw);
json = true;
} else { // yaml or yml
obj = libyaml.load(raw);
if (json) {
Y.log(filePath + extensions[2] + ' exists. But ' + extensions[i] + ' file will be used', 'warn', NAME);
}
}
} catch (parseErr) {
throw new Error(parseErr);
}
} catch (err) {
if (err.errno !== 34) { // if the error was not "no such file or directory" report it
throw new Error("Error parsing file: " + filePath + extensions[i] + "\n" + err);
}
}
}
return obj;
},



/** /**
* Reads a configuration file that is in YCB format. * Reads a configuration file that is in YCB format.
Expand All @@ -114,7 +148,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
cacheKey = Y.JSON.stringify(ctx); cacheKey = Y.JSON.stringify(ctx);
ycb = this._ycbCache[fullPath][cacheKey]; ycb = this._ycbCache[fullPath][cacheKey];
if (!ycb) { if (!ycb) {
json = this.readConfigJSON(fullPath); json = this.readConfigSimple(fullPath);
json = this._ycbDims.concat(json); json = this._ycbDims.concat(json);
ycb = libycb.read(json, ctx); ycb = libycb.read(json, ctx);
this._ycbCache[fullPath][cacheKey] = ycb; this._ycbCache[fullPath][cacheKey] = ycb;
Expand Down Expand Up @@ -142,8 +176,8 @@ YUI.add('addon-rs-config', function(Y, NAME) {
if ('.' !== fs.subDir) { if ('.' !== fs.subDir) {
return; return;
} }
// we only care about json files // we only care about json or yaml files
if ('.json' !== fs.ext) { if ('.json' !== fs.ext && '.yaml' !== fs.ext && '.yml' !== fs.ext) {
return; return;
} }
// use package.json for the app and the mojit // use package.json for the app and the mojit
Expand Down Expand Up @@ -217,7 +251,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
if (!existsSync(path)) { if (!existsSync(path)) {
path = libpath.join(this.mojitoRoot, 'dimensions.json'); path = libpath.join(this.mojitoRoot, 'dimensions.json');
} }
return this.readConfigJSON(path); return this.readConfigSimple(path);
} }




Expand Down
4 changes: 2 additions & 2 deletions lib/app/addons/rs/selector.server.js
Expand Up @@ -4,7 +4,7 @@
* See the accompanying LICENSE file for terms. * See the accompanying LICENSE file for terms.
*/ */


/*jslint anon:true, sloppy:true, nomen:true*/ /*jslint anon:true, sloppy:true, nomen:true, stupid:true*/
/*global YUI*/ /*global YUI*/




Expand Down Expand Up @@ -42,7 +42,7 @@ YUI.add('addon-rs-selector', function(Y, NAME) {
this.mojitoRoot = config.mojitoRoot; this.mojitoRoot = config.mojitoRoot;


dims = config.host.config.getDimensions(); dims = config.host.config.getDimensions();
json = config.host.config.readConfigJSON(libpath.join(this.appRoot, 'application.json')); json = config.host.config.readConfigSimple(libpath.join(this.appRoot, 'application.json'));
json = dims.concat(json); json = dims.concat(json);
// TODO: use rs.config for this too // TODO: use rs.config for this too
this._appConfigYCB = new libycb.Ycb(json); this._appConfigYCB = new libycb.Ycb(json);
Expand Down
2 changes: 1 addition & 1 deletion lib/app/addons/rs/url.server.js
Expand Up @@ -113,7 +113,7 @@ YUI.add('addon-rs-url', function(Y, NAME) {
mojitIsPublic = false; mojitIsPublic = false;
if (mojitRes) { if (mojitRes) {
packageJson = libpath.join(mojitRes.source.fs.fullPath, 'package.json'); packageJson = libpath.join(mojitRes.source.fs.fullPath, 'package.json');
packageJson = store.config.readConfigJSON(packageJson); packageJson = store.config.readConfigSimple(packageJson);
if ('public' === (packageJson.yahoo && if ('public' === (packageJson.yahoo &&
packageJson.yahoo.mojito && packageJson.yahoo.mojito &&
packageJson.yahoo.mojito['package'])) { packageJson.yahoo.mojito['package'])) {
Expand Down
33 changes: 25 additions & 8 deletions lib/app/commands/start.js
Expand Up @@ -55,20 +55,37 @@ exports.run = function(params, opts, callback) {
pack, pack,
inputOptions = opts || {}, inputOptions = opts || {},
options = {}, options = {},
app; app,
store;

Y.applyConfig({
useSync: true,
modules: {
'mojito-util': {
fullpath: path.join(__dirname, '../../app/autoload/util.common.js')
},
'mojito-resource-store': {
fullpath: path.join(__dirname, '../../store.server.js')
}
}
});
Y.use('mojito-util', 'mojito-resource-store');

// load details
store = new Y.mojito.ResourceStore({
root: process.cwd(),
context: {}
});


try { try {
// Are we in a Mojito App? Read the application.json config to find out. // Are we in a Mojito App? Read the application config to find out.
appConfig = Y.JSON.parse(fs.readFileSync(path.join(root, appConfig = store.config.readConfigYCB(path.join(root, 'application.json'));
'application.json'), 'utf8'));
appConfig = appConfig[0];
} catch (err) { } catch (err) {
appConfig = {}; appConfig = {};
} }


try { // Read the package.json config try { // Read the package config
pack = Y.JSON.parse(fs.readFileSync(path.join(root, 'package.json'), pack = store.config.readConfigSimple(path.join(root, 'package.json'));
'utf8'));
} catch (err2) { } catch (err2) {
pack = {}; pack = {};
} }
Expand Down
21 changes: 11 additions & 10 deletions lib/store.server.js
Expand Up @@ -207,7 +207,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {


this._validDims = this._parseValidDims(this.config.getDimensions()); this._validDims = this._parseValidDims(this.config.getDimensions());
this.validateContext(this._config.context); this.validateContext(this._config.context);
this._fwConfig = this.config.readConfigJSON(this._libs.path.join(this._config.mojitoRoot, 'config.json')); this._fwConfig = this.config.readConfigSimple(this._libs.path.join(this._config.mojitoRoot, 'config.json'));
this._appConfigStatic = this.getAppConfig({}); this._appConfigStatic = this.getAppConfig({});
}, },
destructor: function() {}, destructor: function() {},
Expand Down Expand Up @@ -732,7 +732,8 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
ress, ress,
r, r,
res, res,
routes; routes,
routeFile;


for (p = 0; p < routesFiles.length; p += 1) { for (p = 0; p < routesFiles.length; p += 1) {
path = routesFiles[p]; path = routesFiles[p];
Expand All @@ -743,11 +744,9 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
fixedPaths[path] = true; fixedPaths[path] = true;
} }


ress = this.getResources('server', ctx, {type: 'config'}); for (routeFile in fixedPaths) {
for (r = 0; r < ress.length; r += 1) { if (fixedPaths.hasOwnProperty(routeFile)) {
res = ress[r]; routes = Y.mojito.util.copy(this.config.readConfigYCB(routeFile, ctx));
if (fixedPaths[res.source.fs.fullPath]) {
routes = Y.mojito.util.copy(this.config.readConfigYCB(res.source.fs.fullPath, ctx));
out = Y.merge(out, routes); out = Y.merge(out, routes);
} }
} }
Expand Down Expand Up @@ -916,7 +915,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
parents: [], parents: [],
dir: dir dir: dir
}; };
info.pkg = this.config.readConfigJSON(this._libs.path.join(dir, 'package.json')); info.pkg = this.config.readConfigSimple(this._libs.path.join(dir, 'package.json'));


if (Object.keys(info.pkg).length) { if (Object.keys(info.pkg).length) {
mojitoVersion = info.pkg.version; mojitoVersion = info.pkg.version;
Expand Down Expand Up @@ -979,9 +978,11 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
if (CONVENTION_SUBDIR_TYPE_IS_JS[type] && '.js' !== fs.ext) { if (CONVENTION_SUBDIR_TYPE_IS_JS[type] && '.js' !== fs.ext) {
return false; return false;
} }
if ('spec' === type && '.json' !== fs.ext) {
if ('spec' === type && ('.json' !== fs.ext && '.yaml' !== fs.ext && '.yml' !== fs.ext)) {
return false; return false;
} }

return { return {
type: type, type: type,
skipSubdirParts: 1 skipSubdirParts: 1
Expand Down Expand Up @@ -1620,7 +1621,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
} else { } else {
mojitType = this._libs.path.basename(dir); mojitType = this._libs.path.basename(dir);
} }
packageJson = this.config.readConfigJSON(this._libs.path.join(dir, 'package.json')); packageJson = this.config.readConfigSimple(this._libs.path.join(dir, 'package.json'));
if (packageJson) { if (packageJson) {
if (packageJson.name) { if (packageJson.name) {
mojitType = packageJson.name; mojitType = packageJson.name;
Expand Down

0 comments on commit df6149b

Please sign in to comment.