Permalink
Browse files

fix bug 4404935, including work from pr580 and pr670

  • Loading branch information...
Lichun Zhan
Lichun Zhan committed Nov 8, 2012
1 parent 14e96cc commit df6149b225c6b9ad4e003df6a13936fade1ec0b5
Showing with 517 additions and 64 deletions.
  1. +19 −6 docs/dev_guide/intro/mojito_configuring.rst
  2. +1 −1 examples/developer-guide/model_yql/mojits/flickr/models/model.server.js
  3. +57 −23 lib/app/addons/rs/config.server.js
  4. +2 −2 lib/app/addons/rs/selector.server.js
  5. +1 −1 lib/app/addons/rs/url.server.js
  6. +25 −8 lib/app/commands/start.js
  7. +11 −10 lib/store.server.js
  8. +81 −4 lib/tests/autoload/app/addons/rs/config-tests.server.js
  9. +1 −1 lib/tests/autoload/app/addons/rs/url-tests.server.js
  10. +1 −1 lib/tests/autoload/app/addons/rs/yui-tests.server.js
  11. +1 −1 lib/tests/autoload/store.server-tests.js
  12. +1 −0 package.json
  13. +2 −0 tests/fixtures/config/bad.yaml
  14. +3 −0 tests/fixtures/config/ext.json
  15. +3 −0 tests/fixtures/config/json.json
  16. +1 −0 tests/fixtures/config/yaml.yaml
  17. +1 −0 tests/fixtures/config/yml.yml
  18. +6 −0 tests/func/applications/apps.json
  19. +23 −0 tests/func/applications/frameworkapp/yaml-config/application.json
  20. +14 −0 tests/func/applications/frameworkapp/yaml-config/application.yaml
  21. +13 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/controller.common.js
  22. +9 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/defaults.json
  23. +9 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/defaults.yaml
  24. +5 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/definition.json
  25. +11 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/definition.yaml
  26. +8 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/specs/default.json
  27. +8 −0 tests/func/applications/frameworkapp/yaml-config/mojits/simple/specs/default.yaml
  28. +3 −0 tests/func/applications/frameworkapp/yaml-config/package.json
  29. +2 −0 tests/func/applications/frameworkapp/yaml-config/package.yaml
  30. +15 −0 tests/func/applications/frameworkapp/yaml-config/routes.json
  31. +22 −0 tests/func/applications/frameworkapp/yaml-config/routes.yml
  32. +21 −0 tests/func/yaml-config/testyamlconfig1.js
  33. +21 −0 tests/func/yaml-config/testyamlconfig2.js
  34. +33 −0 tests/func/yaml-config/yamlconfigtest_descriptor.json
  35. +80 −3 tests/unit/lib/app/addons/rs/test-config.server.js
  36. +1 −1 tests/unit/lib/app/addons/rs/test-url.server.js
  37. +1 −1 tests/unit/lib/app/addons/rs/test-yui.server.js
  38. +1 −1 tests/unit/lib/test-store.server.js
