mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: composition root for user subscriptions (#8649)
Co-Authored-By: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									b491d9eb8b
								
							
						
					
					
						commit
						6a8a75ce71
					
				| @ -189,7 +189,7 @@ export const createStores = ( | ||||
|             eventBus, | ||||
|             config.flagResolver, | ||||
|         ), | ||||
|         userUnsubscribeStore: new UserUnsubscribeStore(db, getLogger), | ||||
|         userUnsubscribeStore: new UserUnsubscribeStore(db), | ||||
|         userSubscriptionsReadModel: new UserSubscriptionsReadModel( | ||||
|             db, | ||||
|             eventBus, | ||||
|  | ||||
| @ -0,0 +1,36 @@ | ||||
| import type { Db, IUnleashConfig } from '../../server-impl'; | ||||
| import UserSubscriptionService from './user-subscriptions-service'; | ||||
| import { UserUnsubscribeStore } from './user-unsubscribe-store'; | ||||
| import { | ||||
|     createEventsService, | ||||
|     createFakeEventsService, | ||||
| } from '../events/createEventsService'; | ||||
| import { FakeUserUnsubscribeStore } from './fake-user-unsubscribe-store'; | ||||
| 
 | ||||
| export const createUserSubscriptionsService = | ||||
|     (config: IUnleashConfig) => | ||||
|     (db: Db): UserSubscriptionService => { | ||||
|         const userUnsubscribeStore = new UserUnsubscribeStore(db); | ||||
|         const eventService = createEventsService(db, config); | ||||
| 
 | ||||
|         const userSubscriptionsService = new UserSubscriptionService( | ||||
|             { userUnsubscribeStore }, | ||||
|             config, | ||||
|             eventService, | ||||
|         ); | ||||
| 
 | ||||
|         return userSubscriptionsService; | ||||
|     }; | ||||
| 
 | ||||
| export const createFakeUserSubscriptionsService = (config: IUnleashConfig) => { | ||||
|     const userUnsubscribeStore = new FakeUserUnsubscribeStore(); | ||||
|     const eventService = createFakeEventsService(config); | ||||
| 
 | ||||
|     const userSubscriptionsService = new UserSubscriptionService( | ||||
|         { userUnsubscribeStore }, | ||||
|         config, | ||||
|         eventService, | ||||
|     ); | ||||
| 
 | ||||
|     return userSubscriptionsService; | ||||
| }; | ||||
| @ -45,10 +45,14 @@ export class UserSubscriptionsReadModel implements IUserSubscriptionsReadModel { | ||||
|     } | ||||
| 
 | ||||
|     async getUserSubscriptions(userId: number) { | ||||
|         const unsubscriptions = await this.db(UNSUBSCRIPTION_TABLE) | ||||
|         const unsubscriptionsList = await this.db(UNSUBSCRIPTION_TABLE) | ||||
|             .select('subscription') | ||||
|             .where('user_id', userId); | ||||
| 
 | ||||
|         const unsubscriptions: string[] = unsubscriptionsList.map( | ||||
|             (item) => item.subscription, | ||||
|         ); | ||||
| 
 | ||||
|         return SUBSCRIPTION_TYPES.filter( | ||||
|             (subscription) => !unsubscriptions.includes(subscription), | ||||
|         ); | ||||
|  | ||||
| @ -0,0 +1,67 @@ | ||||
| import { | ||||
|     type IUnleashConfig, | ||||
|     type IUnleashStores, | ||||
|     type IUser, | ||||
|     TEST_AUDIT_USER, | ||||
| } from '../../types'; | ||||
| import type UserSubscriptionService from './user-subscriptions-service'; | ||||
| import dbInit, { type ITestDb } from '../../../test/e2e/helpers/database-init'; | ||||
| import { createTestConfig } from '../../../test/config/test-config'; | ||||
| import getLogger from '../../../test/fixtures/no-logger'; | ||||
| import { createUserSubscriptionsService } from './createUserSubscriptionsService'; | ||||
| import type { IUserSubscriptionsReadModel } from './user-subscriptions-read-model-type'; | ||||
| 
 | ||||
| let stores: IUnleashStores; | ||||
| let db: ITestDb; | ||||
| let userSubscriptionService: UserSubscriptionService; | ||||
| let userSubscriptionsReadModel: IUserSubscriptionsReadModel; | ||||
| let config: IUnleashConfig; | ||||
| let user: IUser; | ||||
| 
 | ||||
| beforeAll(async () => { | ||||
|     db = await dbInit('user_subscriptions', getLogger); | ||||
|     stores = db.stores; | ||||
|     config = createTestConfig({}); | ||||
| 
 | ||||
|     userSubscriptionService = createUserSubscriptionsService(config)( | ||||
|         db.rawDatabase, | ||||
|     ); | ||||
|     userSubscriptionsReadModel = db.stores.userSubscriptionsReadModel; | ||||
| 
 | ||||
|     user = await stores.userStore.insert({ | ||||
|         email: 'test@getunleash.io', | ||||
|         name: 'Sample Name', | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| afterAll(async () => { | ||||
|     await db.destroy(); | ||||
| }); | ||||
| 
 | ||||
| test('Subscribe and unsubscribe', async () => { | ||||
|     const subscribers = await userSubscriptionsReadModel.getSubscribedUsers( | ||||
|         'productivity-report', | ||||
|     ); | ||||
|     expect(subscribers).toMatchObject([ | ||||
|         { email: 'test@getunleash.io', name: 'Sample Name' }, | ||||
|     ]); | ||||
| 
 | ||||
|     const userSubscriptions = | ||||
|         await userSubscriptionsReadModel.getUserSubscriptions(user.id); | ||||
|     expect(userSubscriptions).toMatchObject(['productivity-report']); | ||||
| 
 | ||||
|     await userSubscriptionService.unsubscribe( | ||||
|         user.id, | ||||
|         'productivity-report', | ||||
|         TEST_AUDIT_USER, | ||||
|     ); | ||||
| 
 | ||||
|     const noSubscribers = await userSubscriptionsReadModel.getSubscribedUsers( | ||||
|         'productivity-report', | ||||
|     ); | ||||
|     expect(noSubscribers).toMatchObject([]); | ||||
| 
 | ||||
|     const noUserSubscriptions = | ||||
|         await userSubscriptionsReadModel.getUserSubscriptions(user.id); | ||||
|     expect(noUserSubscriptions).toMatchObject([]); | ||||
| }); | ||||
| @ -1,9 +1,5 @@ | ||||
| import type { Logger, LogProvider } from '../../logger'; | ||||
| import type { Db } from '../../db/db'; | ||||
| import type { | ||||
|     UnsubscribeEntry, | ||||
|     IUserUnsubscribeStore, | ||||
| } from './user-unsubscribe-store-type'; | ||||
| import type { IUserUnsubscribeStore } from './user-unsubscribe-store-type'; | ||||
| 
 | ||||
| const COLUMNS = ['user_id', 'subscription', 'created_at']; | ||||
| export const TABLE = 'user_unsubscription'; | ||||
| @ -14,20 +10,11 @@ interface IUserUnsubscribeTable { | ||||
|     created_at?: Date; | ||||
| } | ||||
| 
 | ||||
| const rowToField = (row: IUserUnsubscribeTable): UnsubscribeEntry => ({ | ||||
|     userId: row.user_id, | ||||
|     subscription: row.subscription, | ||||
|     createdAt: row.created_at, | ||||
| }); | ||||
| 
 | ||||
| export class UserUnsubscribeStore implements IUserUnsubscribeStore { | ||||
|     private db: Db; | ||||
| 
 | ||||
|     private logger: Logger; | ||||
| 
 | ||||
|     constructor(db: Db, getLogger: LogProvider) { | ||||
|     constructor(db: Db) { | ||||
|         this.db = db; | ||||
|         this.logger = getLogger('user-unsubscribe-store.ts'); | ||||
|     } | ||||
| 
 | ||||
|     async insert({ userId, subscription }) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user