Skip to content

Instantly share code, notes, and snippets.

@musou1500
Created November 6, 2020 16:20
Show Gist options
  • Save musou1500/596adf81aaa79e65e356eb6ea5e634bc to your computer and use it in GitHub Desktop.
Save musou1500/596adf81aaa79e65e356eb6ea5e634bc to your computer and use it in GitHub Desktop.
/**
* domain module
* UserAggregate
* - (Aggregate Root) User
* - (Aggregate Root) UserQuota
*/
export class User {
#organizationId: number;
#name: string;
constructor(organizationId: number, name: string) {
this.#organizationId = organizationId;
this.#name = name;
}
get organizationId() {
return this.#organizationId;
}
get name() {
return this.#name;
}
}
export interface UserRepository {
save(user: User): Promise<User>;
countUserInOrganization(organizationId: number): Promise<number>;
}
export interface UserQuotaRepository {
lock(organizationId: number): Promise<number>;
}
export class ReachedToUserQuota extends Error {
name = "ReachedToUserQuota";
}
// domain service to add user
export const addUser = async (
userQuotaRepository: UserQuotaRepository,
userRepository: UserRepository,
user: User
): Promise<User> => {
const quota = await userQuotaRepository.lock(user.organizationId);
const count = await userRepository.countUserInOrganization(
user.organizationId
);
if (count + 1 > quota) {
throw new ReachedToUserQuota();
}
return userRepository.save(user);
};
/**
* application module
* - AddUserUseCase
*/
export interface AddUserRequest {
name: string;
organizationId: number;
}
export interface RepositoryFactory {
userRepository(): UserRepository;
userQuotaRepository(): UserQuotaRepository;
}
export interface Transaction {
run<T>(fn: (factory: RepositoryFactory) => Promise<T>): Promise<T>;
}
export class AddUserUseCase {
#transaction: Transaction;
constructor(transaction: Transaction) {
this.#transaction = transaction;
}
addUser({ name, organizationId }: AddUserRequest): Promise<User> {
return this.#transaction.run(({ userRepository, userQuotaRepository }) =>
addUser(
userQuotaRepository(),
userRepository(),
new User(organizationId, name)
)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment