"use strict"; // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under // Secretary of Defense (Personnel & Readiness). // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software distributed under the License // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express // or implied. See the License for the specific language governing permissions and limitations under // the License. /// vwf/configuration maintains the runtime configuration settings. A set of fixed factory defaults /// cascade into instance settings and appear as the active configuration. /// /// @module vwf/configuration define( function() { var exports = Object.create( Object.prototype, { /// The factory default settings. /// /// The factory settings are constant, and this property returns a copy to prevent /// modifications. Factory settings are paritioned by environment with default settings that /// apply to all environments and additional settings for specific environments, typically /// "production", "development", and "testing". For example: /// /// { /// default: { alpha: 1, beta: 2, gamma: 3 }, /// production: { alpha: 101 }, /// development: { beta: 222, gamma: 3000 }, /// testing: { }, /// } factory: { get: function() { return merge( {}, factory ); } }, // -- instance ----------------------------------------------------------------------------- /// Set or get the instance settings. The instance settings apply to the active environment /// and override the factory settings. For example: /// /// { /// beta: 222, /// gamma: 3000, /// delta: false, /// } instance: { set: function( value ) { instance = typeof value == "object" && value != null ? value : {}; update(); }, get: function() { return instance; } }, // -- active ------------------------------------------------------------------------------- /// The computed configuration for the environment. /// /// The active configuration is the result of a cascade of the factory default settings, /// factory settings for the active environment, and the instance settings. Changes to the /// configuration update this object in place without invalidating references to it. active: { get: function() { return active; } }, // -- environment -------------------------------------------------------------------------- /// The name of the active environment. environment: { set: function( value ) { environment = factory[value] ? value : "default"; update(); }, get: function() { return environment; } }, // -- changed ------------------------------------------------------------------------------ /// Register a notification function to be called when the configuration in active changes. /// /// @param {Function} callback /// The function to call, invoked as callback( active ). /// @param {Object} [context] /// The value of *this* in the call to callback. If context is not provided, *this* will /// be the configuration module. changed: { value: function( callback, context ) { callbacks.push( { callback: callback, context: context || this } ); }, }, } ); // == Private ================================================================================== /// Update the cascade. function update() { // Clear active so that we may update it in place. This preserves any existing references. Object.keys( active ).forEach( function( key ) { delete active[key]; } ); // Merge the factory defaults and the instance settings into the active configuration. merge( active, factory.default, factory[environment] || {}, instance ); // Call the notification callbacks. callbacks.forEach( function( callback ) { callback.callback.call( callback.context, active ); }, this ); } /// Merge fields from the `source` objects into `target`. function merge( target /* [, source1 [, source2 ... ] ] */ ) { for ( var index = 1; index < arguments.length; index++ ) { var source = arguments[index]; Object.keys( source ).forEach( function( key ) { target[key] = source[key]; } ); } return target; } // -- factory ---------------------------------------------------------------------------------- /// Factory default configurations. var factory = { /// Default configuration for all environments. default: { "log-level": "warn", // logger threshold "random-seed": +new Date, // pseudorandom number generator seed "randomize-ids": false, // randomize IDs to discourage assumptions about ID allocation "humanize-ids": false, // append recognizable strings to node IDs "preserve-script-closures": false, // retain method/event closures by not serializing functions (breaks replication, persistence) "load-timeout": 10, // resource load timeout in seconds }, /// Changes for production environments. production: { "load-timeout": 60, }, /// Changes for development environments. development: { "log-level": "info", "randomize-ids": true, "humanize-ids": true, "load-timeout": 30, }, /// Changes for testing environments. testing: { "random-seed": window.location.href, // make the random sequence repeatable }, }; // -- instance --------------------------------------------------------------------------------- /// Configuration overrides for the current instance. var instance = {}; // -- active ----------------------------------------------------------------------------------- /// The computed configuration. var active = {}; // -- environment ------------------------------------------------------------------------------ /// Name of the active environment. var environment = require.toUrl( "dummy" ).indexOf( "../lib/" ) === 0 ? "testing" : "development"; // -- callbacks -------------------------------------------------------------------------------- /// Update callbacks. var callbacks = []; // Force the first update. exports.instance = exports.instance; // Return the module. return exports; } );