{"id":23440041,"url":"https://github.com/bassdman/feature-toggle-api","last_synced_at":"2026-02-28T17:02:03.566Z","repository":{"id":32551960,"uuid":"136755654","full_name":"bassdman/feature-toggle-api","owner":"bassdman","description":"Gives you advanced feature-toggle for any framework","archived":false,"fork":false,"pushed_at":"2025-01-28T05:45:47.000Z","size":894,"stargazers_count":16,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-25T15:52:17.739Z","etag":null,"topics":["api","feature-toggle","library"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bassdman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2018-06-09T20:28:07.000Z","updated_at":"2025-04-09T10:13:00.000Z","dependencies_parsed_at":"2024-06-19T00:14:02.464Z","dependency_job_id":"f05dae0a-c9f6-4a84-957c-8f7aeae0d4e7","html_url":"https://github.com/bassdman/feature-toggle-api","commit_stats":{"total_commits":73,"total_committers":3,"mean_commits":"24.333333333333332","dds":0.09589041095890416,"last_synced_commit":"6567ae52051bc4daa2d1b951909aac4c0f844b04"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bassdman/feature-toggle-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Ffeature-toggle-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Ffeature-toggle-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Ffeature-toggle-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Ffeature-toggle-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bassdman","download_url":"https://codeload.github.com/bassdman/feature-toggle-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bassdman%2Ffeature-toggle-api/sbom","scorecard":{"id":226958,"data":{"date":"2025-08-11","repo":{"name":"github.com/bassdman/feature-toggle-api","commit":"e5da85ad52ebffbab2ef66ae798e849d234e9a2f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/18 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T03:59:04.213Z","repository_id":32551960,"created_at":"2025-08-17T03:59:04.213Z","updated_at":"2025-08-17T03:59:04.213Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29943662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T13:49:17.081Z","status":"ssl_error","status_checked_at":"2026-02-28T13:48:50.396Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","feature-toggle","library"],"created_at":"2024-12-23T15:39:37.334Z","updated_at":"2026-02-28T17:02:03.517Z","avatar_url":"https://github.com/bassdman.png","language":"TypeScript","readme":"# feature-toggle-api\n\n\u003e Gives you advanced feature-toggle for any Framework\n\n[![npm version](https://img.shields.io/npm/v/feature-toggle-api.svg)](https://www.npmjs.com/package/feature-toggle-api)\n[![npm downloads](https://img.shields.io/npm/dt/feature-toggle-api.svg)](https://www.npmjs.com/package/feature-toggle-api)\n[![npm downloads](https://img.shields.io/github/license/mashape/apistatus.svg)](https://www.npmjs.com/package/feature-toggle-api)\n## Install\n\n``` shell\n    npm install feature-toggle-api --save\n```\n\n - [Quicklink to the API](#api-description)\n - [Quicklink to the HTML-Plugin](https://github.com/bassdman/feature-toggle-api/blob/master/src/plugins/htmlplugin/readme.md)\n - [Quicklink to the URL-Plugin](https://github.com/bassdman/feature-toggle-api/blob/master/src/plugins/urlplugin/readme.md)\n - [Quicklink to the vue-Plugin (package vue-feature-toggle)](https://github.com/bassdman/vue-feature-toggle)\n\n## The Problem\nImagine you have an onlineshop with an testmode and in multiple languages. \nOne part uses a html-template that looks like this:\n``` html\n\u003ccontent-area\u003e\n    \u003c!-- Show important debugging information for testmode --\u003e\n    \u003ctestmode-nav onload=\"showIf(testmode)\"\u003e\u003c/testmode-nav\u003e\n\n    \u003c!-- That's the old one, in a few days the new one, commented out here will be released \n        \u003cleft-nav-new\u003e\u003c/left-nav-new\u003e\n    --\u003e\n    \u003cleft-nav\u003e\u003c/left-nav\u003e\n\n    \u003c!-- Every shop has a slider with amazing foodinfo on the startpage--\u003e\n    \u003cdiv id=\"startpage-slider-de\" ref=\"food/bratwurst\" onload=\"showIf(shop=='de')\"\u003e...\u003c/div\u003e\n    \u003cdiv id=\"startpage-slider-en\" ref=\"food/fishnchips\" onload=\"showIf(shop=='en')\"\u003e...\u003c/div\u003e\n    \u003cdiv id=\"startpage-slider-fr\" ref=\"food/croissant\" onload=\"showIf(shop=='fr')\"\u003e...\u003c/div\u003e\n\n    \u003cfooter-new\u003e\u003c/footer-new\u003e\n    \u003c!-- \n    New footer just went live. When there are some problems, we rollback and comment out the new footer and uncomment the old one\n    \u003cfooter-old\u003e\u003c/footer-old\u003e --\u003e\n\u003c/content-area\u003e\n```\nIt's generally a bad idea to have visibility rules in the template. Of course, by refactoring the template a little bit the code will look better. \nBut that's not the point. The problem is: The view-logic is spread in .html and .js files and if the viewlogic changes, you have to change at least them. And all visibility rules are spread over the whole system.\nThat's not good.\n\n## The solution\nFeature-toggle. All View-Logic is placed in one place. This can be a config file, a webservice or a tool with a User Interface.\nWhen you want to change a visibility rule, for example \"Show feature XYZ also in the french shop\", you just have to update the config or add this info in an UI. And no developer is needed for it.\n\n\u003ca href=\"https://martinfowler.com/articles/feature-toggles.html\"\u003eRead the article from Martin Fowler about feature toggle for a better understanding.\u003c/a\u003e\n\n## The Usage\nLook in the example folder for working examples in HTML Templates.\n\n### Initialisation\nCreate a new project, type\n``` shell\n    npm install feature-toggle-api --save\n```\n\nUse it in your script\n``` javascript\nimport { useFeatureToggle } from \"feature-toggle-api\";\n\n//initialize it with your feature-flags\nconst feature = useFeatureToggle({      \n    a:true, \n});\n\nconsole.log(feature.isActive('a')); //true\nconsole.log(feature.isActive('c')); //false\n```\n\nYou use commonjs-scripts? Here we go:\n``` javascript\nconst { useFeatureToggle } = require(\"feature-toggle-api/dist/feature-toggle.cjs\");\n\n//initialize it with your feature-flags\nconst feature = useFeatureToggle({      \n    a:true, \n});\n\nconsole.log(feature.isActive('a')); //true\nconsole.log(feature.isActive('c')); //false\n```\n\n\nOr you want to include it as a scripttag? Here's a sample HTML-File. \n``` html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003ctitle\u003eBasic Feature-Toggle-API-Test\u003c/title\u003e\n    \u003cscript src=\"path/to/feature-toggle-api/dist/feature-toggle.umd.min.js\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv class=\"feature1\"\u003eThis is text from feature1\u003c/div\u003e\n    \u003cdiv class=\"feature2\"\u003eThis is text from feature2\u003c/div\u003e\n    \u003cscript\u003e\n        var api = useFeatureToggle({\n            feature1: true\n        });\n        var feature1Visible = api.isActive('feature1');\n        var feature2Visible = api.isActive('feature2');\n        \n        //here we could also use jquery or any other library,... The api has done its job.\n        if(!feature1Visible) document.querySelector(\".feature1\").style.display = 'none';\n        if(!feature2Visible) document.querySelector(\".feature2\").style.display = 'none';\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\n### Initialisation\nInitialisation is very simple\n```javascript\n//This api has already initialized some visiblity rules:\nvar api = useFeatureToggle({\n    feature1: true, //feature1 will be shown\n    feature2: false, //feature2 won't be shown,\n    // a rule can also be a function. important: it must return a boolean value; feature 3 would be shown\n    feature3: function(rule){return true;}, \n    feature4: true,\n    \"feature4:new\": false, //feature 4 will be shown - but if variant is new, it won't be. \n});\n\n//You could also write it like this:\nvar api = useFeatureToggle();\napi.setFlag('feature1',true);\napi.setFlag('feature2',false);\napi.setFlag('feature3',function(rule){return true});\napi.setFlag('feature4',true);\napi.setFlag('feature4','new',false);\n//only possible via functioncall: pass some data; maybe necessary in the listener\napi.setFlag('feature4','new',\"some custom data\",false);\n```\n\nImportant: A visibilityrule must not start with an underscore or $. Both is reserved. Attributes starting with an it are reserved for configuration settings.\n```javascript\n//This api has already initialized some visiblity rules:\nvar api = useFeatureToggle({\n    feature1: true,  //visibilityrule feature1 -\u003e true\n    plugins: true,   //visibilityrule plugins -\u003e true\n    _feature1: true, //_ is reserved for configuration (deprecated)-\u003e this attribute does nothing\n    _plugins: [],    //_ is reserved for configuration -\u003e add plugins (deprecated). use $plugins instead\n\n    $plugins: [],    //$ is reserved for configuration -\u003e add plugins\n});\n```\n\n### Features\nFor the next examples we will imagine, the properties are mapped to the visibility rules. (Btw, the [html-plugin](https://github.com/bassdman/feature-toggle-api/blob/master/src/plugins/htmlplugin/readme.md) does this for you ;)\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003c!-- Just imagine, the properties are matched to the visibility rules --\u003e\n    \u003cfeature name=\"feature1\"\u003eThis is \"Feature1\"\u003c/feature\u003e\n    \u003cfeature name=\"feature2\"\u003eThis is \"Feature2\"\u003c/feature\u003e\n    \u003cfeature name=\"feature2\" variant=\"new\"\u003eThis is \"Feature2\" with variant \"new\"\u003c/feature\u003e\n    \u003cfeature name=\"feature2\" variant=\"old\"\u003eThis \"Feature2\" with variant \"old\"\u003c/feature\u003e\n    \u003cfeature name=\"feature2\" variant=\"grumpfel\"\u003eThis \"Feature2\" with variant \"grumpfel\"\u003c/feature\u003e\n    \n    \u003cfeature name=\"feature3\" variant=\"old\" data=\"grumpfel\"\u003eThis \"Feature3\" with variant \"old\" has some Data.\u003c/feature\u003e\n    \u003cfeature name=\"feature3\" variant=\"new\" data=\"{'text':'grumpfel'}\"\u003eThis \"Feature3\" with variant \"old\" has some Data.\u003c/feature\u003e\n\u003c/div\u003e\n```\n#### Basic visibility\n```javascript\n// shows Feature1\n//Feature2 is not configured, so it will be hidden\napi.setFlag('feature1',true);\n\n//Remember: you can also wrap it in functions - but the example above is better to read\napi.setFlag('feature1',function ( rule) {\n        //here would be some more complex logic, in this example we keep it simple\n        return true;\n});\n```\n```javascript\n/* \n    shows all features with name feature2, in this case: \n    api.isActive('feature1') -\u003e return false\n    api.isActive('feature2') -\u003e return true\n    api.isActive('feature2','new') -\u003e return true\n    api.isActive('feature2','old') -\u003e return true\n    api.isActive('feature2','grumpfel') -\u003e return true\n    \n */\napi.setFlag('feature2', true);\n\n/*\n    This overwrites the rule above for \"feature2\", variant \"new\"    \n    api.isActive('feature1') -\u003e return false\n    api.isActive('feature2') -\u003e return true - because of rule above \n    api.isActive('feature2','new') -\u003e return false\n    api.isActive('feature2','old') -\u003e return true\n    api.isActive('feature2','grumpfel') -\u003e return true\n*/\napi.setFlag('feature2','new', false);\n```\n```javascript\n/*\n    feature.isActive('feature3','new','grumpfel'); //returns true\n    feature.isActive('feature3','new','grumpfelbu'); //returns false\n*/\napi.setFlag('feature3','new', function (rule) {\n     //rule.data could also be an object or whatever you want\n     //you could also use rule.name, rule.variant,...\n      return rule.data == \"grumpfel\";\n});\n```\n#### Default Visibility\nBored of writing the same visibility rule again and again? Use defaultFlag. This is the default-rule and will be overwritten by feature.setFlag() - rules.\n``` javascript\nfeature.setDefaultFlag(function(rule){\n    return true;\n});\n\nfeature.setFlag('feature2', 'new', function(rule){\n    return false;\n});\n/*\n    \"Feature2\", variant \"new\" is overwritten, all other features have the defaultFlag\n    api.isActive('feature1') -\u003e return true\n    api.isActive('feature2') -\u003e return true\n    api.isActive('feature2','new') -\u003e return false\n    api.isActive('feature2','old') -\u003e return true\n    api.isActive('feature2','grumpfel') -\u003e return true\n*/\n```\nYou already want to initialize it in the constructor? No Problem.\n```javascript\n    var api = useFeatureToggle({\n    _default: true, //default visibility always returns true; again: this could also be a function\n });\n```\n\n#### Required Visibility\nThis rule is always executed, before the other rules. When it returns false, the other rules are ignored.\n``` javascript\n/*\n   Imagine a config that is loaded via ajax. When the name is in the config, it returns true.\n   And this config looks like this: \n   var globalConfig = { \"feature2\" : true }\n*/\n\nfeature.setRequiredFlag(function(rule){\n    //In this case it returns true, when name == 'feture2'\n    return globalConfig[rule.name] === true;\n});\n\n/*\n  feature2, variant \"new\" returns false, but requiredConfig returns true. Both rules must match, so it will be hidden\n*/\nfeature.setFlag('feature2','new',function(rule){\n    return false;\n});\n\n/*\n  feature3 returns true, but requiredConfig returns false. Both rules must match, so Feature3 is hidden\n*/\nfeature.setFlag('feature3',function(rule){\n    return true;\n});\n\n/*\n    api.isActive('feature2') -\u003e return true\n    api.isActive('feature2','new') -\u003e return false\n    api.isActive('feature2','old') -\u003e return true\n    api.isActive('feature2','grumpfel') -\u003e return true\n\n    api.isActive('feature3','new') -\u003e return false\n    api.isActive('feature3','old') -\u003e return false\n*/\n```\nYou already want to initialize it in the constructor? No Problem.\n```javascript\n    var api = useFeatureToggle({\n    _required: true, //default visibility always returns true; again: this could also be a function\n });\n```\n\n#### Function isActive\nExample for this function:\n```javascript\n// prooves if feature2 is visible\nvar isActive = feature.isActive('feature2');\n\n// prooves if tag feature \"feature2\", variant \"new\" is visible\nvar isActive_new = feature.isActive('feature2','new');\n\n// prooves if tag feature \"feature2\", variant \"new\" with data \"grumpfl\" is visible\nvar isActive_data = feature.isActive('feature2','new','grumpfl');\n\n// prooves if tag feature \"feature2\" with data \"grumpfl\" is visible\nvar isActive_data_onlyname = feature.isActive('feature2',null,'grumpfl');\n```\n\n#### Function setData\nif you want to update the data without updating the whole visibilityrule, use the setData-Function.\n```javascript\n    api.setData('featurename','variantname','anydata'); //will set the data for featurename#variantnam -\u003e anydata\n    //or\n    api.setData('featurename','anydata2'); // will set the data for featurename -\u003e anydata2\n\n    //api.setData() calls the listener.\n    api.on('visibilityrule', function (rule) {\n        console.log(rule.data); \n    });\n\n    api.setFlag('feature', 'variant','gruempfel',true); // logs 'gruempfel'\n    api.setData('feature','variant','newgruempfel');  // logs 'newgruempfel'\n    api.setFlag('feature2', null,'gruempfel2',true);  // logs 'gruempfel2'\n    api.setData('feature2','newgruempfel2');  // logs 'newgruempfel2'\n```\n\n#### Listeners\nIf you want to 'watch' every initialisation of a visibility rule, you can append a watcher on it.\n```javascript\n    var api = useFeatureToggle({feature: true});\n    api.setFlag(\"feature2\",\"variant\",\"data\",true);\n    \n    //Calling the listener will also regard already added visibility rules\n    //The result: \n    //true, 'feature', undefined, undefined\n    //true, 'feature2, 'variant', \"data\"\n    api.on('visibilityrule', function (event) {\n        console.log(event.result+\",\"+event.name+\",\"+event.variant+\",\"+event.data);\n    })\n```\n\nYou can also add custom events and triggers whenever you want.\n```javascript\n    var api = useFeatureToggle();\n    api.on('customevent', function (param) {\n        console.log(\"customevent \" + param);\n    });\n\n    api.trigger('customevent','fired');\n    //logs \"customevent fired\"\n```\n\n#### Plugins\nYou can add more functionality to the feature-toggle-api with plugins. Imagine you want an api that watches url-parameters - then you can add a plugin that implemented this logic. Or (if it does not exist) write a custom one.\n\n##### Use existing plugins\nThe feature toggle api already implemented some Plugins that can be used without installing other packages.\nSome plugins are included within this package:\n\n###### HTML-Plugin\nYou can use the api with \u003cfeature\u003e tags\n```html\n    \u003cfeature name=\"feature1\"\u003e\n        \u003c!-- Will be shown because feature1 is visible --\u003e\n    \u003c/feature\u003e\n```\n[Read more about this plugin here.](https://github.com/bassdman/feature-toggle-api/blob/master/src/plugins/htmlplugin/readme.md)\n\n###### URL-Plugin\nThe api sets the features according to the url-parameters.\n\nExample: \nURL: https://anydomain.de?feature1=true\u0026feature2=false\n-\u003e sets feature1=true and feature2=false\n\n[Read more about this plugin here.](https://github.com/bassdman/feature-toggle-api/blob/master/src/plugins/urlplugin/readme.md)\n\n\n##### Write a custom plugin\nA plugin is just a function with a parameter. You can add it with the .addPlugin()-Function.\nCalling addPlugin() prevents you from from adding a plugin multiple times, so if you do this, the plugin will only be executed once. \n```javascript\n    function customFunctionPlugin(api){\n        //adds function customFunction to your api\n\n        return {\n            customFunction(){console.log('custom function created')}\n        }\n    }\n    \n    //1st option: via constructor\n    //Important: don't forget the _ in the property _plugins!!!\n    const api = useFeatureToggle({_plugins:[customFunctionPlugin]});\n\n    //2nd option: via function\n    api.addPlugin(customFunctionPlugin);\n\n    //-\u003e now api.customFunction() logs \"custom function created\"\n```\n\nHere's the way, how to add parameters to your plugin\n```javascript\n    function pluginWithParams(param1)\n    {\n        return function (api){\n            //adds function customFunction to your api\n            return {\n                customFunction = function(){console.log('Hello ' + param1)}\n            }\n        }\n    }\n\n    //1st option: via constructor\n    //Important: don't forget the _ in the property _plugins!!!\n    const api = useFeatureToggle({$plugins:[pluginWithParams('Peter')]});\n\n    //2nd option: via function\n    api.addPlugin(pluginWithParams('Peter'));\n\n    //-\u003e now api.customFunction() logs \"Hello Peter\"\n```\n\n#### ShowLogs\nImagine this following html-snippet:\n```javascript\n    /* Why is this ******* feature hidden? I checked the visibilityrule. It should be visible... */\n    api.isActive('anamazingFeature') //returns false, but should return true... wtf???\n```\nAll developers of the world agree with you, debugging sth like this is horrible. But don't worry, we have a perfect solution for it. And it's just one line of code.\n```javascript\nfeature.showLogs(); //or feature.showLogs(true);\n```\nThis returns a log like the following:\n```html\nCheck Visibility of Feature \"anAmazingFeature\".\nThe requiredFlag rule returns false. This feature will be hidden.\n\nCheck Visibility of Feature \"anotherAmazingFeature\", variant \"new\" with data {\"id\":\"bla\"}.\nThe requiredFlag rule returns true. This feature will be shown when no other rule rejects it.\nNo visibility rule found matching name and variant.\nNo rules found for name anotherAmazingFeature without variants.\nNo default rule found.\nOnly the requiredFlag rule was found. This returned true. =\u003e This feature will be visible.\n```\nWith this you don't have to waste your time with debugging the visibility state. \n\n\n## API-Description\n### Constructor\n - 1 paramter; must be an object; optional;\n - all parameters _not_ starting with an _ are visibilityrules\n - all parameters starting with an _ are _not_ visibilityrules, but configuration for the api\n - possible configuration settings:\n    - _plugins: Adds a plugin; Array of functions; optional\n\n```javascript\n//initializes a visibilityrule and adds a plugin\nvar api = useFeatureToggle({\n    feature1: true,\n},{\n    plugins:[]\n})\n```\n\n### Flag\nAdds a Flag.\n\nParameters:\n - name: name of the feature; required; type string\n - variant: variant of the feature; optional; type string\n - data: corresp. data for the feature; optional; type any\n - result: result for this feature; required; boolean or function that returns boolean\n\nReturns:\n    nothing\n```javascript\n//possible parameters\napi.setFlag(name,result);\napi.setFlag(name,variant,result);\napi.setFlag(name,variant,data,result);\n```\nExample: \n```javascript\n//possible parameters\napi.setFlag('name',true);\napi.setFlag('name','variant',true);\napi.setFlag('name','variant','data',true);\n\n//if result is a function\napi.setFlag('name',function(rule){\n    /*\n    rule has the following parameters\n        name: Name of the feature,\n        variant: Variant: Variant of the feature\n        data: Data of the feature\n    }\n    */\n   return true\n});\n```\n\n### isActive\nProoves if a function is visible.\n\nParameters:\n - name: name of the feature; required; type string\n - variant: variant of the feature; optional; type string\n - data: corresp. data for the feature; optional; type any\n\nReturns:\n    boolean: weather the feature is visible or not\n\n```javascript\n//possible parameters\napi.isActive(name);\napi.isActive(name,variant);\napi.isActive(name,variant,data);\n```\n\n### on\nA listener that is executed, everytime a function visibility rule is added or changed. Is also executed for rules that are passed via constructor.\n\nParameters:\n - eventname: name of event; required; type string; \n - eventfunction: function that is executed when a rule changes; required; type function\n\nEvents:\n - visibilityrule: executed, everytime a function visibility rule is added or changed. Is also executed for rules that are passed via constructor.\n\nReturns\n    Nothing\n\n```javascript\napi.on('visibilityrule', function (event) {\n    /*\n        Parameters: \n        event.name, \n        event.variant, \n        event.data, \n        event.result\n    */\n})\n```\n\n### trigger\ntriggers an Event\nParameters:\n - eventname: name of event; required; type string; \n - parameter: optional; will be passed to the event as 1st parameter\n\nReturns\n    Nothing\n\n```javascript\napi.on('eventname', function (event) {\n    console.log('doSth');\n})\napi.trigger('eventname'); //triggers event eventname\napi.trigger('eventname','parameter');\n```\n\n### setData\nSets the data for the corresp. feature;\nAlso triggers listener \"visibilityrule\".\n\nParameters:\n - name: name of the feature; required; type string\n - variant: variant of the feature; optional; type string\n - data: corresp. data for the feature; required; type any\n\nReturns\n    nothing\n\n```javascript\n     api.setData(name,data); \n     api.setData(name,variant,data);\n```\n\n### requiredFlag\nSets the function for the required visibility.\n\nParameters: \n - requiredFlagFunction\n\nReturns:\n - nothing\n\n```javascript\n//possible parameters\napi.setRequiredFlag(function(rule){\n    //do sth\n    /* Parameters: \n        event.name, \n        event.variant, \n        event.data, \n    */\n});\n```\n\n### defaultFlag\nSets the function for the default visibility.\n\nParameters: \n - defaultFlagFunction\n\nReturns:\n - nothing\n\n```javascript\n//possible parameters\napi.setDefaultFlag(function(rule){\n    //do sth\n    /* Parameters: \n        event.name, \n        event.variant, \n        event.data, \n    */\n});\n```\n\n### addPlugin\nAdds a plugin to the api. A plugin will only be executed once, even if the function is called multiple times.\n\nParameters: \n - plugin: required -\u003e adds a plugin to the api\n\nReturns:\n - nothing\n\n```javascript\napi.addPlugin(plugin);\n```\n\n### showLogs\nShows the Logs of a visibilityrule when function is called or listener is triggered.\n\nParameters:\n - showLogs: should logs be shown or not?; optional; type boolean; default: true\n\nReturns\n    nothing\n\n```javascript\napi.showLogs(); \n//is the same as\napi.showLogs(true);\n```\n\n## License\t\n\u003ca href=\"https://opensource.org/licenses/MIT\"\u003eMIT\u003c/a\u003e.\nCopyright (c) 2018 Manuel Gelsen\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbassdman%2Ffeature-toggle-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbassdman%2Ffeature-toggle-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbassdman%2Ffeature-toggle-api/lists"}