{"id":20038529,"url":"https://github.com/yahoo/ycb-config","last_synced_at":"2025-10-23T18:06:33.345Z","repository":{"id":15259176,"uuid":"17988277","full_name":"yahoo/ycb-config","owner":"yahoo","description":"Configuration manager for Yahoo configuration bundles.","archived":false,"fork":false,"pushed_at":"2025-08-11T18:41:21.000Z","size":447,"stargazers_count":12,"open_issues_count":5,"forks_count":16,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-08-17T07:50:05.905Z","etag":null,"topics":["configuration-manager","javascript","web"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yahoo.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-03-21T17:33:28.000Z","updated_at":"2025-03-24T16:01:41.000Z","dependencies_parsed_at":"2023-10-24T16:44:41.213Z","dependency_job_id":"3478af9d-e45f-42a0-8d86-999d71f667fa","html_url":"https://github.com/yahoo/ycb-config","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/yahoo/ycb-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yahoo","download_url":"https://codeload.github.com/yahoo/ycb-config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-config/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270820760,"owners_count":24651529,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-manager","javascript","web"],"created_at":"2024-11-13T10:29:48.569Z","updated_at":"2025-10-23T18:06:28.303Z","avatar_url":"https://github.com/yahoo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YCB Config\n\n[![npm version](https://badge.fury.io/js/ycb-config.svg)](http://badge.fury.io/js/ycb-config)\n![Build Status](https://github.com/yahoo/ycb-config/actions/workflows/test.yml/badge.svg)\n\nA module that provides a simpler API to access and configure Yahoo Configuration Bundle files,\nregardless of the file format used. It also provides a caching layer to reduce the amount of\ncalls necessary to the `ycb` module for processing.\n\n## Overview\n\n### Goals\n\nYahoo Configuration Bundle files (known as YCB files) are configuration files used to store information on\nmultiple \"dimensions\" of an application. They can include configuration information for properties such as\nspecific locales, languages, device types, environments (development vs. production), and more.\n\nThe YCB Config module helps to provide a better interface for reading important information from those files.\nIt provides a normalized way of accessing those files regardless of what file format (JSON, YAML, etc.) they're in.\nAnd it provides a caching layer so that duplicate reads don't need to re-process the entire configuration object.\n\n### Installation\n\nInstall using npm:\n\n```shell\n$ npm install ycb-config\n```\n\n## Usage\n\nTo get started, `require` the `ycb-config` module and instantiate it:\n\n```js\nvar ConfigHelper = require('ycb-config'),\n    helper = new ConfigHelper();\n```\n\nThe following methods are then exposed through the `helper` object:\n\n## Methods\n\n#### `helper.addConfig(bundleName, configName, path, [callback])`\n\nExample:\n\n```js\nhelper.addConfig('homepage', 'weather-widget', 'config/application.json', function (err, config) {\n    /**\n     * `config` contains the configuration you just added as a JavaScript object\n     * Properties within it will vary depending on your configuration file.\n     */\n});\n```\n\nYCB Config allows you to register a single configuration file with two properties:\n\n- A `bundle` name, which references the bundle of CSS, JavaScript, and other assets involved with a single\n  modular portion of a web page.\n\n- A `config` name, which is just a simple name that we can use to reference that configuration object, rather\n  than using the full file path name.\n\nThis needs to be done for every configuration file that you plan on accessing through YCB Config.\n\n#### `helper.read(bundleName, configName, context, callback)`\n\nExample:\n\n```js\n// This contextual information is usually obtained from some custom middleware in your application.\nvar context = {\n    device: 'iphone',\n    locale: 'en-US',\n    bucket: 'new-feature-x',\n};\n\n// This requires that the config we're reading has already been added through `addConfig`.\nhelper.read('homepage', 'weather-widget', context, function (err, config) {\n    /**\n     * The `config` object now contains the correct configuration settings for\n     * our context above.  You can use it to render a template correctly for an\n     * iPhone, with the right localization settings for the US, and with the new\n     * feature you're bucket testing for.\n     */\n});\n```\n\nYCB Config lets you read the configuration you've specified with the dimensions that you've provided through a\ncontext object. The context object is always generated per request, and through custom middleware you write.\n\n`read` will merge all of the matched configuration selectors into a single object that you can use. What\nthat means is that the context:\n\n```js\n{\n    'device': 'iphone',\n    'locale': 'en-US'\n}\n```\n\nIt will match the configuration that you specify for just:\n\n```js\n{\n    'device': 'iphone'\n}\n```\n\nAs well as a more specific config for both:\n\n```js\n{\n    'device': 'iphone',\n    'locale': 'en-US'\n}\n```\n\nIt works a lot like CSS selectors, where a more specific config setting will override a\nless specific config setting.\n\n#### `helper.readNoMerge(bundleName, configName, context, callback)`\n\nExample:\n\n```js\n// This contextual information is usually obtained from some custom middleware in your application.\nvar context = {\n    device: 'iphone',\n    locale: 'en-US',\n    bucket: 'new-feature-x',\n};\n\n// This requires that the config we're reading has already been added through `addConfig`.\nhelper.readNoMerge('homepage', 'weather-widget', context, function (err, configs) {\n    /**\n     * The `configs` variable now contains an array of configuration settings, based on\n     * the individual selectors, from most specific to least specific.\n     *\n     * Like before, you can use them to render a template correctly for an\n     * iPhone, with the right localization settings for the US, and with the new\n     * feature you're bucket testing for.\n     *\n     * This time, though, it's up to you to merge the individual configs instead of having\n     * them automatically merged for you.\n     */\n});\n```\n\nYCB Config lets you read the configuration you've specified with the dimensions that you've provided through a\ncontext object. The context object is always generated per request, and through custom middleware you write.\n\n`readNoMerge` will not merge all of the matched configuration selectors into a single object, but instead,\nprovide all of them as individual objects within an array. It's up to the developer to determine how they\nwould like to properly handle all of the individual configuration settings with the current context.\n\n#### `helper.readDimensions(callback)`\n\nExample:\n\n```js\n// This requires that the config we're reading has already been added through `addConfig`\nhelper.readDimensions(function (err, dimensions) {\n    /**\n     * The `dimensions` variable contains an array of objects containing all of the possible\n     * selectors that can be used to contextualize a request that's coming in.\n     * See https://github.com/yahoo/ycb/blob/master/examples/full/dimensions.json\n     * for an example of what this could look like.\n     */\n});\n```\n\nYCB Config lets you read just the dimensions that are available for you to contextualize a request that's\ncoming in. This can be an array of properties such as device type, language, feature bucket, or more.\n\n### Promises\n\nThe following methods do not require a `callback` parameter, they will return Promise so that you can use chainable methods (such as` then` and `catch`) or` async` and `await` to handle asynchronous operations.\n\n#### `helper.promises.addConfig(bundleName, configName, path)`\n\nExample:\n\n```js\nhelper.promises.addConfig('homepage', 'weather-widget', 'config/application.json').then(function (config) {\n    /**\n     * `config` contains the configuration you just added as a JavaScript object\n     * Properties within it will vary depending on your configuration file.\n     */\n});\n```\n\n#### `helper.promises.read(bundleName, configName, context)`\n\nExample:\n\n```js\n// This contextual information is usually obtained from some custom middleware in your application.\nvar context = {\n    device: 'iphone',\n    locale: 'en-US',\n    bucket: 'new-feature-x',\n};\n\n// This requires that the config we're reading has already been added through `addConfig`.\nhelper.promises.read('homepage', 'weather-widget', context).then(function (config) {\n    /**\n     * The `config` object now contains the correct configuration settings for\n     * our context above.  You can use it to render a template correctly for an\n     * iPhone, with the right localization settings for the US, and with the new\n     * feature you're bucket testing for.\n     */\n});\n```\n\n#### `helper.promises.readNoMerge(bundleName, configName, context)`\n\nExample:\n\n```js\n// This contextual information is usually obtained from some custom middleware in your application.\nvar context = {\n    device: 'iphone',\n    locale: 'en-US',\n    bucket: 'new-feature-x',\n};\n\n// This requires that the config we're reading has already been added through `addConfig`.\nhelper.readNoMerge('homepage', 'weather-widget', context).then(function (configs) {\n    /**\n     * The `configs` variable now contains an array of configuration settings, based on\n     * the individual selectors, from most specific to least specific.\n     *\n     * Like before, you can use them to render a template correctly for an\n     * iPhone, with the right localization settings for the US, and with the new\n     * feature you're bucket testing for.\n     *\n     * This time, though, it's up to you to merge the individual configs instead of having\n     * them automatically merged for you.\n     */\n});\n```\n\n#### `helper.promises.readDimensions()`\n\nExample:\n\n```js\n// This requires that the config we're reading has already been added through `addConfig`\nhelper.promises.readDimensions.then(function (dimensions) {\n    /**\n     * The `dimensions` variable contains an array of objects containing all of the possible\n     * selectors that can be used to contextualize a request that's coming in.\n     * See https://github.com/yahoo/ycb/blob/master/examples/full/dimensions.json\n     * for an example of what this could look like.\n     */\n});\n```\n\n## Scheduled Configs\n\nTo support scheduled configs as described in [ycb](https://github.com/yahoo/ycb) ycb-config must be set to time aware mode via option flag and the time must be passed as a special dimension of the context when in this mode.\n\n```\nlet helper = new ConfigHelper({timeAware: true});\nlet context = req.context;\ncontext.time = Date.now(); //{device: 'mobile', time: 1573235678929}\nhelper.read(bundle, config, context, callback);\n```\n\nThe time value in the context should be a millisecond timestamp. To use a custom time dimension\nit may specified asn an option:`new ConfigHelper({timeDimension: 'my-time-key'})`.\n\n## License\n\nThis software is free to use under the Yahoo Inc. BSD license.\nSee the [LICENSE file][] for license text and copyright information.\n\n[license file]: https://github.com/yahoo/ycb-config/blob/master/LICENSE.txt\n\n## Contribute\n\nSee the [CONTRIBUTING.md file][] for info.\n\n[contributing.md file]: https://github.com/yahoo/ycb-config/blob/master/CONTRIBUTING.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahoo%2Fycb-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyahoo%2Fycb-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahoo%2Fycb-config/lists"}