-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
254 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Developer notes on persistence layer | ||
|
||
## Mapping aggregates to entities | ||
|
||
During development many aggregates were created and these aggregates have to be persisted as entities. | ||
Therefore, repositories were built which typically contain at least a _mapAggregateToData_ method and a _mapDataToAggregate_ method. | ||
|
||
### Troubleshooting | ||
|
||
If you encounter following error while writing such a method, 'Type Option<string> is not assignable to type string' e.g. on the id: | ||
|
||
```typescript | ||
function mapAggregateToData(aggregate: Aggregate<boolean>): RequiredEntityData<Aggregate> { | ||
return { | ||
// Don't assign createdAt and updatedAt, they are auto-generated! | ||
id: aggregate.id, //Here following error is shown: Type Option<string> is not assignable to type string | ||
personId: rel(PersonEntity, aggregate.personId), | ||
value: aggregate.value, | ||
}; | ||
} | ||
``` | ||
make sure that id is the primary key for the entity, additional declarations of primary key attributes may result in the error mentioned above, like e.g. in this entity: | ||
```typescript | ||
@Entity({ tableName: 'tableName' }) | ||
export class Entitiy extends TimestampedEntity { | ||
//... | ||
public [PrimaryKeyProp]?: ['anotherProp']; | ||
} | ||
``` | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ import { PersonRepository } from '../../person/persistence/person.repository.js' | |
import { EventModule, EventService } from '../../../core/eventbus/index.js'; | ||
import { EmailFactory } from './email.factory.js'; | ||
import { Email } from './email.js'; | ||
import { EmailID, PersonID, RolleID } from '../../../shared/types/index.js'; | ||
import { EmailAddressID, PersonID, RolleID } from '../../../shared/types/index.js'; | ||
import { EmailInvalidError } from '../error/email-invalid.error.js'; | ||
import { ClassLogger } from '../../../core/logging/class-logger.js'; | ||
import { EmailAddress } from './email-address.js'; | ||
|
@@ -37,16 +37,11 @@ import { PersonDeletedEvent } from '../../../shared/events/person-deleted.event. | |
import { EmailAddressNotFoundError } from '../error/email-address-not-found.error.js'; | ||
|
||
function getEmail(emaiGeneratorService: EmailGeneratorService, personRepository: PersonRepository): Email<true> { | ||
const fakeEmailId: EmailID = faker.string.uuid(); | ||
return Email.construct( | ||
fakeEmailId, | ||
faker.date.past(), | ||
faker.date.recent(), | ||
faker.string.uuid(), | ||
emaiGeneratorService, | ||
personRepository, | ||
[new EmailAddress<true>(fakeEmailId, faker.internet.email(), true)], | ||
); | ||
const fakePersonId: PersonID = faker.string.uuid(); | ||
const fakeEmailAddressId: string = faker.string.uuid(); | ||
return Email.construct(fakePersonId, emaiGeneratorService, personRepository, [ | ||
new EmailAddress<boolean>(fakeEmailAddressId, undefined, undefined, fakePersonId, faker.internet.email(), true), | ||
]); | ||
} | ||
|
||
describe('Email Event Handler', () => { | ||
|
@@ -141,7 +136,7 @@ describe('Email Event Handler', () => { | |
describe('when existing email is found', () => { | ||
it('should enable existing email', async () => { | ||
const fakePersonId: PersonID = faker.string.uuid(); | ||
const emailId: EmailID = faker.string.uuid(); | ||
const emailAddressId: EmailAddressID = faker.string.uuid(); | ||
const event: PersonenkontextCreatedEvent = new PersonenkontextCreatedEvent( | ||
fakePersonId, | ||
faker.string.uuid(), | ||
|
@@ -152,7 +147,14 @@ describe('Email Event Handler', () => { | |
serviceProviderRepoMock.findByIds.mockResolvedValueOnce(spMap); | ||
|
||
const emailAddresses: EmailAddress<true>[] = [ | ||
new EmailAddress<true>(emailId, faker.internet.email(), true), | ||
new EmailAddress<true>( | ||
emailAddressId, | ||
faker.date.past(), | ||
faker.date.recent(), | ||
fakePersonId, | ||
faker.internet.email(), | ||
true, | ||
), | ||
]; | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
emailRepoMock.findByPerson.mockImplementationOnce(async (personId: PersonID) => { | ||
|
@@ -168,7 +170,7 @@ describe('Email Event Handler', () => { | |
get currentAddress(): Option<string> { | ||
return '[email protected]'; | ||
}, | ||
id: emailId, | ||
personId: fakePersonId, | ||
emailAddresses: emailAddresses, | ||
}), | ||
}; | ||
|
@@ -187,7 +189,7 @@ describe('Email Event Handler', () => { | |
describe('when existing email is found but enabling results in error', () => { | ||
it('should log error', async () => { | ||
const fakePersonId: PersonID = faker.string.uuid(); | ||
const emailId: EmailID = faker.string.uuid(); | ||
const emailAddressId: EmailAddressID = faker.string.uuid(); | ||
const event: PersonenkontextCreatedEvent = new PersonenkontextCreatedEvent( | ||
fakePersonId, | ||
faker.string.uuid(), | ||
|
@@ -198,7 +200,14 @@ describe('Email Event Handler', () => { | |
serviceProviderRepoMock.findByIds.mockResolvedValueOnce(spMap); | ||
|
||
const emailAddresses: EmailAddress<true>[] = [ | ||
new EmailAddress<true>(emailId, faker.internet.email(), true), | ||
new EmailAddress<true>( | ||
emailAddressId, | ||
faker.date.past(), | ||
faker.date.recent(), | ||
fakePersonId, | ||
faker.internet.email(), | ||
true, | ||
), | ||
]; | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
emailRepoMock.findByPerson.mockImplementationOnce(async (personId: PersonID) => { | ||
|
@@ -239,7 +248,16 @@ describe('Email Event Handler', () => { | |
|
||
emailFactoryMock.createNew.mockImplementationOnce((personId: PersonID) => { | ||
const emailMock: DeepMocked<Email<false>> = createMock<Email<false>>({ | ||
emailAddresses: [new EmailAddress<false>(undefined, faker.internet.email(), true)], | ||
emailAddresses: [ | ||
new EmailAddress<false>( | ||
undefined, | ||
undefined, | ||
undefined, | ||
personId, | ||
faker.internet.email(), | ||
true, | ||
), | ||
], | ||
personId: personId, | ||
}); | ||
const emailAddress: EmailAddress<false> = createMock<EmailAddress<false>>({ | ||
|
@@ -374,8 +392,6 @@ describe('Email Event Handler', () => { | |
|
||
describe('when deletion is successful', () => { | ||
it('should log info', async () => { | ||
emailRepoMock.deleteById.mockResolvedValueOnce(true); | ||
|
||
await emailEventHandler.asyncPersonDeletedEventHandler(event); | ||
|
||
expect(loggerMock.info).toHaveBeenCalledWith(`Successfully deactivated email-address:${emailAddress}`); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,22 @@ | ||
import { BaseEntity, Entity, ManyToOne, PrimaryKeyProp, Property, Rel } from '@mikro-orm/core'; | ||
import { EmailEntity } from './email.entity.js'; | ||
import { Entity, ManyToOne, Property, Ref } from '@mikro-orm/core'; | ||
import { PersonEntity } from '../../person/persistence/person.entity.js'; | ||
import { TimestampedEntity } from '../../../persistence/timestamped.entity.js'; | ||
|
||
@Entity({ tableName: 'email_address' }) | ||
export class EmailAddressEntity extends BaseEntity { | ||
export class EmailAddressEntity extends TimestampedEntity { | ||
@ManyToOne({ | ||
columnType: 'uuid', | ||
fieldName: 'email_id', | ||
fieldName: 'person_id', | ||
ref: true, | ||
entity: () => EmailEntity, | ||
nullable: true, | ||
deleteRule: 'set null', | ||
entity: () => PersonEntity, | ||
}) | ||
public email!: Rel<EmailEntity>; | ||
public personId!: Ref<PersonEntity>; | ||
|
||
@Property({ primary: true, nullable: false, unique: true }) | ||
public address!: string; | ||
|
||
@Property({ nullable: false }) | ||
public enabled!: boolean; | ||
|
||
public [PrimaryKeyProp]?: ['address']; | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.