{"action":"created","comment":{"url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/comments/78776414","id":78776414,"diff_hunk":"@@ -351,10 +351,131 @@ practice for modules to claim their own area in the configuration object is to\n insert their default configuration object using a key that either matches their\n module name or that matches their module name minus any `bedrock-` prefix. For\n example, the [bedrock-server][] module's specific configuration object can be\n-found under `bedrock.config.server`. Modules may define whatever configuration\n+found under `bedrock.config.server`. A `megacorp-feature` module would be found\n+under `bedrock['megacorp-feature']`. Modules may define whatever configuration\n variables they want to using whatever format is appropriate for their own\n use.\n \n+The `bedrock.util` module has helpers to setup configurations, and in\n+particular, dynamic computed configurations. Computed values can help to\n+simplify dependency issues by allowing values to be computed at runtime from a\n+function or string template. (Note there is a small cost with computed config\n+values which could be important depending on the use case.)\n+\n+`bedrock.util.Config` creates a wrapper around a config object and optional\n+options. A common setup could look like the following.\n+\n+```js\n+// an empty config object\n+let config = {};\n+// common options\n+let options = {\n+  // the config\n+  config: config\n+  // local vars used during string template evaluation\n+  locals: config\n+};\n+// wrap the config\n+let c = new bedrock.util.Config(config, options);\n+```\n+\n+Bedrock provides a shared wrapper around the common `bedrock.config` as\n+`bedrock.util.config`.\n+\n+To do simple sets of config data, use the `set()` API.\n+\n+```js\n+let c = bedrock.util.config;\n+// set a config variable with a path\n+// path components are created as needed\n+c.set('server.port', 8443);\n+// config is now {\"server\": {\"port\": 8443}}\n+```\n+\n+Normal code and the config API can be mixed. A useful helper is `require()`.\n+This call lets you simplify ensuring a full object path exists before setting\n+data. Objects in the path are created as needed.\n+\n+```js\n+// create container object if needed\n+c.require('accounts.admin');\n+// the config is just a normal object\n+config.accounts.admin.name = \"Ima Admin\";\n+c.set('accounts.admin.id', 1);\n+// the config object is returned from require()\n+let account123 = c.require('accounts.account123');\n+account123.id = 123;\n+account123.name = \"Account 123\";\n+```\n+\n+Computed config values using the `setComputed()` API add on a much more\n+powerful feature where values will be calculated at runtime.\n+\n+```js\n+// get the Config wrapper for the default bedrock.config\n+var c = bedrock.util.config;\n+// set static values\n+c.set('server.port', 8443);\n+c.set('server.domain', 'bedrock.dev');\n+// set a computed value that uses values from the main config\n+c.setComputed('server.host', () => {\n+  return config.server.domain + ':' + config.server.port;\n+});\n+console.log(config.server.host); // \"bedrock.dev:8443\"\n+```\n+\n+The logic for a computed value can be any normal code.\n+\n+```js\n+c.setComputed('server.host', () => {\n+  // only add the port if it's not the well known default\n+  if(config.server.port !== 443) {\n+    return config.server.domain + ':' + config.server.port;\n+  }\n+  return config.server.domain;\n+});\n+```\n+\n+`setComputed()` can be verbose. a wrapper can be created using the standard\n+`bind()` functionality. A helpper called `computer()` will do this for you.\n+```js\n+let cc = bedrock.config.computer();\n+cc('server.host', () => {\n+  // only add the port if it's not the well known default\n+  if(config.server.port !== 443) {\n+    return config.server.domain + ':' + config.server.port;\n+  }\n+  return config.server.domain;\n+});\n+```\n+\n+Copmuted values can also be created with string templates.","path":"README.md","position":103,"original_position":103,"commit_id":"f869fad0f0363461ba80d4251beddabacfffe61d","original_commit_id":"f869fad0f0363461ba80d4251beddabacfffe61d","user":{"login":"dlongley","id":168137,"avatar_url":"https://avatars.githubusercontent.com/u/168137?v=3","gravatar_id":"","url":"https://api.github.com/users/dlongley","html_url":"https://github.com/dlongley","followers_url":"https://api.github.com/users/dlongley/followers","following_url":"https://api.github.com/users/dlongley/following{/other_user}","gists_url":"https://api.github.com/users/dlongley/gists{/gist_id}","starred_url":"https://api.github.com/users/dlongley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dlongley/subscriptions","organizations_url":"https://api.github.com/users/dlongley/orgs","repos_url":"https://api.github.com/users/dlongley/repos","events_url":"https://api.github.com/users/dlongley/events{/privacy}","received_events_url":"https://api.github.com/users/dlongley/received_events","type":"User","site_admin":false},"body":"`with lodash-style string templates.`","created_at":"2016-09-14T15:46:57Z","updated_at":"2016-09-14T15:46:57Z","html_url":"https://github.com/digitalbazaar/bedrock/pull/6#discussion_r78776414","pull_request_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6","_links":{"self":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/comments/78776414"},"html":{"href":"https://github.com/digitalbazaar/bedrock/pull/6#discussion_r78776414"},"pull_request":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6"}}},"pull_request":{"url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6","id":85159963,"html_url":"https://github.com/digitalbazaar/bedrock/pull/6","diff_url":"https://github.com/digitalbazaar/bedrock/pull/6.diff","patch_url":"https://github.com/digitalbazaar/bedrock/pull/6.patch","issue_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/6","number":6,"state":"open","locked":false,"title":"Computed config","user":{"login":"davidlehn","id":109587,"avatar_url":"https://avatars.githubusercontent.com/u/109587?v=3","gravatar_id":"","url":"https://api.github.com/users/davidlehn","html_url":"https://github.com/davidlehn","followers_url":"https://api.github.com/users/davidlehn/followers","following_url":"https://api.github.com/users/davidlehn/following{/other_user}","gists_url":"https://api.github.com/users/davidlehn/gists{/gist_id}","starred_url":"https://api.github.com/users/davidlehn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidlehn/subscriptions","organizations_url":"https://api.github.com/users/davidlehn/orgs","repos_url":"https://api.github.com/users/davidlehn/repos","events_url":"https://api.github.com/users/davidlehn/events{/privacy}","received_events_url":"https://api.github.com/users/davidlehn/received_events","type":"User","site_admin":false},"body":"RFC: Update computed config API using a wrapper design.\r\nThere are README docs but not yet API docs.\r\nOld API is not yet removed.","created_at":"2016-09-14T03:07:28Z","updated_at":"2016-09-14T15:46:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5849fb64ea1ef0d0e99db7fa0f974f235d09261d","assignee":{"login":"dlongley","id":168137,"avatar_url":"https://avatars.githubusercontent.com/u/168137?v=3","gravatar_id":"","url":"https://api.github.com/users/dlongley","html_url":"https://github.com/dlongley","followers_url":"https://api.github.com/users/dlongley/followers","following_url":"https://api.github.com/users/dlongley/following{/other_user}","gists_url":"https://api.github.com/users/dlongley/gists{/gist_id}","starred_url":"https://api.github.com/users/dlongley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dlongley/subscriptions","organizations_url":"https://api.github.com/users/dlongley/orgs","repos_url":"https://api.github.com/users/dlongley/repos","events_url":"https://api.github.com/users/dlongley/events{/privacy}","received_events_url":"https://api.github.com/users/dlongley/received_events","type":"User","site_admin":false},"assignees":[{"login":"dlongley","id":168137,"avatar_url":"https://avatars.githubusercontent.com/u/168137?v=3","gravatar_id":"","url":"https://api.github.com/users/dlongley","html_url":"https://github.com/dlongley","followers_url":"https://api.github.com/users/dlongley/followers","following_url":"https://api.github.com/users/dlongley/following{/other_user}","gists_url":"https://api.github.com/users/dlongley/gists{/gist_id}","starred_url":"https://api.github.com/users/dlongley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dlongley/subscriptions","organizations_url":"https://api.github.com/users/dlongley/orgs","repos_url":"https://api.github.com/users/dlongley/repos","events_url":"https://api.github.com/users/dlongley/events{/privacy}","received_events_url":"https://api.github.com/users/dlongley/received_events","type":"User","site_admin":false},{"login":"mattcollier","id":902041,"avatar_url":"https://avatars.githubusercontent.com/u/902041?v=3","gravatar_id":"","url":"https://api.github.com/users/mattcollier","html_url":"https://github.com/mattcollier","followers_url":"https://api.github.com/users/mattcollier/followers","following_url":"https://api.github.com/users/mattcollier/following{/other_user}","gists_url":"https://api.github.com/users/mattcollier/gists{/gist_id}","starred_url":"https://api.github.com/users/mattcollier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattcollier/subscriptions","organizations_url":"https://api.github.com/users/mattcollier/orgs","repos_url":"https://api.github.com/users/mattcollier/repos","events_url":"https://api.github.com/users/mattcollier/events{/privacy}","received_events_url":"https://api.github.com/users/mattcollier/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6/commits","review_comments_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6/comments","review_comment_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/comments{/number}","comments_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/6/comments","statuses_url":"https://api.github.com/repos/digitalbazaar/bedrock/statuses/f869fad0f0363461ba80d4251beddabacfffe61d","head":{"label":"digitalbazaar:computed-config","ref":"computed-config","sha":"f869fad0f0363461ba80d4251beddabacfffe61d","user":{"login":"digitalbazaar","id":167436,"avatar_url":"https://avatars.githubusercontent.com/u/167436?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalbazaar","html_url":"https://github.com/digitalbazaar","followers_url":"https://api.github.com/users/digitalbazaar/followers","following_url":"https://api.github.com/users/digitalbazaar/following{/other_user}","gists_url":"https://api.github.com/users/digitalbazaar/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalbazaar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalbazaar/subscriptions","organizations_url":"https://api.github.com/users/digitalbazaar/orgs","repos_url":"https://api.github.com/users/digitalbazaar/repos","events_url":"https://api.github.com/users/digitalbazaar/events{/privacy}","received_events_url":"https://api.github.com/users/digitalbazaar/received_events","type":"Organization","site_admin":false},"repo":{"id":27559729,"name":"bedrock","full_name":"digitalbazaar/bedrock","owner":{"login":"digitalbazaar","id":167436,"avatar_url":"https://avatars.githubusercontent.com/u/167436?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalbazaar","html_url":"https://github.com/digitalbazaar","followers_url":"https://api.github.com/users/digitalbazaar/followers","following_url":"https://api.github.com/users/digitalbazaar/following{/other_user}","gists_url":"https://api.github.com/users/digitalbazaar/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalbazaar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalbazaar/subscriptions","organizations_url":"https://api.github.com/users/digitalbazaar/orgs","repos_url":"https://api.github.com/users/digitalbazaar/repos","events_url":"https://api.github.com/users/digitalbazaar/events{/privacy}","received_events_url":"https://api.github.com/users/digitalbazaar/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/digitalbazaar/bedrock","description":"Bedrock: A core foundation for rich Web applications.","fork":false,"url":"https://api.github.com/repos/digitalbazaar/bedrock","forks_url":"https://api.github.com/repos/digitalbazaar/bedrock/forks","keys_url":"https://api.github.com/repos/digitalbazaar/bedrock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/digitalbazaar/bedrock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/digitalbazaar/bedrock/teams","hooks_url":"https://api.github.com/repos/digitalbazaar/bedrock/hooks","issue_events_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/events{/number}","events_url":"https://api.github.com/repos/digitalbazaar/bedrock/events","assignees_url":"https://api.github.com/repos/digitalbazaar/bedrock/assignees{/user}","branches_url":"https://api.github.com/repos/digitalbazaar/bedrock/branches{/branch}","tags_url":"https://api.github.com/repos/digitalbazaar/bedrock/tags","blobs_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/refs{/sha}","trees_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/digitalbazaar/bedrock/statuses/{sha}","languages_url":"https://api.github.com/repos/digitalbazaar/bedrock/languages","stargazers_url":"https://api.github.com/repos/digitalbazaar/bedrock/stargazers","contributors_url":"https://api.github.com/repos/digitalbazaar/bedrock/contributors","subscribers_url":"https://api.github.com/repos/digitalbazaar/bedrock/subscribers","subscription_url":"https://api.github.com/repos/digitalbazaar/bedrock/subscription","commits_url":"https://api.github.com/repos/digitalbazaar/bedrock/commits{/sha}","git_commits_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/commits{/sha}","comments_url":"https://api.github.com/repos/digitalbazaar/bedrock/comments{/number}","issue_comment_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/comments{/number}","contents_url":"https://api.github.com/repos/digitalbazaar/bedrock/contents/{+path}","compare_url":"https://api.github.com/repos/digitalbazaar/bedrock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/digitalbazaar/bedrock/merges","archive_url":"https://api.github.com/repos/digitalbazaar/bedrock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/digitalbazaar/bedrock/downloads","issues_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues{/number}","pulls_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls{/number}","milestones_url":"https://api.github.com/repos/digitalbazaar/bedrock/milestones{/number}","notifications_url":"https://api.github.com/repos/digitalbazaar/bedrock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/digitalbazaar/bedrock/labels{/name}","releases_url":"https://api.github.com/repos/digitalbazaar/bedrock/releases{/id}","deployments_url":"https://api.github.com/repos/digitalbazaar/bedrock/deployments","created_at":"2014-12-04T20:57:14Z","updated_at":"2016-08-16T06:06:50Z","pushed_at":"2016-09-14T03:07:28Z","git_url":"git://github.com/digitalbazaar/bedrock.git","ssh_url":"git@github.com:digitalbazaar/bedrock.git","clone_url":"https://github.com/digitalbazaar/bedrock.git","svn_url":"https://github.com/digitalbazaar/bedrock","homepage":"","size":2721,"stargazers_count":17,"watchers_count":17,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":17,"default_branch":"master"}},"base":{"label":"digitalbazaar:master","ref":"master","sha":"25016a50022556f0aa2b137030f99fef93064f89","user":{"login":"digitalbazaar","id":167436,"avatar_url":"https://avatars.githubusercontent.com/u/167436?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalbazaar","html_url":"https://github.com/digitalbazaar","followers_url":"https://api.github.com/users/digitalbazaar/followers","following_url":"https://api.github.com/users/digitalbazaar/following{/other_user}","gists_url":"https://api.github.com/users/digitalbazaar/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalbazaar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalbazaar/subscriptions","organizations_url":"https://api.github.com/users/digitalbazaar/orgs","repos_url":"https://api.github.com/users/digitalbazaar/repos","events_url":"https://api.github.com/users/digitalbazaar/events{/privacy}","received_events_url":"https://api.github.com/users/digitalbazaar/received_events","type":"Organization","site_admin":false},"repo":{"id":27559729,"name":"bedrock","full_name":"digitalbazaar/bedrock","owner":{"login":"digitalbazaar","id":167436,"avatar_url":"https://avatars.githubusercontent.com/u/167436?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalbazaar","html_url":"https://github.com/digitalbazaar","followers_url":"https://api.github.com/users/digitalbazaar/followers","following_url":"https://api.github.com/users/digitalbazaar/following{/other_user}","gists_url":"https://api.github.com/users/digitalbazaar/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalbazaar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalbazaar/subscriptions","organizations_url":"https://api.github.com/users/digitalbazaar/orgs","repos_url":"https://api.github.com/users/digitalbazaar/repos","events_url":"https://api.github.com/users/digitalbazaar/events{/privacy}","received_events_url":"https://api.github.com/users/digitalbazaar/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/digitalbazaar/bedrock","description":"Bedrock: A core foundation for rich Web applications.","fork":false,"url":"https://api.github.com/repos/digitalbazaar/bedrock","forks_url":"https://api.github.com/repos/digitalbazaar/bedrock/forks","keys_url":"https://api.github.com/repos/digitalbazaar/bedrock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/digitalbazaar/bedrock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/digitalbazaar/bedrock/teams","hooks_url":"https://api.github.com/repos/digitalbazaar/bedrock/hooks","issue_events_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/events{/number}","events_url":"https://api.github.com/repos/digitalbazaar/bedrock/events","assignees_url":"https://api.github.com/repos/digitalbazaar/bedrock/assignees{/user}","branches_url":"https://api.github.com/repos/digitalbazaar/bedrock/branches{/branch}","tags_url":"https://api.github.com/repos/digitalbazaar/bedrock/tags","blobs_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/refs{/sha}","trees_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/digitalbazaar/bedrock/statuses/{sha}","languages_url":"https://api.github.com/repos/digitalbazaar/bedrock/languages","stargazers_url":"https://api.github.com/repos/digitalbazaar/bedrock/stargazers","contributors_url":"https://api.github.com/repos/digitalbazaar/bedrock/contributors","subscribers_url":"https://api.github.com/repos/digitalbazaar/bedrock/subscribers","subscription_url":"https://api.github.com/repos/digitalbazaar/bedrock/subscription","commits_url":"https://api.github.com/repos/digitalbazaar/bedrock/commits{/sha}","git_commits_url":"https://api.github.com/repos/digitalbazaar/bedrock/git/commits{/sha}","comments_url":"https://api.github.com/repos/digitalbazaar/bedrock/comments{/number}","issue_comment_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues/comments{/number}","contents_url":"https://api.github.com/repos/digitalbazaar/bedrock/contents/{+path}","compare_url":"https://api.github.com/repos/digitalbazaar/bedrock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/digitalbazaar/bedrock/merges","archive_url":"https://api.github.com/repos/digitalbazaar/bedrock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/digitalbazaar/bedrock/downloads","issues_url":"https://api.github.com/repos/digitalbazaar/bedrock/issues{/number}","pulls_url":"https://api.github.com/repos/digitalbazaar/bedrock/pulls{/number}","milestones_url":"https://api.github.com/repos/digitalbazaar/bedrock/milestones{/number}","notifications_url":"https://api.github.com/repos/digitalbazaar/bedrock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/digitalbazaar/bedrock/labels{/name}","releases_url":"https://api.github.com/repos/digitalbazaar/bedrock/releases{/id}","deployments_url":"https://api.github.com/repos/digitalbazaar/bedrock/deployments","created_at":"2014-12-04T20:57:14Z","updated_at":"2016-08-16T06:06:50Z","pushed_at":"2016-09-14T03:07:28Z","git_url":"git://github.com/digitalbazaar/bedrock.git","ssh_url":"git@github.com:digitalbazaar/bedrock.git","clone_url":"https://github.com/digitalbazaar/bedrock.git","svn_url":"https://github.com/digitalbazaar/bedrock","homepage":"","size":2721,"stargazers_count":17,"watchers_count":17,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6"},"html":{"href":"https://github.com/digitalbazaar/bedrock/pull/6"},"issue":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/issues/6"},"comments":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/issues/6/comments"},"review_comments":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6/comments"},"review_comment":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/pulls/6/commits"},"statuses":{"href":"https://api.github.com/repos/digitalbazaar/bedrock/statuses/f869fad0f0363461ba80d4251beddabacfffe61d"}}}}
{"actor":{"display_login":"dlongley"}}