Merge branch 'registerWithId' into 'main'

Register with id

See merge request v3/service/user!41
This commit is contained in:
Sylvain Briat 2023-10-10 10:10:16 +00:00
commit e7c5f200f1
9 changed files with 47 additions and 10 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@mobicoop/user", "name": "@mobicoop/user",
"version": "1.0.0", "version": "1.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@mobicoop/user", "name": "@mobicoop/user",
"version": "1.0.0", "version": "1.1.0",
"license": "AGPL", "license": "AGPL",
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.8.0", "@grpc/grpc-js": "^1.8.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@mobicoop/user", "name": "@mobicoop/user",
"version": "1.0.0", "version": "1.1.0",
"description": "Mobicoop V3 User Service", "description": "Mobicoop V3 User Service",
"author": "sbriat", "author": "sbriat",
"private": true, "private": true,

View File

@ -1,6 +1,7 @@
import { Command, CommandProps } from '@mobicoop/ddd-library'; import { Command, CommandProps } from '@mobicoop/ddd-library';
export class CreateUserCommand extends Command { export class CreateUserCommand extends Command {
readonly userId?: string;
readonly firstName?: string; readonly firstName?: string;
readonly lastName?: string; readonly lastName?: string;
readonly email?: string; readonly email?: string;
@ -8,6 +9,7 @@ export class CreateUserCommand extends Command {
constructor(props: CommandProps<CreateUserCommand>) { constructor(props: CommandProps<CreateUserCommand>) {
super(props); super(props);
this.userId = props.userId;
this.firstName = props.firstName; this.firstName = props.firstName;
this.lastName = props.lastName; this.lastName = props.lastName;
this.email = props.email; this.email = props.email;

View File

@ -24,6 +24,7 @@ export class CreateUserService implements ICommandHandler {
async execute(command: CreateUserCommand): Promise<AggregateID> { async execute(command: CreateUserCommand): Promise<AggregateID> {
const user = UserEntity.create({ const user = UserEntity.create({
id: command.userId,
firstName: command.firstName, firstName: command.firstName,
lastName: command.lastName, lastName: command.lastName,
email: command.email, email: command.email,

View File

@ -9,7 +9,7 @@ export class UserEntity extends AggregateRoot<UserProps> {
protected readonly _id: AggregateID; protected readonly _id: AggregateID;
static create = (create: CreateUserProps): UserEntity => { static create = (create: CreateUserProps): UserEntity => {
const id = v4(); const id = create.id ?? v4();
const props: UserProps = { ...create }; const props: UserProps = { ...create };
const user = new UserEntity({ id, props }); const user = new UserEntity({ id, props });

View File

@ -8,6 +8,7 @@ export interface UserProps {
// Properties that are needed for a User creation // Properties that are needed for a User creation
export interface CreateUserProps { export interface CreateUserProps {
id?: string;
firstName?: string; firstName?: string;
lastName?: string; lastName?: string;
email?: string; email?: string;

View File

@ -24,10 +24,18 @@ export class CreateUserGrpcController {
constructor(private readonly commandBus: CommandBus) {} constructor(private readonly commandBus: CommandBus) {}
@GrpcMethod('UserService', 'Create') @GrpcMethod('UserService', 'Create')
async create(data: CreateUserRequestDto): Promise<IdResponse> { async create(
createUserRequestDto: CreateUserRequestDto,
): Promise<IdResponse> {
try { try {
const aggregateID: AggregateID = await this.commandBus.execute( const aggregateID: AggregateID = await this.commandBus.execute(
new CreateUserCommand(data), new CreateUserCommand({
firstName: createUserRequestDto.firstName,
lastName: createUserRequestDto.lastName,
email: createUserRequestDto.email,
phone: createUserRequestDto.phone,
userId: createUserRequestDto.id,
}),
); );
return new IdResponse(aggregateID); return new IdResponse(aggregateID);
} catch (error: any) { } catch (error: any) {

View File

@ -1,13 +1,23 @@
import { IsEmail, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; import {
IsEmail,
IsOptional,
IsPhoneNumber,
IsString,
IsUUID,
} from 'class-validator';
export class CreateUserRequestDto { export class CreateUserRequestDto {
@IsString() @IsUUID(4)
@IsOptional() @IsOptional()
firstName: string; id?: string;
@IsString() @IsString()
@IsOptional() @IsOptional()
lastName: string; firstName?: string;
@IsString()
@IsOptional()
lastName?: string;
@IsEmail() @IsEmail()
@IsOptional() @IsOptional()

View File

@ -14,6 +14,14 @@ const createUserProps: CreateUserProps = {
phone: '+33611223344', phone: '+33611223344',
}; };
const createUserPropsWithId: CreateUserProps = {
id: '66378860-cb75-40de-b6eb-061faf923fee',
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@email.com',
phone: '+33611223344',
};
const updateUserProps: UpdateUserProps = { const updateUserProps: UpdateUserProps = {
firstName: 'Jane', firstName: 'Jane',
lastName: 'Dane', lastName: 'Dane',
@ -28,6 +36,13 @@ describe('User entity create', () => {
expect(userEntity.domainEvents.length).toBe(1); expect(userEntity.domainEvents.length).toBe(1);
expect(userEntity.domainEvents[0]).toBeInstanceOf(UserCreatedDomainEvent); expect(userEntity.domainEvents[0]).toBeInstanceOf(UserCreatedDomainEvent);
}); });
it('should create a new user entity with a given id', async () => {
const userEntity: UserEntity = UserEntity.create(createUserPropsWithId);
expect(userEntity.id).toBe('66378860-cb75-40de-b6eb-061faf923fee');
expect(userEntity.getProps().email).toBe('john.doe@email.com');
expect(userEntity.domainEvents.length).toBe(1);
expect(userEntity.domainEvents[0]).toBeInstanceOf(UserCreatedDomainEvent);
});
}); });
describe('User entity update', () => { describe('User entity update', () => {