@@ -1,5 +1,3 @@
-
-
==================
Configuring Mojito
==================
@@ -13,10 +11,13 @@ configured differently, but uses same general file format consisting of JSON.
File Format
-----------
-All 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.
+JSON
+####
+
+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
conditions for applying the configuration settings. These conditions could be used to
@@ -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:
Application Configuration
@@ -818,6 +830,7 @@ function in the controller of the ``Foo`` mojit.
}
]
+.. _configure_mj-routing:
Routing
=======
@@ -29,7 +29,7 @@ YUI.add('flickrModel', function (Y, NAME) {
// Execute against YQL
Y.YQL(select, function(rawYql) {
// Handle empty response.
- if (null === rawYql || 0 === rawYql.query.count) {
+ if (null === rawYql || !rawYql.query.count || !rawYql.query.results) {
callback([]);
}
// Process data.
@@ -25,7 +25,8 @@ YUI.add('addon-rs-config', function(Y, NAME) {
var libfs = require('fs'),
libpath = require('path'),
existsSync = libfs.existsSync || libpath.existsSync,
- libycb = require('ycb');
+ libycb = require('ycb'),
+ libyaml = require('js-yaml');
function RSAddonConfig() {
RSAddonConfig.superclass.constructor.apply(this, arguments);
@@ -61,33 +62,66 @@ YUI.add('addon-rs-config', function(Y, NAME) {
return Y.mojito.util.copy(this._ycbDims);
},
-
/**
- * Reads and parses a JSON file.
- * @method readConfigJSON
- * @param {string} fullPath path to JSON file
- * @return {user-defined} contents of JSON file
+ * Same as readConfigSync except the result is cached for future calls.
+ * @method readConfigSimple
+ * @param {string} fullPath path to JSON or YAML file
+ * @return {user-defined} contents of file as an object
*/
- // TODO: async interface
- readConfigJSON: function(fullPath) {
- var json,
- contents;
- if (!existsSync(fullPath)) {
- return {};
- }
+ readConfigSimple: function(fullPath) {
+ var json;
json = this._jsonCache[fullPath];
if (!json) {
- try {
- contents = libfs.readFileSync(fullPath, 'utf-8');
- json = Y.JSON.parse(contents);
- } catch (e) {
- throw new Error('Error parsing JSON file: ' + fullPath);
- }
+ json = this.readConfigSync(fullPath);
this._jsonCache[fullPath] = 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.
@@ -114,7 +148,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
cacheKey = Y.JSON.stringify(ctx);
ycb = this._ycbCache[fullPath][cacheKey];
if (!ycb) {
- json = this.readConfigJSON(fullPath);
+ json = this.readConfigSimple(fullPath);
json = this._ycbDims.concat(json);
ycb = libycb.read(json, ctx);
this._ycbCache[fullPath][cacheKey] = ycb;
@@ -142,8 +176,8 @@ YUI.add('addon-rs-config', function(Y, NAME) {
if ('.' !== fs.subDir) {
return;
}
- // we only care about json files
- if ('.json' !== fs.ext) {
+ // we only care about json or yaml files
+ if ('.json' !== fs.ext && '.yaml' !== fs.ext && '.yml' !== fs.ext) {
return;
}
// use package.json for the app and the mojit
@@ -217,7 +251,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
if (!existsSync(path)) {
path = libpath.join(this.mojitoRoot, 'dimensions.json');
}
- return this.readConfigJSON(path);
+ return this.readConfigSimple(path);
}
@@ -4,7 +4,7 @@
* 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*/
@@ -42,7 +42,7 @@ YUI.add('addon-rs-selector', function(Y, NAME) {
this.mojitoRoot = config.mojitoRoot;
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);
// TODO: use rs.config for this too
this._appConfigYCB = new libycb.Ycb(json);
@@ -113,7 +113,7 @@ YUI.add('addon-rs-url', function(Y, NAME) {
mojitIsPublic = false;
if (mojitRes) {
packageJson = libpath.join(mojitRes.source.fs.fullPath, 'package.json');
- packageJson = store.config.readConfigJSON(packageJson);
+ packageJson = store.config.readConfigSimple(packageJson);
if ('public' === (packageJson.yahoo &&
packageJson.yahoo.mojito &&
packageJson.yahoo.mojito['package'])) {
View
@@ -55,20 +55,37 @@ exports.run = function(params, opts, callback) {
pack,
inputOptions = opts || {},
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 {
- // Are we in a Mojito App? Read the application.json config to find out.
- appConfig = Y.JSON.parse(fs.readFileSync(path.join(root,
- 'application.json'), 'utf8'));
- appConfig = appConfig[0];
+ // Are we in a Mojito App? Read the application config to find out.
+ appConfig = store.config.readConfigYCB(path.join(root, 'application.json'));
} catch (err) {
appConfig = {};
}
- try { // Read the package.json config
- pack = Y.JSON.parse(fs.readFileSync(path.join(root, 'package.json'),
- 'utf8'));
+ try { // Read the package config
+ pack = store.config.readConfigSimple(path.join(root, 'package.json'));
} catch (err2) {
pack = {};
}
View
@@ -207,7 +207,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
this._validDims = this._parseValidDims(this.config.getDimensions());
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({});
},
destructor: function() {},
@@ -732,7 +732,8 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
ress,
r,
res,
- routes;
+ routes,
+ routeFile;
for (p = 0; p < routesFiles.length; p += 1) {
path = routesFiles[p];
@@ -743,11 +744,9 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
fixedPaths[path] = true;
}
- ress = this.getResources('server', ctx, {type: 'config'});
- for (r = 0; r < ress.length; r += 1) {
- res = ress[r];
- if (fixedPaths[res.source.fs.fullPath]) {
- routes = Y.mojito.util.copy(this.config.readConfigYCB(res.source.fs.fullPath, ctx));
+ for (routeFile in fixedPaths) {
+ if (fixedPaths.hasOwnProperty(routeFile)) {
+ routes = Y.mojito.util.copy(this.config.readConfigYCB(routeFile, ctx));
out = Y.merge(out, routes);
}
}
@@ -916,7 +915,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
parents: [],
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) {
mojitoVersion = info.pkg.version;
@@ -979,9 +978,11 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
if (CONVENTION_SUBDIR_TYPE_IS_JS[type] && '.js' !== fs.ext) {
return false;
}
- if ('spec' === type && '.json' !== fs.ext) {
+
+ if ('spec' === type && ('.json' !== fs.ext && '.yaml' !== fs.ext && '.yml' !== fs.ext)) {
return false;
}
+
return {
type: type,
skipSubdirParts: 1
@@ -1620,7 +1621,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
} else {
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.name) {
mojitType = packageJson.name;
Oops, something went wrong.

0 comments on commit df6149b

Please sign in to comment.