Merge pull request #2979 from specklesystems/fabians/notifications-ioc-2
chore(server): notifications IoC 2 - updateNotificationPreferencesFactory
This commit is contained in:
@@ -3,3 +3,8 @@ import { NotificationPreferences } from '@/modules/notifications/helpers/types'
|
||||
export type GetSavedUserNotificationPreferences = (
|
||||
userId: string
|
||||
) => Promise<NotificationPreferences>
|
||||
|
||||
export type SaveUserNotificationPreferences = (
|
||||
userId: string,
|
||||
preferences: NotificationPreferences
|
||||
) => Promise<void>
|
||||
|
||||
+10
-3
@@ -1,9 +1,12 @@
|
||||
import { db } from '@/db/knex'
|
||||
import { Resolvers } from '@/modules/core/graph/generated/graphql'
|
||||
import { getSavedUserNotificationPreferencesFactory } from '@/modules/notifications/repositories'
|
||||
import {
|
||||
updateNotificationPreferences,
|
||||
getUserNotificationPreferencesFactory
|
||||
getSavedUserNotificationPreferencesFactory,
|
||||
saveUserNotificationPreferencesFactory
|
||||
} from '@/modules/notifications/repositories'
|
||||
import {
|
||||
getUserNotificationPreferencesFactory,
|
||||
updateNotificationPreferencesFactory
|
||||
} from '@/modules/notifications/services/notificationPreferences'
|
||||
|
||||
const getUserNotificationPreferences = getUserNotificationPreferencesFactory({
|
||||
@@ -12,6 +15,10 @@ const getUserNotificationPreferences = getUserNotificationPreferencesFactory({
|
||||
})
|
||||
})
|
||||
|
||||
const updateNotificationPreferences = updateNotificationPreferencesFactory({
|
||||
saveUserNotificationPreferences: saveUserNotificationPreferencesFactory({ db })
|
||||
})
|
||||
|
||||
export = {
|
||||
User: {
|
||||
async notificationPreferences(parent) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { UserNotificationPreferences } from '@/modules/core/dbSchema'
|
||||
import { GetSavedUserNotificationPreferences } from '@/modules/notifications/domain/operations'
|
||||
import {
|
||||
GetSavedUserNotificationPreferences,
|
||||
SaveUserNotificationPreferences
|
||||
} from '@/modules/notifications/domain/operations'
|
||||
import {
|
||||
NotificationPreferences,
|
||||
UserNotificationPreferencesRecord
|
||||
@@ -22,12 +25,12 @@ export const getSavedUserNotificationPreferencesFactory =
|
||||
return userPreferences?.preferences ?? {}
|
||||
}
|
||||
|
||||
export async function saveUserNotificationPreferences(
|
||||
userId: string,
|
||||
preferences: NotificationPreferences
|
||||
): Promise<void> {
|
||||
await UserNotificationPreferences.knex()
|
||||
.insert({ userId, preferences })
|
||||
.onConflict('userId')
|
||||
.merge()
|
||||
}
|
||||
export const saveUserNotificationPreferencesFactory =
|
||||
(deps: { db: Knex }): SaveUserNotificationPreferences =>
|
||||
async (userId: string, preferences: NotificationPreferences): Promise<void> => {
|
||||
await tables
|
||||
.userNotificationPreferences(deps.db)
|
||||
.insert({ userId, preferences })
|
||||
.onConflict('userId')
|
||||
.merge()
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import * as repo from '@/modules/notifications/repositories'
|
||||
import {
|
||||
NotificationChannel,
|
||||
NotificationType,
|
||||
NotificationPreferences
|
||||
} from '@/modules/notifications/helpers/types'
|
||||
import { InvalidArgumentError } from '@/modules/shared/errors'
|
||||
import { GetSavedUserNotificationPreferences } from '@/modules/notifications/domain/operations'
|
||||
import {
|
||||
GetSavedUserNotificationPreferences,
|
||||
SaveUserNotificationPreferences
|
||||
} from '@/modules/notifications/domain/operations'
|
||||
|
||||
export const getUserNotificationPreferencesFactory =
|
||||
(deps: {
|
||||
@@ -32,35 +34,34 @@ function addDefaultPreferenceValues(
|
||||
return savedPreferences
|
||||
}
|
||||
|
||||
export async function updateNotificationPreferences(
|
||||
userId: string,
|
||||
rawPreferences: Record<string, unknown>
|
||||
): Promise<void> {
|
||||
const parsedPreferences: NotificationPreferences = {}
|
||||
// lets do some nested attribute copying, to sanitize the input
|
||||
for (const key in rawPreferences) {
|
||||
if (!Object.values(NotificationType).includes(key as NotificationType))
|
||||
throw new InvalidArgumentError(
|
||||
`Notification preferences input contains an unknown setting: ${key}`
|
||||
)
|
||||
const nt = key as NotificationType
|
||||
const notificationTypePreferences: Partial<Record<NotificationChannel, boolean>> =
|
||||
{}
|
||||
const notificationTypeSettings = rawPreferences[nt] as Record<string, unknown>
|
||||
for (const ncKey in notificationTypeSettings) {
|
||||
if (!Object.values(NotificationChannel).includes(ncKey as NotificationChannel))
|
||||
export const updateNotificationPreferencesFactory =
|
||||
(deps: { saveUserNotificationPreferences: SaveUserNotificationPreferences }) =>
|
||||
async (userId: string, rawPreferences: Record<string, unknown>): Promise<void> => {
|
||||
const parsedPreferences: NotificationPreferences = {}
|
||||
// lets do some nested attribute copying, to sanitize the input
|
||||
for (const key in rawPreferences) {
|
||||
if (!Object.values(NotificationType).includes(key as NotificationType))
|
||||
throw new InvalidArgumentError(
|
||||
`Notification preferences input contains an unknown setting: ${ncKey}`
|
||||
`Notification preferences input contains an unknown setting: ${key}`
|
||||
)
|
||||
const nc = ncKey as NotificationChannel
|
||||
const preferenceValue = notificationTypeSettings[nc]
|
||||
if (typeof preferenceValue !== 'boolean')
|
||||
throw new InvalidArgumentError(
|
||||
`Notification preferences input contains and invalid value: ${preferenceValue}`
|
||||
)
|
||||
notificationTypePreferences[nc] = preferenceValue
|
||||
const nt = key as NotificationType
|
||||
const notificationTypePreferences: Partial<Record<NotificationChannel, boolean>> =
|
||||
{}
|
||||
const notificationTypeSettings = rawPreferences[nt] as Record<string, unknown>
|
||||
for (const ncKey in notificationTypeSettings) {
|
||||
if (!Object.values(NotificationChannel).includes(ncKey as NotificationChannel))
|
||||
throw new InvalidArgumentError(
|
||||
`Notification preferences input contains an unknown setting: ${ncKey}`
|
||||
)
|
||||
const nc = ncKey as NotificationChannel
|
||||
const preferenceValue = notificationTypeSettings[nc]
|
||||
if (typeof preferenceValue !== 'boolean')
|
||||
throw new InvalidArgumentError(
|
||||
`Notification preferences input contains and invalid value: ${preferenceValue}`
|
||||
)
|
||||
notificationTypePreferences[nc] = preferenceValue
|
||||
}
|
||||
parsedPreferences[nt] = notificationTypePreferences
|
||||
}
|
||||
parsedPreferences[nt] = notificationTypePreferences
|
||||
return await deps.saveUserNotificationPreferences(userId, parsedPreferences)
|
||||
}
|
||||
return await repo.saveUserNotificationPreferences(userId, parsedPreferences)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import { UserNotificationPreferences, Users } from '@/modules/core/dbSchema'
|
||||
import { BasicTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import * as services from '@/modules/notifications/services/notificationPreferences'
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
NotificationType,
|
||||
NotificationChannel
|
||||
} from '@/modules/notifications/helpers/types'
|
||||
import { BaseError } from '@/modules/shared/errors'
|
||||
import { getUserNotificationPreferencesFactory } from '@/modules/notifications/services/notificationPreferences'
|
||||
import { getSavedUserNotificationPreferencesFactory } from '@/modules/notifications/repositories'
|
||||
import {
|
||||
getUserNotificationPreferencesFactory,
|
||||
updateNotificationPreferencesFactory
|
||||
} from '@/modules/notifications/services/notificationPreferences'
|
||||
import {
|
||||
getSavedUserNotificationPreferencesFactory,
|
||||
saveUserNotificationPreferencesFactory
|
||||
} from '@/modules/notifications/repositories'
|
||||
import { db } from '@/db/knex'
|
||||
|
||||
const getSavedUserNotificationPreferences = getSavedUserNotificationPreferencesFactory({
|
||||
@@ -18,6 +23,9 @@ const getSavedUserNotificationPreferences = getSavedUserNotificationPreferencesF
|
||||
const getUserNotificationPreferences = getUserNotificationPreferencesFactory({
|
||||
getSavedUserNotificationPreferences
|
||||
})
|
||||
const updateNotificationPreferences = updateNotificationPreferencesFactory({
|
||||
saveUserNotificationPreferences: saveUserNotificationPreferencesFactory({ db })
|
||||
})
|
||||
|
||||
const cleanup = async () => {
|
||||
await truncateTables([Users.name, UserNotificationPreferences.name])
|
||||
@@ -49,13 +57,13 @@ describe('User notification preferences @notifications', () => {
|
||||
}
|
||||
})
|
||||
it('store notification settings', async () => {
|
||||
await services.updateNotificationPreferences(userA.id, {
|
||||
await updateNotificationPreferences(userA.id, {
|
||||
activityDigest: { email: false }
|
||||
})
|
||||
let preferences = await getUserNotificationPreferences(userA.id)
|
||||
expect(preferences).to.not.be.empty
|
||||
expect(preferences.activityDigest?.email).to.be.false
|
||||
await services.updateNotificationPreferences(userA.id, {
|
||||
await updateNotificationPreferences(userA.id, {
|
||||
activityDigest: { email: true }
|
||||
})
|
||||
preferences = await getUserNotificationPreferences(userA.id)
|
||||
@@ -81,7 +89,7 @@ describe('User notification preferences @notifications', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
preferences[nt][nc] = value
|
||||
await services.updateNotificationPreferences(userA.id, preferences)
|
||||
await updateNotificationPreferences(userA.id, preferences)
|
||||
} catch (err) {
|
||||
expect(err instanceof BaseError)
|
||||
const error = err as BaseError
|
||||
|
||||
Reference in New Issue
Block a user