diff --git a/src/domain/notification/create/insertData.ts b/src/domain/notification/create/insertData.ts index aa1171c6..1742358e 100644 --- a/src/domain/notification/create/insertData.ts +++ b/src/domain/notification/create/insertData.ts @@ -6,5 +6,5 @@ import type { DataModel } from '../types'; export default async function insertData(data: DataModel): Promise { - return database.createRecord(RECORD_TYPE, { ...data }); + return database.createRecord(RECORD_TYPE, { ...data, deleted: false }); } diff --git a/src/domain/notification/getById/getById.ts b/src/domain/notification/getById/getById.ts index 954137d2..4f4f52db 100644 --- a/src/domain/notification/getById/getById.ts +++ b/src/domain/notification/getById/getById.ts @@ -1,4 +1,5 @@ +import type { RecordQuery } from '^/integrations/database'; import database from '^/integrations/database'; import { RECORD_TYPE } from '../definitions'; @@ -6,5 +7,10 @@ import type { DataModel } from '../types'; export default async function getById(id: string): Promise { - return database.readRecord(RECORD_TYPE, id) as Promise; + const query: RecordQuery = + { + id: { EQUALS: id }, + deleted: { EQUALS: false } + }; + return database.findRecord(RECORD_TYPE, query) as Promise; } diff --git a/src/domain/notification/getByPostId/getByPostId.ts b/src/domain/notification/getByPostId/getByPostId.ts new file mode 100644 index 00000000..7a4a1d2c --- /dev/null +++ b/src/domain/notification/getByPostId/getByPostId.ts @@ -0,0 +1,17 @@ + +import type { RecordQuery } from '^/integrations/database'; +import database from '^/integrations/database'; + +import { RECORD_TYPE } from '../definitions'; +import type { DataModel } from '../types'; + +export default async function getByPostId(postId: string): Promise +{ + const query: RecordQuery = + { + deleted: { EQUALS: false }, + postId: { EQUALS: postId } + }; + + return database.searchRecords(RECORD_TYPE, query) as Promise; +} diff --git a/src/domain/notification/getByPostId/index.ts b/src/domain/notification/getByPostId/index.ts new file mode 100644 index 00000000..8c7bc494 --- /dev/null +++ b/src/domain/notification/getByPostId/index.ts @@ -0,0 +1,2 @@ + +export { default } from './getByPostId'; diff --git a/src/domain/notification/getRecent/getRecent.ts b/src/domain/notification/getRecent/getRecent.ts index 36f7be6e..640e31cc 100644 --- a/src/domain/notification/getRecent/getRecent.ts +++ b/src/domain/notification/getRecent/getRecent.ts @@ -1,5 +1,5 @@ -import type { RecordQuery, RecordSort} from '^/integrations/database'; +import type { RecordQuery, RecordSort } from '^/integrations/database'; import database, { SortDirections } from '^/integrations/database'; import { RECORD_TYPE } from '../definitions'; @@ -9,6 +9,7 @@ export default async function getRecent(receiverId: string, limit: number, offse { const query: RecordQuery = { + deleted: { EQUALS: false }, receiverId: { EQUALS: receiverId } }; diff --git a/src/domain/notification/notify/removedPost.ts b/src/domain/notification/notify/removedPost.ts new file mode 100644 index 00000000..68e9ac6f --- /dev/null +++ b/src/domain/notification/notify/removedPost.ts @@ -0,0 +1,11 @@ + +import getNotifications from '../getByPostId'; +import remove from '../remove'; + +export default async function removedPost(postId: string): Promise +{ + const notifications = await getNotifications(postId); + const promises = notifications.map(item => remove(item.id)); + + await Promise.allSettled(promises); +} diff --git a/src/domain/notification/notify/subscriptions.ts b/src/domain/notification/notify/subscriptions.ts index b85bc9c4..884fc682 100644 --- a/src/domain/notification/notify/subscriptions.ts +++ b/src/domain/notification/notify/subscriptions.ts @@ -1,10 +1,12 @@ import { subscribe as subscribeToPostCreated } from '^/domain/post/create'; +import { subscribe as subscribeToPostRemoved } from '^/domain/post/remove'; import { subscribe as subscribeToPostRated } from '^/domain/rating/toggle'; import { subscribe as subscribeToRelationEstablished } from '^/domain/relation/establish'; import reactedToPost from './createdPost'; import ratedPost from './ratedPost'; +import removedPost from './removedPost'; import startedFollowing from './startedFollowing'; async function subscribe(): Promise @@ -13,6 +15,7 @@ async function subscribe(): Promise subscribeToPostRated(({ creatorId, postId, rated }) => ratedPost(creatorId, postId, rated)), subscribeToPostCreated(({ creatorId, postId, parentId }) => reactedToPost(creatorId, postId, parentId)), subscribeToRelationEstablished(({ followerId, followingId }) => startedFollowing(followerId, followingId)), + subscribeToPostRemoved(({ postId }) => removedPost(postId)), ]); } diff --git a/src/domain/notification/remove/index.ts b/src/domain/notification/remove/index.ts new file mode 100644 index 00000000..16bee921 --- /dev/null +++ b/src/domain/notification/remove/index.ts @@ -0,0 +1,2 @@ + +export { default } from './remove'; diff --git a/src/domain/notification/remove/remove.ts b/src/domain/notification/remove/remove.ts new file mode 100644 index 00000000..961a5a8f --- /dev/null +++ b/src/domain/notification/remove/remove.ts @@ -0,0 +1,9 @@ + +import database from '^/integrations/database'; + +import { RECORD_TYPE } from '../definitions'; + +export default async function remove(id: string): Promise +{ + return database.updateRecord(RECORD_TYPE, id, { deleted: true }); +} diff --git a/test/domain/notification/fixtures/databases.fixture.ts b/test/domain/notification/fixtures/databases.fixture.ts index c35ce8a7..4a60a183 100644 --- a/test/domain/notification/fixtures/databases.fixture.ts +++ b/test/domain/notification/fixtures/databases.fixture.ts @@ -37,7 +37,7 @@ async function withCreatorsPostsAndNotifications(): Promise RECORDS.POSTS.map(post => database.createRecord(POST_RECORD_TYPE, { ...post })), RECORDS.POST_METRICS.map(postMetric => database.createRecord(POST_METRICS_RECORD_TYPE, { ...postMetric })), RECORDS.RATINGS.map(rating => database.createRecord(RATING_RECORD_TYPE, { rating })), - RECORDS.NOTIFICATIONS.map(notification => database.createRecord(NOTIFICATION_RECORD_TYPE, { ...notification })) + RECORDS.NOTIFICATIONS.map(notification => database.createRecord(NOTIFICATION_RECORD_TYPE, { ...notification, deleted: false })) ]; await Promise.all(promises.flat()); diff --git a/test/domain/notification/fixtures/records.fixture.ts b/test/domain/notification/fixtures/records.fixture.ts index bde961db..04ed7602 100644 --- a/test/domain/notification/fixtures/records.fixture.ts +++ b/test/domain/notification/fixtures/records.fixture.ts @@ -5,7 +5,7 @@ import type { DataModel as ComicDataModel } from '^/domain/comic'; import type { DataModel as CreatorDataModel } from '^/domain/creator'; import type { DataModel as CreatorMetricsDataModel } from '^/domain/creator.metrics'; import type { DataModel as ImageDataModel } from '^/domain/image'; -import type { DataModel as NotificationDataModel} from '^/domain/notification'; +import type { DataModel as NotificationDataModel } from '^/domain/notification'; import { Types } from '^/domain/notification'; import type { DataModel as PostDataModel } from '^/domain/post'; import type { DataModel as PostMetricsModel } from '^/domain/post.metrics'; @@ -56,12 +56,13 @@ const RATINGS: RatingDataModel[] = [ { id: VALUES.IDS.RATING2, createdAt: new Date().toISOString(), creatorId: VALUES.IDS.CREATOR2, postId: VALUES.IDS.REACTION_LIKED } ]; -const NOTIFICATIONS: NotificationDataModel[] = [ - { id: VALUES.IDS.NOTIFICATION1, createdAt: new Date().toISOString(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR2, postId: undefined }, - { id: VALUES.IDS.NOTIFICATION2, createdAt: new Date().toISOString(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined }, - { id: VALUES.IDS.NOTIFICATION3, createdAt: new Date('01-05-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR3, receiverId: VALUES.IDS.CREATOR2, postId: VALUES.IDS.POST_RATED }, - { id: VALUES.IDS.NOTIFICATION4, createdAt: new Date('01-04-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.REACTION_LIKED }, - { id: VALUES.IDS.NOTIFICATION5, createdAt: new Date('01-03-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_DELETED } +const NOTIFICATIONS: (NotificationDataModel & { deleted: boolean; })[] = [ + { id: VALUES.IDS.NOTIFICATION1, createdAt: new Date().toISOString(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR2, postId: undefined, deleted: false }, + { id: VALUES.IDS.NOTIFICATION2, createdAt: new Date().toISOString(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, deleted: false }, + { id: VALUES.IDS.NOTIFICATION3, createdAt: new Date('01-05-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR3, receiverId: VALUES.IDS.CREATOR2, postId: VALUES.IDS.POST_RATED, deleted: false }, + { id: VALUES.IDS.NOTIFICATION6, createdAt: new Date().toISOString(), type: Types.REACTED_TO_POST, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR3, postId: VALUES.IDS.REACTION_LIKED, deleted: false }, + { id: VALUES.IDS.NOTIFICATION4, createdAt: new Date('01-04-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.REACTION_LIKED, deleted: false }, + { id: VALUES.IDS.NOTIFICATION5, createdAt: new Date('01-03-2024').toISOString(), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_DELETED, deleted: false } ]; export const RECORDS: Record = { CREATORS, CREATOR_METRICS, RELATIONS, IMAGES, COMICS, POSTS, POST_METRICS, RATINGS, NOTIFICATIONS }; diff --git a/test/domain/notification/fixtures/values.fixture.ts b/test/domain/notification/fixtures/values.fixture.ts index c7c560dc..46fed52b 100644 --- a/test/domain/notification/fixtures/values.fixture.ts +++ b/test/domain/notification/fixtures/values.fixture.ts @@ -27,7 +27,8 @@ export const VALUES = NOTIFICATION2: 'N2', NOTIFICATION3: 'N3', NOTIFICATION4: 'N4', - NOTIFICATION5: 'N5' + NOTIFICATION5: 'N5', + NOTIFICATION6: 'N6' }, STORAGE_KEYS: { diff --git a/test/domain/notification/removePostNotifications.spec.ts b/test/domain/notification/removePostNotifications.spec.ts new file mode 100644 index 00000000..24eab02f --- /dev/null +++ b/test/domain/notification/removePostNotifications.spec.ts @@ -0,0 +1,25 @@ + +import { beforeEach, describe, expect, it } from 'vitest'; + +import getByPostId from '^/domain/notification/getByPostId'; +import removedPost from '^/domain/notification/notify/removedPost'; + +import { DATABASES, VALUES } from './fixtures'; + +beforeEach(async () => +{ + await Promise.all([ + DATABASES.withCreatorsPostsAndNotifications() + ]); +}); + +describe('domain/notification/remove', () => +{ + it('should remove all notifications of a removed post', async () => + { + await removedPost(VALUES.IDS.POST_RATED); + const result = await getByPostId(VALUES.IDS.POST_RATED); + + expect(result).toHaveLength(0); + }); +});