mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: feature lifecycle complete and uncomplete (#6927)
Creating a way to complete and uncomplete feature.
This commit is contained in:
		
							parent
							
								
									31ab38e162
								
							
						
					
					
						commit
						78b9299ff1
					
				| @ -7,6 +7,10 @@ import EventStore from '../../db/event-store'; | |||||||
| import type { Db } from '../../db/db'; | import type { Db } from '../../db/db'; | ||||||
| import { FeatureLifecycleStore } from './feature-lifecycle-store'; | import { FeatureLifecycleStore } from './feature-lifecycle-store'; | ||||||
| import EnvironmentStore from '../project-environments/environment-store'; | import EnvironmentStore from '../project-environments/environment-store'; | ||||||
|  | import EventService from '../events/event-service'; | ||||||
|  | import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store'; | ||||||
|  | import { EventEmitter } from 'stream'; | ||||||
|  | import FeatureTagStore from '../../db/feature-tag-store'; | ||||||
| 
 | 
 | ||||||
| export const createFeatureLifecycleService = ( | export const createFeatureLifecycleService = ( | ||||||
|     db: Db, |     db: Db, | ||||||
| @ -16,12 +20,24 @@ export const createFeatureLifecycleService = ( | |||||||
|     const eventStore = new EventStore(db, getLogger); |     const eventStore = new EventStore(db, getLogger); | ||||||
|     const featureLifecycleStore = new FeatureLifecycleStore(db); |     const featureLifecycleStore = new FeatureLifecycleStore(db); | ||||||
|     const environmentStore = new EnvironmentStore(db, eventBus, getLogger); |     const environmentStore = new EnvironmentStore(db, eventBus, getLogger); | ||||||
|  |     const featureTagStore = new FeatureTagStore( | ||||||
|  |         db, | ||||||
|  |         config.eventBus, | ||||||
|  |         config.getLogger, | ||||||
|  |     ); | ||||||
|  |     const eventService = new EventService( | ||||||
|  |         { eventStore, featureTagStore }, | ||||||
|  |         { getLogger, eventBus: new EventEmitter() }, | ||||||
|  |     ); | ||||||
|     const featureLifecycleService = new FeatureLifecycleService( |     const featureLifecycleService = new FeatureLifecycleService( | ||||||
|         { |         { | ||||||
|             eventStore, |             eventStore, | ||||||
|             featureLifecycleStore, |             featureLifecycleStore, | ||||||
|             environmentStore, |             environmentStore, | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             eventService, | ||||||
|  |         }, | ||||||
|         config, |         config, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -37,12 +53,19 @@ export const createFakeFeatureLifecycleService = (config: IUnleashConfig) => { | |||||||
|     const eventStore = new FakeEventStore(); |     const eventStore = new FakeEventStore(); | ||||||
|     const featureLifecycleStore = new FakeFeatureLifecycleStore(); |     const featureLifecycleStore = new FakeFeatureLifecycleStore(); | ||||||
|     const environmentStore = new FakeEnvironmentStore(); |     const environmentStore = new FakeEnvironmentStore(); | ||||||
|  |     const eventService = new EventService( | ||||||
|  |         { eventStore, featureTagStore: new FakeFeatureTagStore() }, | ||||||
|  |         config, | ||||||
|  |     ); | ||||||
|     const featureLifecycleService = new FeatureLifecycleService( |     const featureLifecycleService = new FeatureLifecycleService( | ||||||
|         { |         { | ||||||
|             eventStore, |             eventStore, | ||||||
|             featureLifecycleStore, |             featureLifecycleStore, | ||||||
|             environmentStore, |             environmentStore, | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             eventService, | ||||||
|  |         }, | ||||||
|         config, |         config, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -43,4 +43,14 @@ export class FakeFeatureLifecycleStore implements IFeatureLifecycleStore { | |||||||
|         const lifecycle = await this.get(stage.feature); |         const lifecycle = await this.get(stage.feature); | ||||||
|         return Boolean(lifecycle.find((s) => s.stage === stage.stage)); |         return Boolean(lifecycle.find((s) => s.stage === stage.stage)); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     async deleteStage(stage: FeatureLifecycleStage): Promise<void> { | ||||||
|  |         if (!this.lifecycles[stage.feature]) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         const updatedStages = this.lifecycles[stage.feature].filter( | ||||||
|  |             (s) => s.stage !== stage.stage, | ||||||
|  |         ); | ||||||
|  |         this.lifecycles[stage.feature] = updatedStages; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,10 +5,12 @@ import { | |||||||
|     type IUnleashServices, |     type IUnleashServices, | ||||||
|     NONE, |     NONE, | ||||||
|     serializeDates, |     serializeDates, | ||||||
|  |     UPDATE_FEATURE, | ||||||
| } from '../../types'; | } from '../../types'; | ||||||
| import type { OpenApiService } from '../../services'; | import type { OpenApiService } from '../../services'; | ||||||
| import { | import { | ||||||
|     createResponseSchema, |     createResponseSchema, | ||||||
|  |     emptyResponse, | ||||||
|     featureLifecycleSchema, |     featureLifecycleSchema, | ||||||
|     type FeatureLifecycleSchema, |     type FeatureLifecycleSchema, | ||||||
|     getStandardResponses, |     getStandardResponses, | ||||||
| @ -16,6 +18,7 @@ import { | |||||||
| import Controller from '../../routes/controller'; | import Controller from '../../routes/controller'; | ||||||
| import type { Request, Response } from 'express'; | import type { Request, Response } from 'express'; | ||||||
| import { NotFoundError } from '../../error'; | import { NotFoundError } from '../../error'; | ||||||
|  | import type { IAuthRequest } from '../../routes/unleash-types'; | ||||||
| 
 | 
 | ||||||
| interface FeatureLifecycleParams { | interface FeatureLifecycleParams { | ||||||
|     projectId: string; |     projectId: string; | ||||||
| @ -62,6 +65,46 @@ export default class FeatureLifecycleController extends Controller { | |||||||
|                 }), |                 }), | ||||||
|             ], |             ], | ||||||
|         }); |         }); | ||||||
|  | 
 | ||||||
|  |         this.route({ | ||||||
|  |             method: 'post', | ||||||
|  |             path: `${PATH}/complete`, | ||||||
|  |             handler: this.complete, | ||||||
|  |             permission: UPDATE_FEATURE, | ||||||
|  |             acceptAnyContentType: true, | ||||||
|  |             middleware: [ | ||||||
|  |                 openApiService.validPath({ | ||||||
|  |                     tags: ['Unstable'], | ||||||
|  |                     summary: 'Set feature completed', | ||||||
|  |                     description: 'This will set the feature as completed.', | ||||||
|  |                     operationId: 'complete', | ||||||
|  |                     responses: { | ||||||
|  |                         200: emptyResponse, | ||||||
|  |                         ...getStandardResponses(401, 403, 404), | ||||||
|  |                     }, | ||||||
|  |                 }), | ||||||
|  |             ], | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         this.route({ | ||||||
|  |             method: 'post', | ||||||
|  |             path: `${PATH}/uncomplete`, | ||||||
|  |             handler: this.uncomplete, | ||||||
|  |             permission: UPDATE_FEATURE, | ||||||
|  |             acceptAnyContentType: true, | ||||||
|  |             middleware: [ | ||||||
|  |                 openApiService.validPath({ | ||||||
|  |                     tags: ['Unstable'], | ||||||
|  |                     summary: 'Set feature uncompleted', | ||||||
|  |                     description: 'This will set the feature as uncompleted.', | ||||||
|  |                     operationId: 'uncomplete', | ||||||
|  |                     responses: { | ||||||
|  |                         200: emptyResponse, | ||||||
|  |                         ...getStandardResponses(401, 403, 404), | ||||||
|  |                     }, | ||||||
|  |                 }), | ||||||
|  |             ], | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getFeatureLifecycle( |     async getFeatureLifecycle( | ||||||
| @ -83,4 +126,38 @@ export default class FeatureLifecycleController extends Controller { | |||||||
|             serializeDates(result), |             serializeDates(result), | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     async complete( | ||||||
|  |         req: IAuthRequest<FeatureLifecycleParams>, | ||||||
|  |         res: Response, | ||||||
|  |     ): Promise<void> { | ||||||
|  |         if (!this.flagResolver.isEnabled('featureLifecycle')) { | ||||||
|  |             throw new NotFoundError('Feature lifecycle is disabled.'); | ||||||
|  |         } | ||||||
|  |         const { featureName } = req.params; | ||||||
|  | 
 | ||||||
|  |         await this.featureLifecycleService.featureCompleted( | ||||||
|  |             featureName, | ||||||
|  |             req.audit, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         res.status(200).end(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async uncomplete( | ||||||
|  |         req: IAuthRequest<FeatureLifecycleParams>, | ||||||
|  |         res: Response, | ||||||
|  |     ): Promise<void> { | ||||||
|  |         if (!this.flagResolver.isEnabled('featureLifecycle')) { | ||||||
|  |             throw new NotFoundError('Feature lifecycle is disabled.'); | ||||||
|  |         } | ||||||
|  |         const { featureName } = req.params; | ||||||
|  | 
 | ||||||
|  |         await this.featureLifecycleService.featureUnCompleted( | ||||||
|  |             featureName, | ||||||
|  |             req.audit, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         res.status(200).end(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -68,8 +68,6 @@ test('can insert and read lifecycle stages', async () => { | |||||||
|     emitMetricsEvent('my-prod-environment'); |     emitMetricsEvent('my-prod-environment'); | ||||||
|     emitMetricsEvent('my-another-prod-environment'); |     emitMetricsEvent('my-another-prod-environment'); | ||||||
| 
 | 
 | ||||||
|     eventStore.emit(FEATURE_COMPLETED, { featureName }); |  | ||||||
|     await reachedStage('completed'); |  | ||||||
|     eventStore.emit(FEATURE_ARCHIVED, { featureName }); |     eventStore.emit(FEATURE_ARCHIVED, { featureName }); | ||||||
|     await reachedStage('archived'); |     await reachedStage('archived'); | ||||||
| 
 | 
 | ||||||
| @ -80,7 +78,6 @@ test('can insert and read lifecycle stages', async () => { | |||||||
|         { stage: 'initial', enteredStageAt: expect.any(Date) }, |         { stage: 'initial', enteredStageAt: expect.any(Date) }, | ||||||
|         { stage: 'pre-live', enteredStageAt: expect.any(Date) }, |         { stage: 'pre-live', enteredStageAt: expect.any(Date) }, | ||||||
|         { stage: 'live', enteredStageAt: expect.any(Date) }, |         { stage: 'live', enteredStageAt: expect.any(Date) }, | ||||||
|         { stage: 'completed', enteredStageAt: expect.any(Date) }, |  | ||||||
|         { stage: 'archived', enteredStageAt: expect.any(Date) }, |         { stage: 'archived', enteredStageAt: expect.any(Date) }, | ||||||
|     ]); |     ]); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +1,11 @@ | |||||||
| import { | import { | ||||||
|     CLIENT_METRICS, |     CLIENT_METRICS, | ||||||
|     FEATURE_ARCHIVED, |     FEATURE_ARCHIVED, | ||||||
|     FEATURE_COMPLETED, |  | ||||||
|     FEATURE_CREATED, |     FEATURE_CREATED, | ||||||
|     FEATURE_REVIVED, |     FEATURE_REVIVED, | ||||||
|  |     FeatureCompletedEvent, | ||||||
|  |     FeatureUncompletedEvent, | ||||||
|  |     type IAuditUser, | ||||||
|     type IEnvironmentStore, |     type IEnvironmentStore, | ||||||
|     type IEventStore, |     type IEventStore, | ||||||
|     type IFlagResolver, |     type IFlagResolver, | ||||||
| @ -15,6 +17,7 @@ import type { | |||||||
| } from './feature-lifecycle-store-type'; | } from './feature-lifecycle-store-type'; | ||||||
| import EventEmitter from 'events'; | import EventEmitter from 'events'; | ||||||
| import type { Logger } from '../../logger'; | import type { Logger } from '../../logger'; | ||||||
|  | import type EventService from '../events/event-service'; | ||||||
| import type { ValidatedClientMetrics } from '../metrics/shared/schema'; | import type { ValidatedClientMetrics } from '../metrics/shared/schema'; | ||||||
| 
 | 
 | ||||||
| export const STAGE_ENTERED = 'STAGE_ENTERED'; | export const STAGE_ENTERED = 'STAGE_ENTERED'; | ||||||
| @ -30,6 +33,8 @@ export class FeatureLifecycleService extends EventEmitter { | |||||||
| 
 | 
 | ||||||
|     private eventBus: EventEmitter; |     private eventBus: EventEmitter; | ||||||
| 
 | 
 | ||||||
|  |     private eventService: EventService; | ||||||
|  | 
 | ||||||
|     private logger: Logger; |     private logger: Logger; | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
| @ -42,6 +47,11 @@ export class FeatureLifecycleService extends EventEmitter { | |||||||
|             environmentStore: IEnvironmentStore; |             environmentStore: IEnvironmentStore; | ||||||
|             featureLifecycleStore: IFeatureLifecycleStore; |             featureLifecycleStore: IFeatureLifecycleStore; | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             eventService, | ||||||
|  |         }: { | ||||||
|  |             eventService: EventService; | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             flagResolver, |             flagResolver, | ||||||
|             eventBus, |             eventBus, | ||||||
| @ -54,6 +64,7 @@ export class FeatureLifecycleService extends EventEmitter { | |||||||
|         this.environmentStore = environmentStore; |         this.environmentStore = environmentStore; | ||||||
|         this.flagResolver = flagResolver; |         this.flagResolver = flagResolver; | ||||||
|         this.eventBus = eventBus; |         this.eventBus = eventBus; | ||||||
|  |         this.eventService = eventService; | ||||||
|         this.logger = getLogger( |         this.logger = getLogger( | ||||||
|             'feature-lifecycle/feature-lifecycle-service.ts', |             'feature-lifecycle/feature-lifecycle-service.ts', | ||||||
|         ); |         ); | ||||||
| @ -84,11 +95,6 @@ export class FeatureLifecycleService extends EventEmitter { | |||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|         ); |         ); | ||||||
|         this.eventStore.on(FEATURE_COMPLETED, async (event) => { |  | ||||||
|             await this.checkEnabled(() => |  | ||||||
|                 this.featureCompleted(event.featureName), |  | ||||||
|             ); |  | ||||||
|         }); |  | ||||||
|         this.eventStore.on(FEATURE_ARCHIVED, async (event) => { |         this.eventStore.on(FEATURE_ARCHIVED, async (event) => { | ||||||
|             await this.checkEnabled(() => |             await this.checkEnabled(() => | ||||||
|                 this.featureArchived(event.featureName), |                 this.featureArchived(event.featureName), | ||||||
| @ -145,14 +151,32 @@ export class FeatureLifecycleService extends EventEmitter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async featureCompleted(feature: string) { |     public async featureCompleted(feature: string, auditUser: IAuditUser) { | ||||||
|         await this.featureLifecycleStore.insert([ |         await this.featureLifecycleStore.insert([ | ||||||
|             { |             { | ||||||
|                 feature, |                 feature, | ||||||
|                 stage: 'completed', |                 stage: 'completed', | ||||||
|             }, |             }, | ||||||
|         ]); |         ]); | ||||||
|         this.emit(STAGE_ENTERED, { stage: 'completed' }); |         await this.eventService.storeEvent( | ||||||
|  |             new FeatureCompletedEvent({ | ||||||
|  |                 featureName: feature, | ||||||
|  |                 auditUser, | ||||||
|  |             }), | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public async featureUnCompleted(feature: string, auditUser: IAuditUser) { | ||||||
|  |         await this.featureLifecycleStore.deleteStage({ | ||||||
|  |             feature, | ||||||
|  |             stage: 'completed', | ||||||
|  |         }); | ||||||
|  |         await this.eventService.storeEvent( | ||||||
|  |             new FeatureUncompletedEvent({ | ||||||
|  |                 featureName: feature, | ||||||
|  |                 auditUser, | ||||||
|  |             }), | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async featureArchived(feature: string) { |     private async featureArchived(feature: string) { | ||||||
|  | |||||||
| @ -12,4 +12,5 @@ export interface IFeatureLifecycleStore { | |||||||
|     get(feature: string): Promise<FeatureLifecycleView>; |     get(feature: string): Promise<FeatureLifecycleView>; | ||||||
|     stageExists(stage: FeatureLifecycleStage): Promise<boolean>; |     stageExists(stage: FeatureLifecycleStage): Promise<boolean>; | ||||||
|     delete(feature: string): Promise<void>; |     delete(feature: string): Promise<void>; | ||||||
|  |     deleteStage(stage: FeatureLifecycleStage): Promise<void>; | ||||||
| } | } | ||||||
|  | |||||||
| @ -62,6 +62,15 @@ export class FeatureLifecycleStore implements IFeatureLifecycleStore { | |||||||
|         await this.db('feature_lifecycles').where({ feature }).del(); |         await this.db('feature_lifecycles').where({ feature }).del(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     async deleteStage(stage: FeatureLifecycleStage): Promise<void> { | ||||||
|  |         await this.db('feature_lifecycles') | ||||||
|  |             .where({ | ||||||
|  |                 stage: stage.stage, | ||||||
|  |                 feature: stage.feature, | ||||||
|  |             }) | ||||||
|  |             .del(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     async stageExists(stage: FeatureLifecycleStage): Promise<boolean> { |     async stageExists(stage: FeatureLifecycleStage): Promise<boolean> { | ||||||
|         const result = await this.db.raw( |         const result = await this.db.raw( | ||||||
|             `SELECT EXISTS(SELECT 1 FROM feature_lifecycles WHERE stage = ? and feature = ?) AS present`, |             `SELECT EXISTS(SELECT 1 FROM feature_lifecycles WHERE stage = ? and feature = ?) AS present`, | ||||||
|  | |||||||
| @ -61,6 +61,21 @@ const getFeatureLifecycle = async (featureName: string, expectedCode = 200) => { | |||||||
|         .get(`/api/admin/projects/default/features/${featureName}/lifecycle`) |         .get(`/api/admin/projects/default/features/${featureName}/lifecycle`) | ||||||
|         .expect(expectedCode); |         .expect(expectedCode); | ||||||
| }; | }; | ||||||
|  | const completeFeature = async (featureName: string, expectedCode = 200) => { | ||||||
|  |     return app.request | ||||||
|  |         .post( | ||||||
|  |             `/api/admin/projects/default/features/${featureName}/lifecycle/complete`, | ||||||
|  |         ) | ||||||
|  |         .expect(expectedCode); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uncompleteFeature = async (featureName: string, expectedCode = 200) => { | ||||||
|  |     return app.request | ||||||
|  |         .post( | ||||||
|  |             `/api/admin/projects/default/features/${featureName}/lifecycle/uncomplete`, | ||||||
|  |         ) | ||||||
|  |         .expect(expectedCode); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| function reachedStage(name: StageName) { | function reachedStage(name: StageName) { | ||||||
|     return new Promise((resolve) => |     return new Promise((resolve) => | ||||||
| @ -70,10 +85,10 @@ function reachedStage(name: StageName) { | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const expectFeatureStage = async (stage: StageName) => { | const expectFeatureStage = async (featureName: string, stage: StageName) => { | ||||||
|     const { body: feature } = await app.getProjectFeatures( |     const { body: feature } = await app.getProjectFeatures( | ||||||
|         'default', |         'default', | ||||||
|         'my_feature_a', |         featureName, | ||||||
|     ); |     ); | ||||||
|     expect(feature.lifecycle).toMatchObject({ |     expect(feature.lifecycle).toMatchObject({ | ||||||
|         stage, |         stage, | ||||||
| @ -85,7 +100,7 @@ test('should return lifecycle stages', async () => { | |||||||
|     await app.createFeature('my_feature_a'); |     await app.createFeature('my_feature_a'); | ||||||
|     eventStore.emit(FEATURE_CREATED, { featureName: 'my_feature_a' }); |     eventStore.emit(FEATURE_CREATED, { featureName: 'my_feature_a' }); | ||||||
|     await reachedStage('initial'); |     await reachedStage('initial'); | ||||||
|     await expectFeatureStage('initial'); |     await expectFeatureStage('my_feature_a', 'initial'); | ||||||
|     eventBus.emit(CLIENT_METRICS, { |     eventBus.emit(CLIENT_METRICS, { | ||||||
|         bucket: { |         bucket: { | ||||||
|             toggles: { |             toggles: { | ||||||
| @ -110,20 +125,42 @@ test('should return lifecycle stages', async () => { | |||||||
|         environment: 'non-existent', |         environment: 'non-existent', | ||||||
|     }); |     }); | ||||||
|     await reachedStage('live'); |     await reachedStage('live'); | ||||||
|     await expectFeatureStage('live'); |     await expectFeatureStage('my_feature_a', 'live'); | ||||||
|     eventStore.emit(FEATURE_ARCHIVED, { featureName: 'my_feature_a' }); |     eventStore.emit(FEATURE_ARCHIVED, { featureName: 'my_feature_a' }); | ||||||
|     await reachedStage('archived'); |     await reachedStage('archived'); | ||||||
| 
 | 
 | ||||||
|     const { body } = await getFeatureLifecycle('my_feature_a'); |     const { body } = await getFeatureLifecycle('my_feature_a'); | ||||||
| 
 | 
 | ||||||
|     expect(body).toEqual([ |     expect(body).toEqual([ | ||||||
|         { stage: 'initial', enteredStageAt: expect.any(String) }, |         { | ||||||
|         { stage: 'live', enteredStageAt: expect.any(String) }, |             stage: 'initial', | ||||||
|         { stage: 'archived', enteredStageAt: expect.any(String) }, |             enteredStageAt: expect.any(String), | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             stage: 'live', | ||||||
|  |             enteredStageAt: expect.any(String), | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             stage: 'archived', | ||||||
|  |             enteredStageAt: expect.any(String), | ||||||
|  |         }, | ||||||
|     ]); |     ]); | ||||||
| 
 |     await expectFeatureStage('my_feature_a', 'archived'); | ||||||
|     await expectFeatureStage('archived'); |  | ||||||
| 
 | 
 | ||||||
|     eventStore.emit(FEATURE_REVIVED, { featureName: 'my_feature_a' }); |     eventStore.emit(FEATURE_REVIVED, { featureName: 'my_feature_a' }); | ||||||
|     await reachedStage('initial'); |     await reachedStage('initial'); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | test('should be able to toggle between completed/uncompleted', async () => { | ||||||
|  |     await app.createFeature('my_feature_b'); | ||||||
|  | 
 | ||||||
|  |     await completeFeature('my_feature_b'); | ||||||
|  | 
 | ||||||
|  |     await expectFeatureStage('my_feature_b', 'completed'); | ||||||
|  | 
 | ||||||
|  |     await uncompleteFeature('my_feature_b'); | ||||||
|  | 
 | ||||||
|  |     const { body } = await getFeatureLifecycle('my_feature_b'); | ||||||
|  | 
 | ||||||
|  |     expect(body).toEqual([]); | ||||||
|  | }); | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ export const DROP_FEATURE_TAGS = 'drop-feature-tags' as const; | |||||||
| export const FEATURE_UNTAGGED = 'feature-untagged' as const; | export const FEATURE_UNTAGGED = 'feature-untagged' as const; | ||||||
| export const FEATURE_STALE_ON = 'feature-stale-on' as const; | export const FEATURE_STALE_ON = 'feature-stale-on' as const; | ||||||
| export const FEATURE_COMPLETED = 'feature-completed' as const; | export const FEATURE_COMPLETED = 'feature-completed' as const; | ||||||
|  | export const FEATURE_UNCOMPLETED = 'feature-uncompleted' as const; | ||||||
| export const FEATURE_STALE_OFF = 'feature-stale-off' as const; | export const FEATURE_STALE_OFF = 'feature-stale-off' as const; | ||||||
| export const DROP_FEATURES = 'drop-features' as const; | export const DROP_FEATURES = 'drop-features' as const; | ||||||
| export const FEATURE_ENVIRONMENT_ENABLED = | export const FEATURE_ENVIRONMENT_ENABLED = | ||||||
| @ -208,6 +209,8 @@ export const IEventTypes = [ | |||||||
|     FEATURE_STRATEGY_ADD, |     FEATURE_STRATEGY_ADD, | ||||||
|     FEATURE_STRATEGY_REMOVE, |     FEATURE_STRATEGY_REMOVE, | ||||||
|     FEATURE_TYPE_UPDATED, |     FEATURE_TYPE_UPDATED, | ||||||
|  |     FEATURE_COMPLETED, | ||||||
|  |     FEATURE_UNCOMPLETED, | ||||||
|     STRATEGY_ORDER_CHANGED, |     STRATEGY_ORDER_CHANGED, | ||||||
|     DROP_FEATURE_TAGS, |     DROP_FEATURE_TAGS, | ||||||
|     FEATURE_UNTAGGED, |     FEATURE_UNTAGGED, | ||||||
| @ -370,6 +373,7 @@ class BaseEvent implements IBaseEvent { | |||||||
|     readonly createdByUserId: number; |     readonly createdByUserId: number; | ||||||
| 
 | 
 | ||||||
|     readonly ip: string; |     readonly ip: string; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * @param type the type of the event we're creating. |      * @param type the type of the event we're creating. | ||||||
|      * @param auditUser User info used to track which user performed the action. Includes username (email or username), userId and ip |      * @param auditUser User info used to track which user performed the action. Includes username (email or username), userId and ip | ||||||
| @ -424,7 +428,11 @@ export class FeatureEnvironmentEvent extends BaseEvent { | |||||||
|         this.environment = p.environment; |         this.environment = p.environment; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| export type StrategyIds = { strategyIds: string[] }; | 
 | ||||||
|  | export type StrategyIds = { | ||||||
|  |     strategyIds: string[]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export class StrategiesOrderChangedEvent extends BaseEvent { | export class StrategiesOrderChangedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
| 
 | 
 | ||||||
| @ -459,9 +467,13 @@ export class FeatureVariantEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
| 
 | 
 | ||||||
|     readonly data: { variants: IVariant[] }; |     readonly data: { | ||||||
|  |         variants: IVariant[]; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     readonly preData: { variants: IVariant[] }; |     readonly preData: { | ||||||
|  |         variants: IVariant[]; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     constructor(p: { |     constructor(p: { | ||||||
|         project: string; |         project: string; | ||||||
| @ -485,9 +497,13 @@ export class EnvironmentVariantEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
| 
 | 
 | ||||||
|     readonly data: { variants: IVariant[] }; |     readonly data: { | ||||||
|  |         variants: IVariant[]; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     readonly preData: { variants: IVariant[] }; |     readonly preData: { | ||||||
|  |         variants: IVariant[]; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      */ |      */ | ||||||
| @ -507,9 +523,11 @@ export class EnvironmentVariantEvent extends BaseEvent { | |||||||
|         this.preData = { variants: p.oldVariants }; |         this.preData = { variants: p.oldVariants }; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class ProjectCreatedEvent extends BaseEvent { | export class ProjectCreatedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         project: string; |         project: string; | ||||||
| @ -525,6 +543,7 @@ export class ProjectUpdatedEvent extends BaseEvent { | |||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -540,6 +559,7 @@ export class ProjectUpdatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class ProjectDeletedEvent extends BaseEvent { | export class ProjectDeletedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -552,6 +572,7 @@ export class ProjectDeletedEvent extends BaseEvent { | |||||||
| export class RoleUpdatedEvent extends BaseEvent { | export class RoleUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -562,6 +583,7 @@ export class RoleUpdatedEvent extends BaseEvent { | |||||||
|         this.preData = eventData.preData; |         this.preData = eventData.preData; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class FeatureChangeProjectEvent extends BaseEvent { | export class FeatureChangeProjectEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
| 
 | 
 | ||||||
| @ -582,7 +604,10 @@ export class FeatureChangeProjectEvent extends BaseEvent { | |||||||
|         const { newProject, oldProject, featureName } = p; |         const { newProject, oldProject, featureName } = p; | ||||||
|         this.project = newProject; |         this.project = newProject; | ||||||
|         this.featureName = featureName; |         this.featureName = featureName; | ||||||
|         this.data = { newProject, oldProject }; |         this.data = { | ||||||
|  |             newProject, | ||||||
|  |             oldProject, | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -607,10 +632,37 @@ export class FeatureCreatedEvent extends BaseEvent { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export class FeatureCompletedEvent extends BaseEvent { | ||||||
|  |     readonly featureName: string; | ||||||
|  | 
 | ||||||
|  |     constructor(p: { | ||||||
|  |         featureName: string; | ||||||
|  |         auditUser: IAuditUser; | ||||||
|  |     }) { | ||||||
|  |         super(FEATURE_COMPLETED, p.auditUser); | ||||||
|  |         const { featureName } = p; | ||||||
|  |         this.featureName = featureName; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class FeatureUncompletedEvent extends BaseEvent { | ||||||
|  |     readonly featureName: string; | ||||||
|  | 
 | ||||||
|  |     constructor(p: { | ||||||
|  |         featureName: string; | ||||||
|  |         auditUser: IAuditUser; | ||||||
|  |     }) { | ||||||
|  |         super(FEATURE_UNCOMPLETED, p.auditUser); | ||||||
|  |         const { featureName } = p; | ||||||
|  |         this.featureName = featureName; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export class FeatureUpdatedEvent extends BaseEvent { | export class FeatureUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         featureName: string; |         featureName: string; | ||||||
| @ -628,6 +680,7 @@ export class FeatureTaggedEvent extends BaseEvent { | |||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         featureName: string; |         featureName: string; | ||||||
| @ -644,6 +697,7 @@ export class FeatureTaggedEvent extends BaseEvent { | |||||||
| export class FeatureTypeUpdatedEvent extends BaseEvent { | export class FeatureTypeUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -654,10 +708,12 @@ export class FeatureTypeUpdatedEvent extends BaseEvent { | |||||||
|         this.preData = eventData.preData; |         this.preData = eventData.preData; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class FeatureDependencyAddedEvent extends BaseEvent { | export class FeatureDependencyAddedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         featureName: string; |         featureName: string; | ||||||
| @ -675,6 +731,7 @@ export class FeatureDependencyRemovedEvent extends BaseEvent { | |||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         featureName: string; |         featureName: string; | ||||||
| @ -687,6 +744,7 @@ export class FeatureDependencyRemovedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class FeatureDependenciesRemovedEvent extends BaseEvent { | export class FeatureDependenciesRemovedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
| @ -705,6 +763,7 @@ export class FeatureDependenciesRemovedEvent extends BaseEvent { | |||||||
| export class FeaturesImportedEvent extends BaseEvent { | export class FeaturesImportedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly environment: string; |     readonly environment: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         environment: string; |         environment: string; | ||||||
| @ -892,6 +951,7 @@ export class FeatureStrategyRemoveEvent extends BaseEvent { | |||||||
| export class FeatureFavoritedEvent extends BaseEvent { | export class FeatureFavoritedEvent extends BaseEvent { | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         featureName: string; |         featureName: string; | ||||||
|         data: any; |         data: any; | ||||||
| @ -906,6 +966,7 @@ export class FeatureFavoritedEvent extends BaseEvent { | |||||||
| export class ProjectFavoritedEvent extends BaseEvent { | export class ProjectFavoritedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         data: any; |         data: any; | ||||||
| @ -920,6 +981,7 @@ export class ProjectFavoritedEvent extends BaseEvent { | |||||||
| export class FeatureUnfavoritedEvent extends BaseEvent { | export class FeatureUnfavoritedEvent extends BaseEvent { | ||||||
|     readonly featureName: string; |     readonly featureName: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         featureName: string; |         featureName: string; | ||||||
|         data: any; |         data: any; | ||||||
| @ -934,6 +996,7 @@ export class FeatureUnfavoritedEvent extends BaseEvent { | |||||||
| export class ProjectUnfavoritedEvent extends BaseEvent { | export class ProjectUnfavoritedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1367,6 +1430,7 @@ export class UserDeletedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class TagTypeCreatedEvent extends BaseEvent { | export class TagTypeCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1378,6 +1442,7 @@ export class TagTypeCreatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class TagTypeDeletedEvent extends BaseEvent { | export class TagTypeDeletedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -1389,6 +1454,7 @@ export class TagTypeDeletedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class TagTypeUpdatedEvent extends BaseEvent { | export class TagTypeUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1400,6 +1466,7 @@ export class TagTypeUpdatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class TagCreatedEvent extends BaseEvent { | export class TagCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1411,6 +1478,7 @@ export class TagCreatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class TagDeletedEvent extends BaseEvent { | export class TagDeletedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1422,6 +1490,7 @@ export class TagDeletedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class PatCreatedEvent extends BaseEvent { | export class PatCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1430,8 +1499,10 @@ export class PatCreatedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class PatDeletedEvent extends BaseEvent { | export class PatDeletedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1444,6 +1515,7 @@ export class PatDeletedEvent extends BaseEvent { | |||||||
| export class ProjectEnvironmentAdded extends BaseEvent { | export class ProjectEnvironmentAdded extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly environment: string; |     readonly environment: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         environment: string; |         environment: string; | ||||||
| @ -1458,6 +1530,7 @@ export class ProjectEnvironmentAdded extends BaseEvent { | |||||||
| export class ProjectEnvironmentRemoved extends BaseEvent { | export class ProjectEnvironmentRemoved extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly environment: string; |     readonly environment: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         environment: string; |         environment: string; | ||||||
| @ -1471,6 +1544,7 @@ export class ProjectEnvironmentRemoved extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class FeaturesExportedEvent extends BaseEvent { | export class FeaturesExportedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1482,6 +1556,7 @@ export class FeaturesExportedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class RoleCreatedEvent extends BaseEvent { | export class RoleCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1493,6 +1568,7 @@ export class RoleCreatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class RoleDeletedEvent extends BaseEvent { | export class RoleDeletedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         preData: any; |         preData: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1501,8 +1577,10 @@ export class RoleDeletedEvent extends BaseEvent { | |||||||
|         this.preData = eventData.preData; |         this.preData = eventData.preData; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class StrategyCreatedEvent extends BaseEvent { | export class StrategyCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1511,8 +1589,10 @@ export class StrategyCreatedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class StrategyUpdatedEvent extends BaseEvent { | export class StrategyUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1521,8 +1601,10 @@ export class StrategyUpdatedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class StrategyDeletedEvent extends BaseEvent { | export class StrategyDeletedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1531,8 +1613,10 @@ export class StrategyDeletedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class StrategyDeprecatedEvent extends BaseEvent { | export class StrategyDeprecatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1541,8 +1625,10 @@ export class StrategyDeprecatedEvent extends BaseEvent { | |||||||
|         this.data = eventData.data; |         this.data = eventData.data; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class StrategyReactivatedEvent extends BaseEvent { | export class StrategyReactivatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
| @ -1557,6 +1643,7 @@ export class DefaultStrategyUpdatedEvent extends BaseEvent { | |||||||
|     readonly environment: string; |     readonly environment: string; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         project: string; |         project: string; | ||||||
|         environment: string; |         environment: string; | ||||||
| @ -1574,6 +1661,7 @@ export class DefaultStrategyUpdatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class AddonConfigCreatedEvent extends BaseEvent { | export class AddonConfigCreatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1586,6 +1674,7 @@ export class AddonConfigCreatedEvent extends BaseEvent { | |||||||
| export class AddonConfigUpdatedEvent extends BaseEvent { | export class AddonConfigUpdatedEvent extends BaseEvent { | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         data: any; |         data: any; | ||||||
| @ -1599,6 +1688,7 @@ export class AddonConfigUpdatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class AddonConfigDeletedEvent extends BaseEvent { | export class AddonConfigDeletedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -1611,6 +1701,7 @@ export class AddonConfigDeletedEvent extends BaseEvent { | |||||||
| export class SegmentCreatedEvent extends BaseEvent { | export class SegmentCreatedEvent extends BaseEvent { | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         project: string; |         project: string; | ||||||
| @ -1626,6 +1717,7 @@ export class SegmentUpdatedEvent extends BaseEvent { | |||||||
|     readonly data: any; |     readonly data: any; | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|     readonly project: string; |     readonly project: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         project: string; |         project: string; | ||||||
| @ -1638,9 +1730,11 @@ export class SegmentUpdatedEvent extends BaseEvent { | |||||||
|         this.preData = eventData.preData; |         this.preData = eventData.preData; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| export class SegmentDeletedEvent extends BaseEvent { | export class SegmentDeletedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|     readonly project?: string; |     readonly project?: string; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -1655,6 +1749,7 @@ export class SegmentDeletedEvent extends BaseEvent { | |||||||
| export class GroupUpdatedEvent extends BaseEvent { | export class GroupUpdatedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|     readonly data: any; |     readonly data: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         data: any; |         data: any; | ||||||
|         preData: any; |         preData: any; | ||||||
| @ -1668,6 +1763,7 @@ export class GroupUpdatedEvent extends BaseEvent { | |||||||
| 
 | 
 | ||||||
| export class GroupDeletedEvent extends BaseEvent { | export class GroupDeletedEvent extends BaseEvent { | ||||||
|     readonly preData: any; |     readonly preData: any; | ||||||
|  | 
 | ||||||
|     constructor(eventData: { |     constructor(eventData: { | ||||||
|         preData: any; |         preData: any; | ||||||
|         auditUser: IAuditUser; |         auditUser: IAuditUser; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user