Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fdorantesm/ts-ddd
A Typescript Domain Driven Design library
https://github.com/fdorantesm/ts-ddd
clean-architecture clean-code ddd domain domain-driven-design entity software-architecture software-design software-engineering ts-ddd typescript uncle-bob value-object
Last synced: about 2 months ago
JSON representation
A Typescript Domain Driven Design library
- Host: GitHub
- URL: https://github.com/fdorantesm/ts-ddd
- Owner: fdorantesm
- License: mit
- Created: 2024-08-03T05:15:31.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2024-08-06T05:41:23.000Z (5 months ago)
- Last Synced: 2024-11-08T04:10:54.107Z (2 months ago)
- Topics: clean-architecture, clean-code, ddd, domain, domain-driven-design, entity, software-architecture, software-design, software-engineering, ts-ddd, typescript, uncle-bob, value-object
- Language: TypeScript
- Homepage: https://fdorantesm.github.io/ts-ddd
- Size: 95.7 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Typescript Domain-Driven Design
A set of utilities for Domain-Driven Design
## Packages
| Packages | Link |
| --------------------- | ----------------------------------------------------------------- |
| @ts-ddd/common | [Go to package](https://npmjs.com/package/@ts-ddd/common) |
| @ts-ddd/entity | [Go to package](https://npmjs.com/package/@ts-ddd/entity) |
| @ts-ddd/state-machine | [Go to package](https://npmjs.com/package/@ts-ddd/state-machine) |
| @ts-ddd/value-object | [Go to package](https://npmjs.com/package/@ts-ddd/value-object) |### Common
#### UUID generator
```ts
import { uuidGenerator } from '@ts-ddd/common';const uuid = uuidGenerator() // -> b9ebc3ea-bfbd-4a86-8b7b-39995b47c631
```#### Interfaces
| Interface | Properties |
| -------------- | ------------------------------------------ |
| WithActive | isActive |
| WithAudit | createdBy, updatedBy and deletedBy as date |
| WithDomain | domain |
| WithLocale | locale |
| WithNullable | isNullable |
| WithOwner | ownerId |
| WithScope | scope |
| WithStatus | status |
| WithTimestamps | createdAt and deletedAt |
| WithUser | userId |
| WithUuid | uuid |
| WithVersion | version |#### Example
```ts
interface Post extends WithActive, WithUuid {
title: string;
body: string;
}/*
{
uuid: string;
title: string;
body: string;
isActive: boolean;
}
*/
```### Entity
Use to create domain entities using an interface as contract.
```ts
export interface IBook {
id: Identifier;
name: string;
year: number;
publisher: string;
}```
```ts
import { uuidGenerator } from '@ts-ddd/common';
import { Identifier, Entity } from '@ts-ddd/entity';
import { IBook } from '../interfaces/book.interface';export class Book extends Entity {
public static createToPrimitives(payload: Omit) {
return new Book({
id: uuidGenerator(),
...payload
})
}
public static createFromPrimitives(payload: IBook): Book {
return new Book(payload)
}
}
```#### Getting an object from the data source
```ts
class BooksService {
constructor(private readonly booksRepository: BooksRepository) {}public async findBookById(id: string): Promise {
const book = await this.booksRepository.findOne({ id });if (book) {
return Book.createFromPrimitives(book)
}return undefined;
}
}
```#### Creating a book to store it in the data source
```ts
class CreateBookUseCase {
constructor(private readonly booksService: BooksService) {}public async execute(payload: Omit): Promise {
const book = await this.booksRepository.create(
Book.createToPrimitives(payload)
);return book;
}
}
```### State Machine
```ts
import { StateMachine } from '@ts-ddd/state-machine';enum LightTransitions {
RED = "red",
GREEN = "green",
PULSING_GREEN = "pulsing_green",
AMBER = "amber",
}const transitions = {
[LightTransitions.RED]: [LightTransitions.GREEN],
[LightTransitions.GREEN]: [LightTransitions.PULSING_GREEN],
[LightTransitions.PULSING_GREEN]: [LightTransitions.AMBER],
[LightTransitions.AMBER]: [LightTransitions.RED],
}const light = StateMachine.instance({
transitions,
currentState: LightTransitions.RED,
});try {
light.setState(LightTransitions.GREEN);
} catch (error) {
// InvalidStateTransitionException
}
```### Value Object
```ts
import { StringValue } from '@ts-ddd/value-object'
import { validate, v4 as uuid } from 'uuid';export class Uuid extends StringValue {
constructor(value: string) {
super(value);
this.ensureIsValidUuid(value);
}static generate(): Uuid {
return new Uuid(uuid());
}private ensureIsValidUuid(value: string): void {
if (!validate(value)) {
throw new Error(`${value} is not a valid UUID`)
}
}
}
``````ts
import { StringValue } from '@ts-ddd/value-object'export class Title extends StringValue {}
``````ts
import { PositiveNumberValue } from '@ts-ddd/value-object'export class Year extends PositiveNumberValue {}
``````ts
class BooksRepository {
public async getBook(id: string): Promise {
const book = await this.booksRepository.findOne({ id });if (!book) {
return undefined;
}return Book.createFromPrimitives({
id: new Uuid(book.id),
title: new Title(book.title),
year: new Year(book.year)
})
}
}
```
---