import dayjs from 'dayjs' ; import { Model , mongo } from 'mongoose' ; import { UserData } from '../../domain/user/declarations' ; import { IUserRepo } from '../../domain/user/IUserRepo' ; import User from '../../domain/user/user' ; import { PersistedUserData , ToBePersistedUserData } from './declarations' ; export class UserMongoRepo implements IUserRepo { constructor ( private readonly userModel ) { } return public nextIdentity ( ) { return new mongo . ObjectID ( ) . toString ( ) ; } returns { Promise < User [ ] > } public all ( ) { return new Promise ( ( resolve , reject ) => { this . userModel . find ( ) . then ( ( data ) => resolve ( data . map ( ( userData ) => new User ( userData ) ) ) ) . catch ( ( error ) => reject ( error ) ) ; } ) ; } param { string } userId returns { Promise < User | null > } public findById ( userId ) { return new Promise ( ( resolve , reject ) => { this . userModel . findById ( userId ) . then ( ( userData ) => { if ( ! userData ) { resolve ( null ) ; return ; } resolve ( new User ( userData ) ) ; } ) . catch ( ( error ) => { if ( error . name === 'CastError' ) { return resolve ( null ) ; } reject ( error ) ; } ) ; } ) ; } param { string } email returns { Promise < User | null > } public findByEmail ( email ) { return new Promise ( ( resolve , reject ) => { this . userModel . findOne ( { email } ) . then ( ( userData ) => { if ( userData === null ) { resolve ( null ) ; return ; } resolve ( new User ( userData ) ) ; } ) . catch ( ( error ) => reject ( error ) ) ; } ) ; } param { string } username returns { Promise < User | null > } public findByUsername ( username ) { return new Promise ( ( resolve , reject ) => { this . userModel . findOne ( { username } ) . then ( ( userData ) => { if ( userData === null ) { resolve ( null ) ; return ; } resolve ( new User ( userData ) ) ; } ) . catch ( ( error ) => reject ( error ) ) ; } ) ; } return { Promise < number > } public count ( ) { return new Promise ( ( resolve , reject ) => { this . userModel . count ( { } ) . then ( ( count ) => resolve ( count ) ) . catch ( ( error ) => reject ( error ) ) ; } ) ; } param { User } user returns { Promise < User > } public async persist ( user ) { const dataToBePersisted = this . getDataToBePersisted ( user ) ; const persistedUser = await this . userModel . findOneAndUpdate ( { _id : user . _id } , dataToBePersisted , { new : true , upsert : true } ) . lean ( ) ; user . updateDates ( dayjs ( persistedUser . updatedAt ) ) ; return user ; } private getDataToBePersisted ( user ) { return { _id : user . _id , email : user . email , ... ( user . username && { username : user . username } ) , } ; } } export default ( userModel ) : UserMongoRepo => { return new UserMongoRepo ( userModel ) ; } ;