extract config files
This commit is contained in:
parent
376260d903
commit
f960299565
18
.env.dist
18
.env.dist
|
@ -10,3 +10,21 @@ DATABASE_URL="postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=configur
|
|||
MESSAGE_BROKER_URI=amqp://v3-broker:5672
|
||||
MESSAGE_BROKER_EXCHANGE=mobicoop
|
||||
MESSAGE_BROKER_EXCHANGE_DURABILITY=true
|
||||
|
||||
|
||||
# DEFAULT CONFIGURATION
|
||||
|
||||
# CARPOOL
|
||||
# default carpool departure time margin (in seconds)
|
||||
DEPARTURE_TIME_MARGIN=900
|
||||
# default role
|
||||
ROLE=passenger
|
||||
# seats proposed as driver / requested as passenger
|
||||
SEATS_PROPOSED=3
|
||||
SEATS_REQUESTED=1
|
||||
# accept only same frequency requests
|
||||
STRICT_FREQUENCY=false
|
||||
|
||||
# PAGINATION
|
||||
# number of results per page
|
||||
PER_PAGE=10
|
||||
|
|
|
@ -2687,6 +2687,12 @@
|
|||
"pretty-format": "^29.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-yaml": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.8.tgz",
|
||||
"integrity": "sha512-m6jnPk1VhlYRiLFm3f8X9Uep761f+CK8mHyS65LutH2OhmBF0BeMEjHgg05usH8PLZMWWc/BUR9RPmkvpWnyRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
|
||||
|
@ -5559,20 +5565,6 @@
|
|||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
|
|
|
@ -16,10 +16,24 @@ import { MESSAGE_PUBLISHER } from '@modules/messager/messager.di-tokens';
|
|||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||
import { ConfigurationModule } from '@modules/configuration/configuration.module';
|
||||
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||
import brokerConfig from './config/broker.config';
|
||||
import carpoolConfig from './config/carpool.config';
|
||||
import databaseConfig from './config/database.config';
|
||||
import paginationConfig from './config/pagination.config';
|
||||
import serviceConfig from './config/service.config';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({ isGlobal: true }),
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
load: [
|
||||
brokerConfig,
|
||||
carpoolConfig,
|
||||
databaseConfig,
|
||||
paginationConfig,
|
||||
serviceConfig,
|
||||
],
|
||||
}),
|
||||
EventEmitterModule.forRoot(),
|
||||
HealthModule.forRootAsync({
|
||||
imports: [ConfigurationModule, MessagerModule],
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('broker', () => ({
|
||||
uri: process.env.MESSAGE_BROKER_URI ?? 'amqp://v3-broker:5672',
|
||||
exchange: process.env.MESSAGE_BROKER_EXCHANGE ?? 'mobicoop',
|
||||
durability: process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY
|
||||
? process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY === 'false'
|
||||
? false
|
||||
: true
|
||||
: true,
|
||||
}));
|
|
@ -0,0 +1,19 @@
|
|||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('carpool', () => ({
|
||||
departureTimeMargin: process.env.DEPARTURE_TIME_MARGIN
|
||||
? parseInt(process.env.DEPARTURE_TIME_MARGIN, 10)
|
||||
: 900,
|
||||
role: process.env.ROLE ?? 'passenger',
|
||||
seatsProposed: process.env.SEATS_PROPOSED
|
||||
? parseInt(process.env.SEATS_PROPOSED, 10)
|
||||
: 3,
|
||||
seatsRequested: process.env.SEATS_REQUESTED
|
||||
? parseInt(process.env.SEATS_REQUESTED, 10)
|
||||
: 1,
|
||||
strictFrequency: process.env.STRICT_FREQUENCY
|
||||
? process.env.STRICT_FREQUENCY === 'false'
|
||||
? false
|
||||
: true
|
||||
: false,
|
||||
}));
|
|
@ -0,0 +1,7 @@
|
|||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('database', () => ({
|
||||
url:
|
||||
process.env.DATABASE_URL ??
|
||||
'postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=configuration',
|
||||
}));
|
|
@ -0,0 +1,5 @@
|
|||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('pagination', () => ({
|
||||
perPage: process.env.PER_PAGE ? parseInt(process.env.PER_PAGE, 10) : 10,
|
||||
}));
|
|
@ -0,0 +1,8 @@
|
|||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('service', () => ({
|
||||
url: process.env.SERVICE_URL ?? '0.0.0.0',
|
||||
port: process.env.SERVICE_PORT
|
||||
? parseInt(process.env.SERVICE_PORT, 10)
|
||||
: 5003,
|
||||
}));
|
|
@ -6,6 +6,10 @@ import {
|
|||
ConfigurationWriteModel,
|
||||
} from './infrastructure/configuration.repository';
|
||||
import { ConfigurationResponseDto } from './interface/dtos/configuration.response.dto';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from './core/domain/configuration.types';
|
||||
|
||||
/**
|
||||
* Mapper constructs objects that are used in different layers:
|
||||
|
@ -28,9 +32,10 @@ export class ConfigurationMapper
|
|||
const copy = entity.getProps();
|
||||
const record: ConfigurationWriteModel = {
|
||||
uuid: entity.id,
|
||||
domain: copy.domain,
|
||||
key: copy.key,
|
||||
domain: copy.identifier.domain,
|
||||
key: copy.identifier.key,
|
||||
value: copy.value,
|
||||
type: copy.type,
|
||||
};
|
||||
return record;
|
||||
};
|
||||
|
@ -41,9 +46,12 @@ export class ConfigurationMapper
|
|||
createdAt: new Date(record.createdAt),
|
||||
updatedAt: new Date(record.updatedAt),
|
||||
props: {
|
||||
domain: record.domain,
|
||||
identifier: {
|
||||
domain: record.domain as ConfigurationDomain,
|
||||
key: record.key,
|
||||
},
|
||||
value: record.value,
|
||||
type: record.type as ConfigurationType,
|
||||
},
|
||||
});
|
||||
return entity;
|
||||
|
@ -52,9 +60,10 @@ export class ConfigurationMapper
|
|||
toResponse = (entity: ConfigurationEntity): ConfigurationResponseDto => {
|
||||
const props = entity.getProps();
|
||||
const response = new ConfigurationResponseDto(entity);
|
||||
response.domain = props.domain;
|
||||
response.key = props.key;
|
||||
response.domain = props.identifier.domain;
|
||||
response.key = props.identifier.key;
|
||||
response.value = props.value;
|
||||
response.type = props.type;
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import { SetConfigurationCommand } from './set-configuration.command';
|
|||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||
import { ConfigurationRepositoryPort } from '../../ports/configuration.repository.port';
|
||||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
|
||||
@CommandHandler(SetConfigurationCommand)
|
||||
export class SetConfigurationService implements ICommandHandler {
|
||||
|
@ -29,7 +33,14 @@ export class SetConfigurationService implements ICommandHandler {
|
|||
} catch (error: any) {
|
||||
if (error instanceof NotFoundException) {
|
||||
try {
|
||||
const newConfiguration = ConfigurationEntity.create(command);
|
||||
const newConfiguration = ConfigurationEntity.create({
|
||||
identifier: {
|
||||
domain: command.domain as ConfigurationDomain,
|
||||
key: command.key,
|
||||
},
|
||||
value: command.value,
|
||||
type: ConfigurationType.STRING,
|
||||
});
|
||||
await this.repository.insert(newConfiguration);
|
||||
return newConfiguration.id;
|
||||
} catch (error: any) {
|
||||
|
|
|
@ -21,8 +21,8 @@ export class PublishMessageWhenConfigurationIsDeletedDomainEventHandler {
|
|||
const configurationDeletedIntegrationEvent =
|
||||
new ConfigurationDeletedIntegrationEvent({
|
||||
id: event.aggregateId,
|
||||
domain: event.domain,
|
||||
key: event.key,
|
||||
domain: event.identifier.domain,
|
||||
key: event.identifier.key,
|
||||
metadata: event.metadata,
|
||||
});
|
||||
this.messagePublisher.publish(
|
||||
|
|
|
@ -18,8 +18,8 @@ export class PublishMessageWhenConfigurationIsSetDomainEventHandler {
|
|||
const configurationSetIntegrationEvent =
|
||||
new ConfigurationSetIntegrationEvent({
|
||||
id: event.aggregateId,
|
||||
domain: event.domain,
|
||||
key: event.key,
|
||||
domain: event.identifier.domain,
|
||||
key: event.identifier.key,
|
||||
value: event.value,
|
||||
metadata: event.metadata,
|
||||
});
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
ConfigurationItems,
|
||||
} from './configuration.types';
|
||||
|
||||
export const configurationItems: ConfigurationItems = {
|
||||
[ConfigurationDomain.CARPOOL]: {
|
||||
seatsProposed: {
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
seatsRequested: {
|
||||
value: '1',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
strictFrequency: {
|
||||
value: 'false',
|
||||
type: ConfigurationType.BOOLEAN,
|
||||
},
|
||||
departureTimeMargin: {
|
||||
value: '900',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
role: {
|
||||
value: 'passenger',
|
||||
type: ConfigurationType.STRING,
|
||||
enum: ['driver', 'passenger'],
|
||||
},
|
||||
},
|
||||
[ConfigurationDomain.USER]: {},
|
||||
};
|
|
@ -18,9 +18,9 @@ export class ConfigurationEntity extends AggregateRoot<ConfigurationProps> {
|
|||
configuration.addEvent(
|
||||
new ConfigurationSetDomainEvent({
|
||||
aggregateId: id,
|
||||
domain: props.domain,
|
||||
key: props.key,
|
||||
identifier: props.identifier,
|
||||
value: props.value,
|
||||
type: props.type,
|
||||
}),
|
||||
);
|
||||
return configuration;
|
||||
|
@ -31,9 +31,9 @@ export class ConfigurationEntity extends AggregateRoot<ConfigurationProps> {
|
|||
this.addEvent(
|
||||
new ConfigurationSetDomainEvent({
|
||||
aggregateId: this._id,
|
||||
domain: this.props.domain,
|
||||
key: this.props.key,
|
||||
identifier: this.props.identifier,
|
||||
value: props.value,
|
||||
type: this.props.type,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -42,8 +42,7 @@ export class ConfigurationEntity extends AggregateRoot<ConfigurationProps> {
|
|||
this.addEvent(
|
||||
new ConfigurationDeletedDomainEvent({
|
||||
aggregateId: this.id,
|
||||
domain: this.props.domain,
|
||||
key: this.props.key,
|
||||
identifier: this.props.identifier,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,23 +1,48 @@
|
|||
// All properties that a Configuration has
|
||||
export interface ConfigurationProps {
|
||||
domain: string;
|
||||
key: string;
|
||||
value: string;
|
||||
identifier: ConfigurationIdentifier;
|
||||
value: ConfigurationValue;
|
||||
type: ConfigurationType;
|
||||
}
|
||||
|
||||
// Properties that are needed for a Configuration creation
|
||||
export interface CreateConfigurationProps {
|
||||
domain: string;
|
||||
key: string;
|
||||
value: string;
|
||||
identifier: ConfigurationIdentifier;
|
||||
value: ConfigurationValue;
|
||||
type: ConfigurationType;
|
||||
}
|
||||
|
||||
export interface UpdateConfigurationProps {
|
||||
value: string;
|
||||
value: ConfigurationValue;
|
||||
}
|
||||
|
||||
export enum Domain {
|
||||
AD = 'AD',
|
||||
MATCHER = 'MATCHER',
|
||||
export enum ConfigurationDomain {
|
||||
CARPOOL = 'CARPOOL',
|
||||
USER = 'USER',
|
||||
}
|
||||
|
||||
export enum ConfigurationType {
|
||||
BOOLEAN = 'BOOLEAN',
|
||||
NUMBER = 'NUMBER',
|
||||
STRING = 'STRING',
|
||||
}
|
||||
|
||||
export type ConfigurationIdentifier = {
|
||||
domain: ConfigurationDomain;
|
||||
key: ConfigurationKey;
|
||||
};
|
||||
|
||||
export type ConfigurationKey = string;
|
||||
export type ConfigurationValue = string;
|
||||
|
||||
export type ConfigurationItems = Record<
|
||||
ConfigurationDomain,
|
||||
Record<
|
||||
ConfigurationKey,
|
||||
{
|
||||
value: ConfigurationValue;
|
||||
type: ConfigurationType;
|
||||
enum?: Array<string>;
|
||||
}
|
||||
>
|
||||
>;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
|
||||
import { ConfigurationIdentifier } from '../configuration.types';
|
||||
|
||||
export class ConfigurationDeletedDomainEvent extends DomainEvent {
|
||||
readonly domain: string;
|
||||
readonly key: string;
|
||||
readonly identifier: ConfigurationIdentifier;
|
||||
|
||||
constructor(props: DomainEventProps<ConfigurationDeletedDomainEvent>) {
|
||||
super(props);
|
||||
this.domain = props.domain;
|
||||
this.key = props.key;
|
||||
this.identifier = props.identifier;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
|
||||
import {
|
||||
ConfigurationIdentifier,
|
||||
ConfigurationType,
|
||||
ConfigurationValue,
|
||||
} from '../configuration.types';
|
||||
|
||||
export class ConfigurationSetDomainEvent extends DomainEvent {
|
||||
readonly domain: string;
|
||||
readonly key: string;
|
||||
readonly value: string;
|
||||
readonly identifier: ConfigurationIdentifier;
|
||||
readonly value: ConfigurationValue;
|
||||
readonly type: ConfigurationType;
|
||||
|
||||
constructor(props: DomainEventProps<ConfigurationSetDomainEvent>) {
|
||||
super(props);
|
||||
this.domain = props.domain;
|
||||
this.key = props.key;
|
||||
this.identifier = props.identifier;
|
||||
this.type = props.type;
|
||||
this.value = props.value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ export type ConfigurationBaseModel = {
|
|||
domain: string;
|
||||
key: string;
|
||||
value: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type ConfigurationReadModel = ConfigurationBaseModel & {
|
||||
|
|
|
@ -4,4 +4,5 @@ export class ConfigurationResponseDto extends ResponseBase {
|
|||
domain: string;
|
||||
key: string;
|
||||
value: string;
|
||||
type: string;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class DeleteConfigurationRequestDto {
|
||||
@IsEnum(Domain)
|
||||
@IsEnum(ConfigurationDomain)
|
||||
@IsNotEmpty()
|
||||
domain: Domain;
|
||||
domain: ConfigurationDomain;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class GetConfigurationRequestDto {
|
||||
@IsEnum(Domain)
|
||||
@IsEnum(ConfigurationDomain)
|
||||
@IsNotEmpty()
|
||||
domain: Domain;
|
||||
domain: ConfigurationDomain;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class SetConfigurationRequestDto {
|
||||
@IsEnum(Domain)
|
||||
@IsEnum(ConfigurationDomain)
|
||||
@IsNotEmpty()
|
||||
domain: Domain;
|
||||
domain: ConfigurationDomain;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
|
|
@ -6,7 +6,7 @@ import { ConfigurationMapper } from '@modules/configuration/configuration.mapper
|
|||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
import {
|
||||
CreateConfigurationProps,
|
||||
Domain,
|
||||
ConfigurationDomain,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationRepository } from '@modules/configuration/infrastructure/configuration.repository';
|
||||
import { PrismaService } from '@modules/configuration/infrastructure/prisma.service';
|
||||
|
@ -36,7 +36,7 @@ describe('Configuration Repository', () => {
|
|||
for (let i = 0; i < nbToCreate; i++) {
|
||||
const configurationToCreate = {
|
||||
uuid: getSeed(i, baseUuid.uuid),
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: `key${i}`,
|
||||
value: `value${i}`,
|
||||
createdAt: '2023-07-24 13:07:05.000',
|
||||
|
@ -98,7 +98,7 @@ describe('Configuration Repository', () => {
|
|||
it('should return a configuration', async () => {
|
||||
await createConfigurations(1);
|
||||
const result = await configurationRepository.findOne({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: 'key0',
|
||||
});
|
||||
expect(result.getProps().value).toBe('value0');
|
||||
|
@ -119,7 +119,7 @@ describe('Configuration Repository', () => {
|
|||
const beforeCount = await prismaService.configuration.count();
|
||||
|
||||
const createConfigurationProps: CreateConfigurationProps = {
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: 'seatsProposed',
|
||||
value: '3',
|
||||
};
|
||||
|
@ -139,7 +139,7 @@ describe('Configuration Repository', () => {
|
|||
await createConfigurations(1);
|
||||
const configurationToUpdate: ConfigurationEntity =
|
||||
await configurationRepository.findOne({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: 'key0',
|
||||
});
|
||||
configurationToUpdate.update({ value: 'newValue' });
|
||||
|
@ -149,7 +149,7 @@ describe('Configuration Repository', () => {
|
|||
);
|
||||
const result: ConfigurationEntity = await configurationRepository.findOne(
|
||||
{
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: 'key0',
|
||||
},
|
||||
);
|
||||
|
@ -163,7 +163,7 @@ describe('Configuration Repository', () => {
|
|||
const beforeCount = await prismaService.configuration.count();
|
||||
const configurationToDelete: ConfigurationEntity =
|
||||
await configurationRepository.findOne({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.AD,
|
||||
key: 'key4',
|
||||
});
|
||||
await configurationRepository.delete(configurationToDelete);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
||||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationReadModel,
|
||||
ConfigurationWriteModel,
|
||||
|
@ -12,9 +15,12 @@ const now = new Date('2023-06-21 06:00:00');
|
|||
const configurationEntity: ConfigurationEntity = new ConfigurationEntity({
|
||||
id: 'c160cf8c-f057-4962-841f-3ad68346df44',
|
||||
props: {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
@ -24,6 +30,7 @@ const configurationReadModel: ConfigurationReadModel = {
|
|||
domain: 'AD',
|
||||
key: 'seatsProposed',
|
||||
value: '4',
|
||||
type: 'NUMBER',
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
import {
|
||||
CreateConfigurationProps,
|
||||
Domain,
|
||||
ConfigurationDomain,
|
||||
UpdateConfigurationProps,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDeletedDomainEvent } from '@modules/configuration/core/domain/events/configuration-deleted.domain-event';
|
||||
import { ConfigurationSetDomainEvent } from '@modules/configuration/core/domain/events/configuration-set.domain-event';
|
||||
|
||||
const createConfigurationProps: CreateConfigurationProps = {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
};
|
||||
|
||||
const updateConfigurationProps: UpdateConfigurationProps = {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||
import { DeleteConfigurationCommand } from '@modules/configuration/core/application/commands/delete-configuration/delete-configuration.command';
|
||||
import { DeleteConfigurationService } from '@modules/configuration/core/application/commands/delete-configuration/delete-configuration.service';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { DeleteConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/delete-configuration.request.dto';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const deleteConfigurationRequest: DeleteConfigurationRequestDto = {
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { GetConfigurationQueryHandler } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler';
|
||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||
import { GetConfigurationQuery } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query';
|
||||
|
@ -9,9 +12,12 @@ const now = new Date('2023-06-21 06:00:00');
|
|||
const configuration: ConfigurationEntity = new ConfigurationEntity({
|
||||
id: 'c160cf8c-f057-4962-841f-3ad68346df44',
|
||||
props: {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
@ -47,7 +53,7 @@ describe('Get Configuration Query Handler', () => {
|
|||
describe('execution', () => {
|
||||
it('should return a configuration item', async () => {
|
||||
const getConfigurationQuery = new GetConfigurationQuery(
|
||||
Domain.AD,
|
||||
ConfigurationDomain.CARPOOL,
|
||||
'seatsProposed',
|
||||
);
|
||||
const configuration: ConfigurationEntity =
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
CONFIGURATION_MESSAGE_PUBLISHER,
|
||||
CONFIGURATION_REPOSITORY,
|
||||
|
@ -17,9 +20,12 @@ const configurationEntities = [
|
|||
new ConfigurationEntity({
|
||||
id: '047a6ecf-23d4-4d3e-877c-3225d560a8da',
|
||||
props: {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
createdAt: new Date('2023-10-23T07:00:00Z'),
|
||||
updatedAt: new Date('2023-10-23T07:00:00Z'),
|
||||
|
@ -27,9 +33,12 @@ const configurationEntities = [
|
|||
new ConfigurationEntity({
|
||||
id: '047a6ecf-23d4-4d3e-877c-3225d560a8db',
|
||||
props: {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsRequested',
|
||||
},
|
||||
value: '1',
|
||||
type: ConfigurationType.NUMBER,
|
||||
},
|
||||
createdAt: new Date('2023-10-23T07:00:00Z'),
|
||||
updatedAt: new Date('2023-10-23T07:00:00Z'),
|
||||
|
@ -40,14 +49,16 @@ const mockConfigurationMapper = {
|
|||
toResponse: jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => ({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
}))
|
||||
.mockImplementationOnce(() => ({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsRequested',
|
||||
value: '1',
|
||||
type: ConfigurationType.NUMBER,
|
||||
})),
|
||||
};
|
||||
|
||||
|
@ -93,7 +104,7 @@ describe('Propagate Configurations Service', () => {
|
|||
expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1);
|
||||
expect(mockMessagePublisher.publish).toHaveBeenCalledWith(
|
||||
CONFIGURATION_PROPAGATED_ROUTING_KEY,
|
||||
'[{"domain":"AD","key":"seatsProposed","value":"3"},{"domain":"AD","key":"seatsRequested","value":"1"}]',
|
||||
'[{"domain":"CARPOOL","key":"seatsProposed","value":"3","type":"NUMBER"},{"domain":"CARPOOL","key":"seatsRequested","value":"1","type":"NUMBER"}]',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { CONFIGURATION_MESSAGE_PUBLISHER } from '@modules/configuration/configuration.di-tokens';
|
||||
import { PublishMessageWhenConfigurationIsDeletedDomainEventHandler } from '@modules/configuration/core/application/event-handlers/publish-message-when-configuration-is-deleted.domain-event-handler';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDeletedDomainEvent } from '@modules/configuration/core/domain/events/configuration-deleted.domain-event';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CONFIGURATION_DELETED_ROUTING_KEY } from '@src/app.constants';
|
||||
|
@ -33,8 +33,10 @@ describe('Publish message when configuration is deleted domain event handler', (
|
|||
jest.spyOn(mockMessagePublisher, 'publish');
|
||||
const configurationDeletedDomainEvent: ConfigurationDeletedDomainEvent = {
|
||||
id: 'some-domain-event-id',
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
aggregateId: 'some-aggregate-id',
|
||||
metadata: {
|
||||
timestamp: new Date('2023-06-28T05:00:00Z').getTime(),
|
||||
|
@ -50,7 +52,7 @@ describe('Publish message when configuration is deleted domain event handler', (
|
|||
expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1);
|
||||
expect(mockMessagePublisher.publish).toHaveBeenCalledWith(
|
||||
CONFIGURATION_DELETED_ROUTING_KEY,
|
||||
'{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"domain":"AD","key":"seatsProposed"}',
|
||||
'{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"domain":"CARPOOL","key":"seatsProposed"}',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { CONFIGURATION_MESSAGE_PUBLISHER } from '@modules/configuration/configuration.di-tokens';
|
||||
import { PublishMessageWhenConfigurationIsSetDomainEventHandler } from '@modules/configuration/core/application/event-handlers/publish-message-when-configuration-is-set.domain-event-handler';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationSetDomainEvent } from '@modules/configuration/core/domain/events/configuration-set.domain-event';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CONFIGURATION_SET_ROUTING_KEY } from '@src/app.constants';
|
||||
|
@ -34,8 +37,11 @@ describe('Publish message when configuration is set domain event handler', () =>
|
|||
const configurationSetDomainEvent: ConfigurationSetDomainEvent = {
|
||||
id: 'some-domain-event-id',
|
||||
aggregateId: 'some-aggregate-id',
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
type: ConfigurationType.NUMBER,
|
||||
value: '3',
|
||||
metadata: {
|
||||
timestamp: new Date('2023-06-28T05:00:00Z').getTime(),
|
||||
|
@ -51,7 +57,7 @@ describe('Publish message when configuration is set domain event handler', () =>
|
|||
expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1);
|
||||
expect(mockMessagePublisher.publish).toHaveBeenCalledWith(
|
||||
CONFIGURATION_SET_ROUTING_KEY,
|
||||
'{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"domain":"AD","key":"seatsProposed","value":"3"}',
|
||||
'{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"domain":"CARPOOL","key":"seatsProposed","value":"3"}',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AggregateID, NotFoundException } from '@mobicoop/ddd-library';
|
||||
import { SetConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { SetConfigurationService } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.service';
|
||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||
import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command';
|
||||
import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity';
|
||||
|
||||
const setConfigurationRequest: SetConfigurationRequestDto = {
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
value: '3',
|
||||
};
|
||||
|
@ -16,8 +19,11 @@ const setConfigurationRequest: SetConfigurationRequestDto = {
|
|||
const existingConfigurationEntity = new ConfigurationEntity({
|
||||
id: '047a6ecf-23d4-4d3e-877c-3225d560a8da',
|
||||
props: {
|
||||
domain: Domain.AD,
|
||||
identifier: {
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
},
|
||||
type: ConfigurationType.NUMBER,
|
||||
value: '2',
|
||||
},
|
||||
createdAt: new Date('2023-10-23T07:00:00Z'),
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
NotFoundException,
|
||||
} from '@mobicoop/ddd-library';
|
||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { DeleteConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/delete-configuration.grpc.controller';
|
||||
import { DeleteConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/delete-configuration.request.dto';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
|
@ -11,7 +11,7 @@ import { RpcException } from '@nestjs/microservices';
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const deleteConfigurationRequest: DeleteConfigurationRequestDto = {
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { NotFoundException } from '@mobicoop/ddd-library';
|
||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationType,
|
||||
} from '@modules/configuration/core/domain/configuration.types';
|
||||
import { GetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller';
|
||||
import { QueryBus } from '@nestjs/cqrs';
|
||||
import { RpcException } from '@nestjs/microservices';
|
||||
|
@ -21,9 +24,10 @@ const mockQueryBus = {
|
|||
|
||||
const mockConfigurationMapper = {
|
||||
toResponse: jest.fn().mockImplementationOnce(() => ({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
value: '3',
|
||||
type: ConfigurationType.NUMBER,
|
||||
})),
|
||||
};
|
||||
|
||||
|
@ -62,7 +66,7 @@ describe('Get Configuration Grpc Controller', () => {
|
|||
jest.spyOn(mockQueryBus, 'execute');
|
||||
jest.spyOn(mockConfigurationMapper, 'toResponse');
|
||||
const response = await getConfigurationGrpcController.get({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
});
|
||||
expect(response.value).toBe('3');
|
||||
|
@ -76,7 +80,7 @@ describe('Get Configuration Grpc Controller', () => {
|
|||
expect.assertions(4);
|
||||
try {
|
||||
await getConfigurationGrpcController.get({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'price',
|
||||
});
|
||||
} catch (e: any) {
|
||||
|
@ -93,7 +97,7 @@ describe('Get Configuration Grpc Controller', () => {
|
|||
expect.assertions(4);
|
||||
try {
|
||||
await getConfigurationGrpcController.get({
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'someValue',
|
||||
});
|
||||
} catch (e: any) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { IdResponse } from '@mobicoop/ddd-library';
|
||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { Domain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types';
|
||||
import { SetConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto';
|
||||
import { SetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
|
@ -8,7 +8,7 @@ import { RpcException } from '@nestjs/microservices';
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const setConfigurationRequest: SetConfigurationRequestDto = {
|
||||
domain: Domain.AD,
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: 'seatsProposed',
|
||||
value: '3',
|
||||
};
|
||||
|
|
|
@ -16,12 +16,10 @@ const imports = [
|
|||
useFactory: async (
|
||||
configService: ConfigService,
|
||||
): Promise<MessageBrokerModuleOptions> => ({
|
||||
uri: configService.get<string>('MESSAGE_BROKER_URI') as string,
|
||||
uri: configService.get<string>('broker.uri') as string,
|
||||
exchange: {
|
||||
name: configService.get<string>('MESSAGE_BROKER_EXCHANGE') as string,
|
||||
durable: configService.get<boolean>(
|
||||
'MESSAGE_BROKER_EXCHANGE_DURABILITY',
|
||||
) as boolean,
|
||||
name: configService.get<string>('broker.exchange') as string,
|
||||
durable: configService.get<boolean>('broker.durability') as boolean,
|
||||
},
|
||||
name: SERVICE_NAME,
|
||||
}),
|
||||
|
|
Loading…
Reference in New Issue