mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: add option and functionality that allows a user to hook into feature mutations (#457)
* Add option and functionality that allows a user to hook into feature mutations. * Fix function argument to include the entire event.
This commit is contained in:
		
							parent
							
								
									55d2208422
								
							
						
					
					
						commit
						d917e8018f
					
				| @ -59,6 +59,7 @@ Available unleash options include: | |||||||
|   - `custom` - use this when you implement your own custom authentication logic. |   - `custom` - use this when you implement your own custom authentication logic. | ||||||
| - **ui** (object) - Set of UI specific overrides. You may set the following keys: `headerBackground`, `environment`, `slogan`. | - **ui** (object) - Set of UI specific overrides. You may set the following keys: `headerBackground`, `environment`, `slogan`. | ||||||
| - **getLogger** (function) - Used to register a [custom log provider](#How do I configure the log output). | - **getLogger** (function) - Used to register a [custom log provider](#How do I configure the log output). | ||||||
|  | - **eventHook** (`function(event, data)`) - If provided, this function will be invoked whenever a feature is mutated. The possible values for `event` are `'feature-created'`, `'feature-updated'`, `'feature-archived'`, `'feature-revived'`. The `data` argument contains information about the mutation. Its fields are `type` (string) - the event type (same as `event`); `createdBy` (string) - the user who performed the mutation; `data` - the contents of the change. The contents in `data` differs based on the event type; For `'feature-archived'` and `'feature-revived'`, the only field will be `name` - the name of the feature. For `'feature-created'` and `'feature-updated'` the data follows a schema defined in the code [here](https://github.com/Unleash/unleash/blob/master/lib/routes/admin-api/feature-schema.js#L38-L59). | ||||||
| 
 | 
 | ||||||
| ### 3. Docker | ### 3. Docker | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								lib/event-hook.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/event-hook.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const { | ||||||
|  |     FEATURE_CREATED, | ||||||
|  |     FEATURE_UPDATED, | ||||||
|  |     FEATURE_ARCHIVED, | ||||||
|  |     FEATURE_REVIVED, | ||||||
|  | } = require('./event-type'); | ||||||
|  | 
 | ||||||
|  | exports.addEventHook = (eventHook, eventStore) => { | ||||||
|  |     eventStore.on(FEATURE_CREATED, data => { | ||||||
|  |         eventHook(FEATURE_CREATED, data); | ||||||
|  |     }); | ||||||
|  |     eventStore.on(FEATURE_UPDATED, data => { | ||||||
|  |         eventHook(FEATURE_UPDATED, data); | ||||||
|  |     }); | ||||||
|  |     eventStore.on(FEATURE_ARCHIVED, data => { | ||||||
|  |         eventHook(FEATURE_ARCHIVED, data); | ||||||
|  |     }); | ||||||
|  |     eventStore.on(FEATURE_REVIVED, data => { | ||||||
|  |         eventHook(FEATURE_REVIVED, data); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
							
								
								
									
										32
									
								
								lib/event-hook.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lib/event-hook.test.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const test = require('ava'); | ||||||
|  | const { EventEmitter } = require('events'); | ||||||
|  | const eventStore = new EventEmitter(); | ||||||
|  | const { addEventHook } = require('./event-hook'); | ||||||
|  | const { | ||||||
|  |     FEATURE_CREATED, | ||||||
|  |     FEATURE_UPDATED, | ||||||
|  |     FEATURE_ARCHIVED, | ||||||
|  |     FEATURE_REVIVED, | ||||||
|  | } = require('./event-type'); | ||||||
|  | 
 | ||||||
|  | const o = {}; | ||||||
|  | 
 | ||||||
|  | function testHook(feature, data) { | ||||||
|  |     o[feature] = data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | test.before(() => { | ||||||
|  |     addEventHook(testHook, eventStore); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | [FEATURE_CREATED, FEATURE_UPDATED, FEATURE_ARCHIVED, FEATURE_REVIVED].forEach( | ||||||
|  |     feature => { | ||||||
|  |         test(`should invoke hook on ${feature}`, t => { | ||||||
|  |             const data = { dataKey: feature }; | ||||||
|  |             eventStore.emit(feature, data); | ||||||
|  |             t.true(o[feature] === data); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | ); | ||||||
| @ -11,6 +11,7 @@ const { createOptions } = require('./options'); | |||||||
| const StateService = require('./state-service'); | const StateService = require('./state-service'); | ||||||
| const User = require('./user'); | const User = require('./user'); | ||||||
| const AuthenticationRequired = require('./authentication-required'); | const AuthenticationRequired = require('./authentication-required'); | ||||||
|  | const { addEventHook } = require('./event-hook'); | ||||||
| 
 | 
 | ||||||
| async function createApp(options) { | async function createApp(options) { | ||||||
|     // Database dependencies (stateful)
 |     // Database dependencies (stateful)
 | ||||||
| @ -35,6 +36,10 @@ async function createApp(options) { | |||||||
|         stores.clientMetricsStore |         stores.clientMetricsStore | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  |     if (typeof config.eventHook === 'function') { | ||||||
|  |         addEventHook(config.eventHook, stores.eventStore); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const stateService = new StateService(config); |     const stateService = new StateService(config); | ||||||
|     config.stateService = stateService; |     config.stateService = stateService; | ||||||
|     if (config.importFile) { |     if (config.importFile) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user