configuration.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/configuration maintains the runtime configuration settings. A set of fixed factory defaults
  15. /// cascade into instance settings and appear as the active configuration.
  16. ///
  17. /// @module vwf/configuration
  18. define( function() {
  19. var exports = Object.create( Object.prototype, {
  20. /// The factory default settings.
  21. ///
  22. /// The factory settings are constant, and this property returns a copy to prevent
  23. /// modifications. Factory settings are paritioned by environment with default settings that
  24. /// apply to all environments and additional settings for specific environments, typically
  25. /// "production", "development", and "testing". For example:
  26. ///
  27. /// {
  28. /// default: { alpha: 1, beta: 2, gamma: 3 },
  29. /// production: { alpha: 101 },
  30. /// development: { beta: 222, gamma: 3000 },
  31. /// testing: { },
  32. /// }
  33. factory: {
  34. get: function() {
  35. return merge( {}, factory );
  36. }
  37. },
  38. // -- instance -----------------------------------------------------------------------------
  39. /// Set or get the instance settings. The instance settings apply to the active environment
  40. /// and override the factory settings. For example:
  41. ///
  42. /// {
  43. /// beta: 222,
  44. /// gamma: 3000,
  45. /// delta: false,
  46. /// }
  47. instance: {
  48. set: function( value ) {
  49. instance = typeof value == "object" && value != null ? value : {};
  50. update();
  51. },
  52. get: function() {
  53. return instance;
  54. }
  55. },
  56. // -- active -------------------------------------------------------------------------------
  57. /// The computed configuration for the environment.
  58. ///
  59. /// The active configuration is the result of a cascade of the factory default settings,
  60. /// factory settings for the active environment, and the instance settings. Changes to the
  61. /// configuration update this object in place without invalidating references to it.
  62. active: {
  63. get: function() {
  64. return active;
  65. }
  66. },
  67. // -- environment --------------------------------------------------------------------------
  68. /// The name of the active environment.
  69. environment: {
  70. set: function( value ) {
  71. environment = factory[value] ? value : "default";
  72. update();
  73. },
  74. get: function() {
  75. return environment;
  76. }
  77. },
  78. // -- changed ------------------------------------------------------------------------------
  79. /// Register a notification function to be called when the configuration in active changes.
  80. ///
  81. /// @param {Function} callback
  82. /// The function to call, invoked as callback( active ).
  83. /// @param {Object} [context]
  84. /// The value of *this* in the call to callback. If context is not provided, *this* will
  85. /// be the configuration module.
  86. changed: {
  87. value: function( callback, context ) {
  88. callbacks.push( { callback: callback, context: context || this } );
  89. },
  90. },
  91. } );
  92. // == Private ==================================================================================
  93. /// Update the cascade.
  94. function update() {
  95. // Clear active so that we may update it in place. This preserves any existing references.
  96. Object.keys( active ).forEach( function( key ) {
  97. delete active[key];
  98. } );
  99. // Merge the factory defaults and the instance settings into the active configuration.
  100. merge( active, factory.default, factory[environment] || {}, instance );
  101. // Call the notification callbacks.
  102. callbacks.forEach( function( callback ) {
  103. callback.callback.call( callback.context, active );
  104. }, this );
  105. }
  106. /// Merge fields from the `source` objects into `target`.
  107. function merge( target /* [, source1 [, source2 ... ] ] */ ) {
  108. for ( var index = 1; index < arguments.length; index++ ) {
  109. var source = arguments[index];
  110. Object.keys( source ).forEach( function( key ) {
  111. target[key] = source[key];
  112. } );
  113. }
  114. return target;
  115. }
  116. // -- factory ----------------------------------------------------------------------------------
  117. /// Factory default configurations.
  118. var factory = {
  119. /// Default configuration for all environments.
  120. default: {
  121. "log-level": "warn", // logger threshold
  122. "random-seed": +new Date, // pseudorandom number generator seed
  123. "randomize-ids": false, // randomize IDs to discourage assumptions about ID allocation
  124. "humanize-ids": false, // append recognizable strings to node IDs
  125. "preserve-script-closures": false, // retain method/event closures by not serializing functions (breaks replication, persistence)
  126. "load-timeout": 10, // resource load timeout in seconds
  127. },
  128. /// Changes for production environments.
  129. production: {
  130. "load-timeout": 60,
  131. },
  132. /// Changes for development environments.
  133. development: {
  134. "log-level": "info",
  135. "randomize-ids": true,
  136. "humanize-ids": true,
  137. "load-timeout": 30,
  138. },
  139. /// Changes for testing environments.
  140. testing: {
  141. "random-seed": window.location.href, // make the random sequence repeatable
  142. },
  143. };
  144. // -- instance ---------------------------------------------------------------------------------
  145. /// Configuration overrides for the current instance.
  146. var instance = {};
  147. // -- active -----------------------------------------------------------------------------------
  148. /// The computed configuration.
  149. var active = {};
  150. // -- environment ------------------------------------------------------------------------------
  151. /// Name of the active environment.
  152. var environment = require.toUrl( "dummy" ).indexOf( "../lib/" ) === 0 ?
  153. "testing" : "development";
  154. // -- callbacks --------------------------------------------------------------------------------
  155. /// Update callbacks.
  156. var callbacks = [];
  157. // Force the first update.
  158. exports.instance = exports.instance;
  159. // Return the module.
  160. return exports;
  161. } );