Permalink
Browse files

[gh238] [bz5667423] application.json files in NPM packages can contri…

…bute as well
  • Loading branch information...
1 parent 1fd2775 commit d1390d7f619c79a7bcdc66b6327ce27b7dee019c @drewfish drewfish committed Jan 10, 2013
View
@@ -4,6 +4,7 @@
*.bak
*~
node_modules
+!tests/fixtures/app-jsons/node_modules
!tests/fixtures/packages/node_modules
!tests/fixtures/packages/node_modules/*/node_modules
arrowreport
@@ -165,6 +165,48 @@ YUI.add('addon-rs-config', function(Y, NAME) {
/**
+ * Creates a YCB configuration bundle using contents from multiple files.
+ * The appropriate dimensions.json file will be mixed in, and doesn't need
+ * to be part of the list of files.
+ * @method createMultipartYCB
+ * @param {array} paths list of files to load
+ * @return {YCB|undefined} return a YCB library object, or undefined if an error occurs
+ */
+ createMultipartYCB: function(paths) {
+ var p,
+ path,
+ config,
+ s,
+ section,
+ settings = {},
+ bundle = [];
+ bundle.push(this.getDimensions()[0]);
+ for (p = 0; p < paths.length; p += 1) {
+ path = paths[p];
+ config = this.readConfigSync(path);
+ if (!Y.Lang.isArray(config)) {
+ Y.log('not a YCB file: ' + path, 'error', NAME);
+ return;
+ }
+ for (s = 0; s < config.length; s += 1) {
+ section = config[s];
+ if (!Y.Lang.isArray(section.settings)) {
+ Y.log('missing "settings" in YCB file: ' + path, 'error', NAME);
+ return;
+ }
+ if (settings[section.settings]) {
+ Y.log('settings "' + section.settings + '" exists in both \n' + path + ' and\n' + settings[section.settings], 'error', NAME);
+ return;
+ }
+ settings[section.settings] = path;
+ bundle.push(section);
+ }
+ }
+ return new libycb.Ycb(bundle);
+ },
+
+
+ /**
* Using AOP, this is called after the ResourceStore's version.
* @method findResourceVersionByConvention
* @param {object} source metadata about where the resource is located
@@ -199,6 +241,10 @@ YUI.add('addon-rs-config', function(Y, NAME) {
if (mojitType && 'shared' !== mojitType) {
use = true;
}
+ // use application.{json,yaml,yml} in bundles as well
+ if ('bundle' === fs.rootType && 'application' === fs.basename) {
+ use = true;
+ }
if (!use) {
return;
}
@@ -237,7 +283,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
affinity: 'common',
selector: '*'
};
- if ('app' !== source.fs.rootType) {
+ if ('mojit' === source.fs.rootType) {
res.mojit = mojitType;
}
res.name = libpath.join(source.fs.subDir, baseParts.join('.'));
@@ -36,16 +36,10 @@ YUI.add('addon-rs-selector', function(Y, NAME) {
* @return {nothing}
*/
initializer: function(config) {
- var dims,
- json;
this.appRoot = config.appRoot;
this.mojitoRoot = config.mojitoRoot;
- dims = config.host.config.getDimensions();
- 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);
+ this._appConfigYCB = config.host.getAppConfigYCB();
this._poslCache = {}; // context: POSL
},
@@ -223,7 +223,15 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
this._validDims = this._parseValidDims(this.config.getDimensions());
this.validateContext(this._config.context);
this._fwConfig = this.config.readConfigSimple(this._libs.path.join(this._config.mojitoRoot, 'config.json'));
+
+ // We use this during preload() before we even know about all the
+ // application.jsons. This might be OK, since we'll have the real
+ // values during the second pass.
+ // In practice, this only applies to "mojitDirs" and "mojitsDirs",
+ // which can only be given in the app-level application.json.
this._appConfigStatic = this.getAppConfig({});
+
+ this._appConfigYCB = null; // libycb object
},
destructor: function() {},
@@ -349,13 +357,20 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
key,
ycb;
+ ctx = this.blendStaticContext(ctx);
key = JSON.stringify(ctx || {});
if (this._appConfigCache[key]) {
return JSON.parse(this._appConfigCache[key]);
}
- ycb = this.config.readConfigYCB(this._libs.path.join(this._config.root, 'application.json'), ctx);
+ if (this._appConfigYCB) {
+ ycb = this._appConfigYCB.read(ctx);
+ } else {
+ // This is generally only used to populate the initial this._appConfigStatic.
+ // After preload() we'll have this._appConfigYCB.
+ ycb = this.config.readConfigYCB(this._libs.path.join(this._config.root, 'application.json'), ctx);
+ }
appConfig = Y.mojito.util.blend(this._fwConfig.appConfigBase, this._config.appConfig);
appConfig = Y.mojito.util.blend(appConfig, ycb);
@@ -364,6 +379,19 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
return appConfig;
},
+
+
+ /**
+ * Returns the YCB library object for the application config.
+ * This is rarely what you want to use. getAppConfig() is a better choice.
+ * @method getAppConfigYCB
+ * @return {YCB} YCB library object for the application config
+ */
+ getAppConfigYCB: function() {
+ return this._appConfigYCB;
+ },
+
+
/**
* Preloads everything in the app, and as well pertinent parts of
* the framework.
@@ -374,10 +402,19 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
preload: function() {
// We need to do an initial sweep to find the resource store addons.
this.preloadResourceVersions();
+
+ // Now that we've found all the application.jsons, we can aggregate them.
+ this._initAppConfig();
+
+ // We need to rebuild _appConfigStatic -before- we load the addons,
+ // since they might (they do) cache the results of getStaticAppConfig().
+ this._appConfigStatic = this.getAppConfig({});
+
// And then use them.
this.loadAddons();
// Then, do another sweep so that the loaded addons can be used.
this.preloadResourceVersions();
+
this.makeResourceVersions();
this.resolveResourceVersions();
},
@@ -2081,6 +2118,36 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
});
Y.use.apply(Y, Object.keys(modules));
Y.applyConfig({ useSync: false });
+ },
+
+
+ /**
+ * Initializes the special multi-file YCB library for all the application.jsons.
+ * The object is used by getAppConfig().
+ * @private
+ * @method _initAppConfig
+ * @return {nothing}
+ */
+ _initAppConfig: function() {
+ var r,
+ res,
+ ress,
+ paths = [];
+
+ // TODO: detect conflicting peers (i.e. both application.json and application.yaml)
+
+ ress = this.getResourceVersions({type: 'config', name: 'application'});
+ for (r = 0; r < ress.length; r += 1) {
+ res = ress[r];
+ paths.push(res.source.fs.fullPath);
+ }
+ this._appConfigYCB = this.config.createMultipartYCB(paths);
+ if (!this._appConfigYCB) {
+ throw new Error("failed to create a YCB config from the following files:\n " + paths.join("\n "));
+ }
+ // New way to load means invalidating the whole cache.
+ // In practice, the cache likely only has the static version.
+ this._appConfigCache = {};
}
@@ -0,0 +1,7 @@
+[
+ {
+ "testKey1": "testVal1",
+ "testKey2": "testVal2",
+ "testKey3": "testVal3"
+ }
+]
@@ -0,0 +1,8 @@
+{
+ "foo": {
+ "settings": [ "master" ],
+ "testKey1": "testVal1",
+ "testKey2": "testVal2",
+ "testKey3": "testVal3"
+ }
+}
@@ -0,0 +1,8 @@
+[
+ {
+ "settings": [ "master" ],
+ "testKey1": "testVal1",
+ "testKey2": "testVal2",
+ "testKey3": "testVal3"
+ }
+]
@@ -0,0 +1,8 @@
+[
+ {
+ "settings": [ "master" ],
+ "testKey1": "testVal1-app2",
+ "testKey2": "testVal2-app2",
+ "testKey3": "testVal3-app2"
+ }
+]

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,13 @@
+{
+ "name": "root",
+ "version": "666.0.0",
+ "description": "root package",
+ "author": "Team Mojito (http://developer.yahoo.com/cocktails/mojito)",
+ "dependencies": {},
+ "main": ".",
+ "engines": {
+ "node": ">= 0.4.0",
+ "npm": ">= 1.0.0"
+ },
+ "devDependencies": {}
+}
Oops, something went wrong.

0 comments on commit d1390d7

Please sign in to comment.