├── .gitignore ├── README.MD ├── assets └── camadas.png ├── behavioral-patterns ├── chain-of-responsibility.ts ├── observe.ts └── strategy.ts ├── creational-patterns ├── abstract-factory.ts ├── builder.ts ├── factory-method.ts └── singleton.ts ├── demo └── students │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── nest-cli.json │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── app.module.ts │ ├── main.ts │ └── students │ │ ├── controllers │ │ └── student.controller.ts │ │ ├── dtos │ │ └── student.dto.ts │ │ ├── entities │ │ └── student.entity.ts │ │ ├── repositories │ │ ├── student-repository.interface.ts │ │ └── student-respository.service.ts │ │ ├── service │ │ └── student.service.ts │ │ └── students.module.ts │ ├── students.module.ts │ ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json │ ├── tsconfig.build.json │ └── tsconfig.json └── structural-patterns ├── adapter.ts ├── bridge.ts └── facade.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | /build 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | pnpm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | 15 | # OS 16 | .DS_Store 17 | 18 | # Tests 19 | /coverage 20 | /.nyc_output 21 | 22 | # IDEs and editors 23 | /.idea 24 | .project 25 | .classpath 26 | .c9/ 27 | *.launch 28 | .settings/ 29 | *.sublime-workspace 30 | 31 | # IDE - VSCode 32 | .vscode/* 33 | !.vscode/settings.json 34 | !.vscode/tasks.json 35 | !.vscode/launch.json 36 | !.vscode/extensions.json 37 | 38 | # dotenv environment variable files 39 | .env 40 | .env.development.local 41 | .env.test.local 42 | .env.production.local 43 | .env.local 44 | 45 | # temp directory 46 | .temp 47 | .tmp 48 | 49 | # Runtime data 50 | pids 51 | *.pid 52 | *.seed 53 | *.pid.lock 54 | 55 | # Diagnostic reports (https://nodejs.org/api/report.html) 56 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 57 | 58 | .DS_Store 59 | /demo/.DS_Store 60 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | --- 2 | presentation: 3 | width: 1500 4 | height: 800 5 | theme: night.css 6 | --- 7 | 8 | 9 | # Design Patterns 10 | 11 | São métodos para resolver problemas recorrentes, agindo como guias para estruturar o código de forma eficiente. Eles não são códigos prontos, mas diretrizes para criar soluções adaptáveis 12 | 13 | 14 | 15 | 16 | ## MVC 17 | 18 | - O padrão mvc tem o principio de dividir o projeto em camadas logicas, para separar as responsabilidades da aplicação. 19 | 20 | - Ele pode ser divido nas camadas : 21 | - Controladora que é responsável por receber as requisições , recebe as interações do client e passar para camada de serviço 22 | - Camada de Serviço que é responsável por orquestrar a lógica de negócio e passar as informações para camada de acesso a dados 23 | - A camada de acesso a dados que é responsável por se comunicar com o banco de dados e fazer as operações 24 | - Nos temos as entidades que são os objetos responsáveis para manter a integridade dos dados que serão salvos 25 | 26 | 27 | 28 | ## Diagrama MVC (Camadas) 29 | 30 | ![MVC](https://raw.githubusercontent.com/GustavoLima93/ts-class-design-patterns/main/assets/camadas.png) 31 | 32 | 33 | 34 | ## Inversão de controle 35 | 36 | Inversão de controle significa delegar as responsabilidades: ao invés de gerenciar todos os detalhes, o controle é transferido para entidades externas, otimizando a gestão e fluxo do processo. 37 | 38 | 39 | 40 | ## Repository 41 | 42 | O padrão Repository abstrai a camada de acesso a dados, facilitando a modularização e teste do código. Utilizando o TypeORM em TypeScript, o padrão promove uma interação mais clara e eficiente com a base de dados, melhorando a manutenibilidade e escalabilidade da aplicação. 43 | 44 | 45 | 46 | ## Padrão DTO 47 | 48 | O padrão DTO otimiza a transferência de dados entre camadas, aumentando a segurança ao prevenir riscos como injeções SQL, garantindo que apenas dados validados circulem na aplicação. 49 | 50 | 51 | 52 | # Padrões de criação 53 | 54 | Os padrões de projeto criacionais são um grupo de padrões que se concentram na maneira como os objetos são criados e instanciados em um programa 55 | 56 | 57 | 58 | ## Abstract Factory 59 | 60 | O padrão Abstract Factory ajuda a criar grupos de objetos relacionados que se encaixam em um estilo ou configuração específica, tudo isso sem precisar saber exatamente quais objetos estão sendo criados. 61 | 62 | 63 | 64 | ## Builder 65 | 66 | O padrão Builder é usado para criar objetos complexos passo a passo, permitindo que você crie diferentes variações de um objeto sem precisar lidar com muitos construtores complicados. 67 | 68 | 69 | 70 | ## Factory Method 71 | 72 | O padrão Factory Method é usado para criar objetos, mas em vez de criar diretamente usando um construtor, você usa um método chamado "factory method". Esse método sabe como criar diferentes tipos de objetos, permitindo que você crie objetos de maneira flexível, de acordo com suas necessidades. 73 | 74 | 75 | 76 | ## Singleton 77 | 78 | O padrão Singleton garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global para essa instância. 79 | 80 | 81 | 82 | # Padrões estruturais 83 | 84 | Os padrões de projeto estruturais são um grupo de padrões que se concentram em como classes e objetos são organizados para formar estruturas maiores e mais complexas. 85 | 86 | 87 | 88 | ## Adapter 89 | 90 | O padrão Adapter é usado quando você tem duas classes com interfaces incompatíveis, mas você deseja que elas trabalhem juntas. O adaptador age como um intermediário entre essas classes, permitindo que elas se comuniquem. 91 | 92 | 93 | 94 | ## Bridge 95 | 96 | O padrão Bridge é usado para separar duas dimensões diferentes de uma classe, permitindo que elas variem independentemente. Ele é útil quando você tem várias formas de uma entidade e várias maneiras de tratá-la, como diferentes formas e diferentes cores. 97 | 98 | 99 | 100 | ## Facade 101 | 102 | O padrão Facade é usado para fornecer uma interface única e simplificada para um conjunto complexo de subsistemas ou classes. Ele ajuda a esconder a complexidade do sistema subjacente e oferece uma maneira fácil de interagir com ele. 103 | 104 | 105 | 106 | # Padrões comportamentais 107 | 108 | Padrões de projeto comportamentais lidam com algoritmos e a atribuição de responsabilidades entre objetos, facilitando a comunicação e interação entre eles 109 | 110 | 111 | 112 | ## Chain of Responsibility 113 | 114 | O padrão Chain of Responsibility é usado quando você tem uma série de objetos que podem lidar com uma solicitação, mas você não sabe qual deles irá tratá-la até o momento em que a solicitação é feita. Cada objeto na cadeia tem a opção de tratar a solicitação ou passá-la para o próximo objeto na cadeia. 115 | 116 | 117 | 118 | ## Padrão Observe 119 | 120 | O padrão Observer é usado para criar uma relação de dependência um-para-muitos entre objetos. Quando um objeto (chamado de "sujeito" ou "observável") muda de estado, todos os seus "observadores" (ou "ouvintes") são notificados e atualizados automaticamente. 121 | 122 | 123 | 124 | ## Padrão Stratey 125 | 126 | O padrão de projeto Strategy é usado para definir uma família de algoritmos, encapsulá-los e torná-los intercambiáveis. Isso permite que um objeto mude seu comportamento de maneira flexível, escolhendo um algoritmo dentre vários disponíveis durante a execução do programa. 127 | 128 | -------------------------------------------------------------------------------- /assets/camadas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GustavoLima93/ts-class-design-patterns/653b5e4d38153b65fecd843ebb47852746bb8dfa/assets/camadas.png -------------------------------------------------------------------------------- /behavioral-patterns/chain-of-responsibility.ts: -------------------------------------------------------------------------------- 1 | // Classe base para manipuladores 2 | abstract class Handler { 3 | protected nextHandler: Handler; 4 | 5 | setNextHandler(nextHandler: Handler): void { 6 | this.nextHandler = nextHandler; 7 | } 8 | 9 | abstract handleRequest(amount: number): void; 10 | } 11 | 12 | // Implementações concretas dos manipuladores 13 | class ManagerHandler extends Handler { 14 | handleRequest(amount: number): void { 15 | if (amount <= 1000) { 16 | console.log(`Manager can approve $${amount}`); 17 | } else if (this.nextHandler != null) { 18 | this.nextHandler.handleRequest(amount); 19 | } else { 20 | console.log(`No one can approve $${amount}`); 21 | } 22 | } 23 | } 24 | 25 | class DirectorHandler extends Handler { 26 | handleRequest(amount: number): void { 27 | if (amount <= 5000) { 28 | console.log(`Director can approve $${amount}`); 29 | } else if (this.nextHandler != null) { 30 | this.nextHandler.handleRequest(amount); 31 | } else { 32 | console.log(`No one can approve $${amount}`); 33 | } 34 | } 35 | } 36 | 37 | class CFOHandler extends Handler { 38 | handleRequest(amount: number): void { 39 | if (amount <= 10000) { 40 | console.log(`CFO can approve $${amount}`); 41 | } else { 42 | console.log(`No one can approve $${amount}`); 43 | } 44 | } 45 | } 46 | 47 | // Exemplo de uso 48 | const manager = new ManagerHandler(); 49 | const director = new DirectorHandler(); 50 | const cfo = new CFOHandler(); 51 | 52 | manager.setNextHandler(director); 53 | director.setNextHandler(cfo); 54 | 55 | manager.handleRequest(1500); 56 | manager.handleRequest(7000); 57 | manager.handleRequest(12000); 58 | -------------------------------------------------------------------------------- /behavioral-patterns/observe.ts: -------------------------------------------------------------------------------- 1 | // Interface que define o Observador 2 | interface Observer { 3 | update(message: string): void; 4 | } 5 | 6 | // Classe que representa o Sujeito (ou Observável) 7 | class Blog { 8 | private observers: Observer[] = []; 9 | private latestArticle: string; 10 | 11 | addObserver(observer: Observer): void { 12 | this.observers.push(observer); 13 | } 14 | 15 | removeObserver(observer: Observer): void { 16 | const index = this.observers.indexOf(observer); 17 | if (index > -1) { 18 | this.observers.splice(index, 1); 19 | } 20 | } 21 | 22 | publishArticle(article: string): void { 23 | this.latestArticle = article; 24 | this.notifyObservers(); 25 | } 26 | 27 | private notifyObservers(): void { 28 | for (const observer of this.observers) { 29 | observer.update(this.latestArticle); 30 | } 31 | } 32 | } 33 | 34 | // Implementação concreta do Observador 35 | class Subscriber implements Observer { 36 | private name: string; 37 | 38 | constructor(name: string) { 39 | this.name = name; 40 | } 41 | 42 | update(message: string): void { 43 | console.log(`${this.name} received an update: ${message}`); 44 | } 45 | } 46 | 47 | // Exemplo de uso 48 | const blog = new Blog(); 49 | 50 | const subscriber1 = new Subscriber("Alice"); 51 | const subscriber2 = new Subscriber("Bob"); 52 | 53 | blog.addObserver(subscriber1); 54 | blog.addObserver(subscriber2); 55 | 56 | blog.publishArticle("New article: Design Patterns"); 57 | -------------------------------------------------------------------------------- /behavioral-patterns/strategy.ts: -------------------------------------------------------------------------------- 1 | // Definição da interface de estratégia de ataque 2 | interface AttackStrategy { 3 | attack(): void; 4 | } 5 | 6 | // Classe Knight com uma estratégia de ataque 7 | class Knight { 8 | private attackStrategy: AttackStrategy; 9 | 10 | setAttackStrategy(attackStrategy: AttackStrategy): void { 11 | this.attackStrategy = attackStrategy; 12 | } 13 | 14 | performAttack(): void { 15 | this.attackStrategy.attack(); 16 | } 17 | } 18 | 19 | // Implementações concretas da estratégia de ataque 20 | class SwordAttack implements AttackStrategy { 21 | attack(): void { 22 | console.log("Sword attack!"); 23 | } 24 | } 25 | 26 | class BowAttack implements AttackStrategy { 27 | attack(): void { 28 | console.log("Bow attack!"); 29 | } 30 | } 31 | 32 | // Exemplo de uso 33 | const knight = new Knight(); 34 | knight.setAttackStrategy(new SwordAttack()); // Configura o ataque como SwordAttack 35 | knight.performAttack(); // Executa o ataque de espada 36 | 37 | knight.setAttackStrategy(new BowAttack()); // Altera a estratégia para BowAttack 38 | knight.performAttack(); // Executa o ataque de arco -------------------------------------------------------------------------------- /creational-patterns/abstract-factory.ts: -------------------------------------------------------------------------------- 1 | // Interfaces for the game products 2 | interface Graphics { 3 | render(): void; 4 | } 5 | 6 | interface Sound { 7 | play(): void; 8 | } 9 | 10 | interface Controls { 11 | handleInput(): void; 12 | } 13 | 14 | // Abstract factory for creating the products 15 | interface GameFactory { 16 | createGraphics(): Graphics; 17 | createSound(): Sound; 18 | createControls(): Controls; 19 | } 20 | 21 | // Concrete product implementations for PC 22 | class PCGraphics implements Graphics { 23 | render(): void { 24 | console.log("Rendering graphics for PC."); 25 | } 26 | } 27 | 28 | class PCSound implements Sound { 29 | play(): void { 30 | console.log("Playing sound for PC."); 31 | } 32 | } 33 | 34 | class PCControls implements Controls { 35 | handleInput(): void { 36 | console.log("Handling input for PC."); 37 | } 38 | } 39 | 40 | // Concrete product implementations for console 41 | class ConsoleGraphics implements Graphics { 42 | render(): void { 43 | console.log("Rendering graphics for console."); 44 | } 45 | } 46 | 47 | class ConsoleSound implements Sound { 48 | play(): void { 49 | console.log("Playing sound for console."); 50 | } 51 | } 52 | 53 | class ConsoleControls implements Controls { 54 | handleInput(): void { 55 | console.log("Handling input for console."); 56 | } 57 | } 58 | 59 | // Concrete factory implementations for PC 60 | class PCGameFactory implements GameFactory { 61 | createGraphics(): Graphics { 62 | return new PCGraphics(); 63 | } 64 | 65 | createSound(): Sound { 66 | return new PCSound(); 67 | } 68 | 69 | createControls(): Controls { 70 | return new PCControls(); 71 | } 72 | } 73 | 74 | // Concrete factory implementations for console 75 | class ConsoleGameFactory implements GameFactory { 76 | createGraphics(): Graphics { 77 | return new ConsoleGraphics(); 78 | } 79 | 80 | createSound(): Sound { 81 | return new ConsoleSound(); 82 | } 83 | 84 | createControls(): Controls { 85 | return new ConsoleControls(); 86 | } 87 | } 88 | 89 | // Client using the factories and products 90 | class GameClient { 91 | static main(): void { 92 | const pcFactory: GameFactory = new PCGameFactory(); 93 | const pcGraphics: Graphics = pcFactory.createGraphics(); 94 | const pcSound: Sound = pcFactory.createSound(); 95 | const pcControls: Controls = pcFactory.createControls(); 96 | 97 | pcGraphics.render(); 98 | pcSound.play(); 99 | pcControls.handleInput(); 100 | 101 | const consoleFactory: GameFactory = new ConsoleGameFactory(); 102 | const consoleGraphics: Graphics = consoleFactory.createGraphics(); 103 | const consoleSound: Sound = consoleFactory.createSound(); 104 | const consoleControls: Controls = consoleFactory.createControls(); 105 | 106 | consoleGraphics.render(); 107 | consoleSound.play(); 108 | consoleControls.handleInput(); 109 | } 110 | } 111 | 112 | // Running the client code 113 | GameClient.main(); -------------------------------------------------------------------------------- /creational-patterns/builder.ts: -------------------------------------------------------------------------------- 1 | // Product class 2 | class Sandwich { 3 | private bread: string; 4 | private meat: string; 5 | private cheese: string; 6 | private veggies: string; 7 | private condiments: string; 8 | 9 | // Methods to set the parts of the sandwich 10 | setBread(bread: string): void { 11 | this.bread = bread; 12 | } 13 | 14 | setMeat(meat: string): void { 15 | this.meat = meat; 16 | } 17 | 18 | setCheese(cheese: string): void { 19 | this.cheese = cheese; 20 | } 21 | 22 | setVeggies(veggies: string): void { 23 | this.veggies = veggies; 24 | } 25 | 26 | setCondiments(condiments: string): void { 27 | this.condiments = condiments; 28 | } 29 | 30 | // Method to display the sandwich 31 | display(): void { 32 | console.log(`Sandwich with ${this.bread}, ${this.meat}, ${this.cheese}, ${this.veggies}, ${this.condiments}`); 33 | } 34 | } 35 | 36 | // Builder class 37 | class SandwichBuilder { 38 | private sandwich: Sandwich = new Sandwich(); 39 | 40 | withBread(bread: string): SandwichBuilder { 41 | this.sandwich.setBread(bread); 42 | return this; 43 | } 44 | 45 | withMeat(meat: string): SandwichBuilder { 46 | this.sandwich.setMeat(meat); 47 | return this; 48 | } 49 | 50 | withCheese(cheese: string): SandwichBuilder { 51 | this.sandwich.setCheese(cheese); 52 | return this; 53 | } 54 | 55 | withVeggies(veggies: string): SandwichBuilder { 56 | this.sandwich.setVeggies(veggies); 57 | return this; 58 | } 59 | 60 | withCondiments(condiments: string): SandwichBuilder { 61 | this.sandwich.setCondiments(condiments); 62 | return this; 63 | } 64 | 65 | build(): Sandwich { 66 | return this.sandwich; 67 | } 68 | } 69 | 70 | // Usage example 71 | const sandwich = new SandwichBuilder() 72 | .withBread("Wheat") 73 | .withMeat("Turkey") 74 | .withCheese("Swiss") 75 | .withVeggies("Lettuce, Tomato") 76 | .withCondiments("Mayo, Mustard") 77 | .build(); 78 | 79 | sandwich.display(); 80 | -------------------------------------------------------------------------------- /creational-patterns/factory-method.ts: -------------------------------------------------------------------------------- 1 | // Base class for the products (vehicles) 2 | abstract class Vehicle { 3 | abstract start(): void; 4 | abstract stop(): void; 5 | } 6 | 7 | // Concrete classes of the products (car and bicycle) 8 | class Car extends Vehicle { 9 | start(): void { 10 | console.log("Car is starting."); 11 | } 12 | 13 | stop(): void { 14 | console.log("Car is stopping."); 15 | } 16 | } 17 | 18 | class Bicycle extends Vehicle { 19 | start(): void { 20 | console.log("Bicycle is starting."); 21 | } 22 | 23 | stop(): void { 24 | console.log("Bicycle is stopping."); 25 | } 26 | } 27 | 28 | // Interface for the Factory Method 29 | interface VehicleFactory { 30 | createVehicle(): Vehicle; 31 | } 32 | 33 | // Concrete implementations of the Factory Method 34 | class CarFactory implements VehicleFactory { 35 | createVehicle(): Vehicle { 36 | return new Car(); 37 | } 38 | } 39 | 40 | class BicycleFactory implements VehicleFactory { 41 | createVehicle(): Vehicle { 42 | return new Bicycle(); 43 | } 44 | } 45 | 46 | // Usage example 47 | const carFactory: VehicleFactory = new CarFactory(); 48 | const car: Vehicle = carFactory.createVehicle(); 49 | car.start(); 50 | car.stop(); 51 | 52 | const bicycleFactory: VehicleFactory = new BicycleFactory(); 53 | const bicycle: Vehicle = bicycleFactory.createVehicle(); 54 | bicycle.start(); 55 | bicycle.stop(); 56 | -------------------------------------------------------------------------------- /creational-patterns/singleton.ts: -------------------------------------------------------------------------------- 1 | import sql from 'mssql'; 2 | 3 | class DatabaseSingleton { 4 | private static instance: DatabaseSingleton; 5 | private connection: sql.ConnectionPool | null = null; 6 | 7 | private constructor() { 8 | // Configuration for the database connection 9 | const config = { 10 | user: 'username', 11 | password: 'password', 12 | server: 'localhost', 13 | database: 'mydatabase', 14 | options: { 15 | encrypt: true, // If using Azure SQL, set to true 16 | enableArithAbort: true 17 | } 18 | }; 19 | 20 | this.connection = new sql.ConnectionPool(config, err => { 21 | if (err) console.error('Database connection failed: ', err); 22 | else console.log('Connected to MSSQL database'); 23 | }); 24 | } 25 | 26 | public static getInstance(): DatabaseSingleton { 27 | if (!DatabaseSingleton.instance) { 28 | DatabaseSingleton.instance = new DatabaseSingleton(); 29 | } 30 | return DatabaseSingleton.instance; 31 | } 32 | 33 | public getConnection(): sql.ConnectionPool | null { 34 | return this.connection; 35 | } 36 | } 37 | 38 | // Usage example 39 | async function main() { 40 | const database = DatabaseSingleton.getInstance(); 41 | const connection = database.getConnection(); 42 | 43 | try { 44 | await connection?.connect(); 45 | console.log('Connected to database:', connection?.config.database); 46 | // Perform database operations here 47 | } catch (error) { 48 | console.error('Error connecting to the database:', error); 49 | } finally { 50 | await connection?.close(); 51 | } 52 | } 53 | 54 | main(); -------------------------------------------------------------------------------- /demo/students/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir: __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /demo/students/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | /build 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | pnpm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | 15 | # OS 16 | .DS_Store 17 | 18 | # Tests 19 | /coverage 20 | /.nyc_output 21 | 22 | # IDEs and editors 23 | /.idea 24 | .project 25 | .classpath 26 | .c9/ 27 | *.launch 28 | .settings/ 29 | *.sublime-workspace 30 | 31 | # IDE - VSCode 32 | .vscode/* 33 | !.vscode/settings.json 34 | !.vscode/tasks.json 35 | !.vscode/launch.json 36 | !.vscode/extensions.json 37 | 38 | # dotenv environment variable files 39 | .env 40 | .env.development.local 41 | .env.test.local 42 | .env.production.local 43 | .env.local 44 | 45 | # temp directory 46 | .temp 47 | .tmp 48 | 49 | # Runtime data 50 | pids 51 | *.pid 52 | *.seed 53 | *.pid.lock 54 | 55 | # Diagnostic reports (https://nodejs.org/api/report.html) 56 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 57 | -------------------------------------------------------------------------------- /demo/students/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /demo/students/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |

A progressive Node.js framework for building efficient and scalable server-side applications.

9 |

10 | NPM Version 11 | Package License 12 | NPM Downloads 13 | CircleCI 14 | Coverage 15 | Discord 16 | Backers on Open Collective 17 | Sponsors on Open Collective 18 | 19 | Support us 20 | 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 28 | 29 | ## Installation 30 | 31 | ```bash 32 | $ npm install 33 | ``` 34 | 35 | ## Running the app 36 | 37 | ```bash 38 | # development 39 | $ npm run start 40 | 41 | # watch mode 42 | $ npm run start:dev 43 | 44 | # production mode 45 | $ npm run start:prod 46 | ``` 47 | 48 | ## Test 49 | 50 | ```bash 51 | # unit tests 52 | $ npm run test 53 | 54 | # e2e tests 55 | $ npm run test:e2e 56 | 57 | # test coverage 58 | $ npm run test:cov 59 | ``` 60 | 61 | ## Support 62 | 63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 64 | 65 | ## Stay in touch 66 | 67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 68 | - Website - [https://nestjs.com](https://nestjs.com/) 69 | - Twitter - [@nestframework](https://twitter.com/nestframework) 70 | 71 | ## License 72 | 73 | Nest is [MIT licensed](LICENSE). 74 | -------------------------------------------------------------------------------- /demo/students/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /demo/students/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "students", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "build": "nest build", 10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 11 | "start": "nest start", 12 | "start:dev": "nest start --watch", 13 | "start:debug": "nest start --debug --watch", 14 | "start:prod": "node dist/main", 15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 16 | "test": "jest", 17 | "test:watch": "jest --watch", 18 | "test:cov": "jest --coverage", 19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 20 | "test:e2e": "jest --config ./test/jest-e2e.json" 21 | }, 22 | "dependencies": { 23 | "@nestjs/common": "^10.0.0", 24 | "@nestjs/core": "^10.0.0", 25 | "@nestjs/platform-express": "^10.0.0", 26 | "@nestjs/typeorm": "^10.0.2", 27 | "pg": "^8.11.5", 28 | "reflect-metadata": "^0.2.0", 29 | "rxjs": "^7.8.1", 30 | "typeorm": "^0.3.20" 31 | }, 32 | "devDependencies": { 33 | "@nestjs/cli": "^10.0.0", 34 | "@nestjs/schematics": "^10.0.0", 35 | "@nestjs/testing": "^10.0.0", 36 | "@types/express": "^4.17.17", 37 | "@types/jest": "^29.5.2", 38 | "@types/node": "^20.3.1", 39 | "@types/supertest": "^6.0.0", 40 | "@typescript-eslint/eslint-plugin": "^6.0.0", 41 | "@typescript-eslint/parser": "^6.0.0", 42 | "eslint": "^8.42.0", 43 | "eslint-config-prettier": "^9.0.0", 44 | "eslint-plugin-prettier": "^5.0.0", 45 | "jest": "^29.5.0", 46 | "prettier": "^3.0.0", 47 | "source-map-support": "^0.5.21", 48 | "supertest": "^6.3.3", 49 | "ts-jest": "^29.1.0", 50 | "ts-loader": "^9.4.3", 51 | "ts-node": "^10.9.1", 52 | "tsconfig-paths": "^4.2.0", 53 | "typescript": "^5.1.3" 54 | }, 55 | "jest": { 56 | "moduleFileExtensions": [ 57 | "js", 58 | "json", 59 | "ts" 60 | ], 61 | "rootDir": "src", 62 | "testRegex": ".*\\.spec\\.ts$", 63 | "transform": { 64 | "^.+\\.(t|j)s$": "ts-jest" 65 | }, 66 | "collectCoverageFrom": [ 67 | "**/*.(t|j)s" 68 | ], 69 | "coverageDirectory": "../coverage", 70 | "testEnvironment": "node" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /demo/students/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { StudentsModule } from './students/students.module'; 3 | import { TypeOrmModule } from '@nestjs/typeorm'; 4 | import { Student } from './students/entities/student.entity'; 5 | 6 | @Module({ 7 | imports: [ 8 | TypeOrmModule.forRoot({ 9 | type: 'postgres', 10 | host: 'localhost', 11 | port: 5432, 12 | username: 'user', 13 | password: '123456', 14 | database: 'students', 15 | synchronize: true, 16 | logging: true, 17 | entities: [Student], 18 | }), 19 | StudentsModule, 20 | ], 21 | controllers: [], 22 | providers: [], 23 | }) 24 | export class AppModule {} 25 | -------------------------------------------------------------------------------- /demo/students/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule); 6 | await app.listen(3000); 7 | } 8 | bootstrap(); 9 | -------------------------------------------------------------------------------- /demo/students/src/students/controllers/student.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Get, Post } from '@nestjs/common'; 2 | import { StudentService } from '../service/student.service'; 3 | import { StudentDTO } from '../dtos/student.dto'; 4 | 5 | @Controller('student') 6 | export class StudentController { 7 | constructor(private readonly studentService: StudentService) {} 8 | 9 | @Get('/') 10 | getStudents() { 11 | return this.studentService.findAll(); 12 | } 13 | 14 | @Post('/') 15 | createStudent(@Body() student: StudentDTO) { 16 | return this.studentService.create(student); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /demo/students/src/students/dtos/student.dto.ts: -------------------------------------------------------------------------------- 1 | export class StudentDTO { 2 | id: number; 3 | firstName: string; 4 | lastName: string; 5 | isActive: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /demo/students/src/students/entities/student.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; 2 | 3 | @Entity() 4 | export class Student { 5 | @PrimaryGeneratedColumn() 6 | id: number; 7 | 8 | @Column() 9 | firstName: string; 10 | 11 | @Column() 12 | lastName: string; 13 | 14 | @Column({ default: true }) 15 | isActive: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /demo/students/src/students/repositories/student-repository.interface.ts: -------------------------------------------------------------------------------- 1 | import { StudentDTO } from '../dtos/student.dto'; 2 | import { Student } from '../entities/student.entity'; 3 | 4 | export const STUDENT_REPOSITORY = 'STUDENT_REPOSITORY'; 5 | 6 | export interface IStudentRepository { 7 | findAll(): Promise; 8 | create(student: StudentDTO): Promise; 9 | } 10 | -------------------------------------------------------------------------------- /demo/students/src/students/repositories/student-respository.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { IStudentRepository } from './student-repository.interface'; 3 | import { StudentDTO } from '../dtos/student.dto'; 4 | import { Student } from '../entities/student.entity'; 5 | import { Repository } from 'typeorm'; 6 | import { InjectRepository } from '@nestjs/typeorm'; 7 | 8 | @Injectable() 9 | export class StudentRespositoryService implements IStudentRepository { 10 | constructor( 11 | @InjectRepository(Student) 12 | private readonly studentRepository: Repository, 13 | ) {} 14 | 15 | findAll(): Promise { 16 | return this.studentRepository.find(); 17 | } 18 | create({ firstName, lastName }: StudentDTO): Promise { 19 | const student = this.studentRepository.create({ firstName, lastName }); 20 | return this.studentRepository.save(student); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo/students/src/students/service/student.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@nestjs/common'; 2 | import { 3 | IStudentRepository, 4 | STUDENT_REPOSITORY, 5 | } from '../repositories/student-repository.interface'; 6 | import { StudentDTO } from '../dtos/student.dto'; 7 | 8 | @Injectable() 9 | export class StudentService { 10 | constructor( 11 | @Inject(STUDENT_REPOSITORY) 12 | private readonly studentRepository: IStudentRepository, 13 | ) {} 14 | 15 | findAll() { 16 | return this.studentRepository.findAll(); 17 | } 18 | 19 | create(student: StudentDTO) { 20 | return this.studentRepository.create(student); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo/students/src/students/students.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { StudentController } from './controllers/student.controller'; 3 | import { StudentService } from './service/student.service'; 4 | import { StudentRespositoryService } from './repositories/student-respository.service'; 5 | import { TypeOrmModule } from '@nestjs/typeorm'; 6 | import { Student } from './entities/student.entity'; 7 | import { STUDENT_REPOSITORY } from './repositories/student-repository.interface'; 8 | 9 | @Module({ 10 | imports: [TypeOrmModule.forFeature([Student])], 11 | controllers: [StudentController], 12 | providers: [ 13 | StudentService, 14 | { useClass: StudentRespositoryService, provide: STUDENT_REPOSITORY }, 15 | ], 16 | }) 17 | export class StudentsModule {} 18 | -------------------------------------------------------------------------------- /demo/students/students.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | @Module({}) 4 | export class StudentsModule {} 5 | -------------------------------------------------------------------------------- /demo/students/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /demo/students/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demo/students/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /demo/students/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "ES2021", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /structural-patterns/adapter.ts: -------------------------------------------------------------------------------- 1 | // Interface representing the dollar payment service 2 | interface DollarPaymentService { 3 | processPayment(amount: number): void; 4 | } 5 | 6 | // Concrete implementation of the dollar payment service 7 | class PayPalService implements DollarPaymentService { 8 | processPayment(amount: number): void { 9 | console.log(`Processing dollar payment of $${amount}`); 10 | } 11 | } 12 | 13 | // Interface representing the euro payment service 14 | interface EuroPaymentService { 15 | processPaymentInEuros(amount: number): void; 16 | } 17 | 18 | // Adapter allowing the dollar payment service to handle euros 19 | class EuroPaymentServiceAdapter implements EuroPaymentService { 20 | private dollarPaymentService: DollarPaymentService; 21 | 22 | constructor(dollarPaymentService: DollarPaymentService) { 23 | this.dollarPaymentService = dollarPaymentService; 24 | } 25 | 26 | processPaymentInEuros(amount: number): void { 27 | // Converting euros to dollars using a fictitious exchange rate 28 | const amountInDollars = amount * 1.2; 29 | this.dollarPaymentService.processPayment(amountInDollars); 30 | } 31 | } 32 | 33 | // Usage example 34 | function main() { 35 | // Using the dollar payment service directly 36 | const dollarService: DollarPaymentService = new PayPalService(); 37 | dollarService.processPayment(100.0); 38 | 39 | // Adapting the dollar payment service to handle euros 40 | const euroService: EuroPaymentService = new EuroPaymentServiceAdapter(dollarService); 41 | euroService.processPaymentInEuros(85.0); 42 | } 43 | 44 | main(); -------------------------------------------------------------------------------- /structural-patterns/bridge.ts: -------------------------------------------------------------------------------- 1 | // Implementação da forma (abstração) 2 | interface Shape { 3 | draw(): void; 4 | } 5 | 6 | // Implementações concretas de formas 7 | class Circle implements Shape { 8 | draw(): void { 9 | console.log("Drawing a circle"); 10 | } 11 | } 12 | 13 | class Square implements Shape { 14 | draw(): void { 15 | console.log("Drawing a square"); 16 | } 17 | } 18 | 19 | // Implementação da cor (implementação) 20 | interface Color { 21 | applyColor(): void; 22 | } 23 | 24 | // Implementações concretas de cores 25 | class Red implements Color { 26 | applyColor(): void { 27 | console.log("Applying red color"); 28 | } 29 | } 30 | 31 | class Blue implements Color { 32 | applyColor(): void { 33 | console.log("Applying blue color"); 34 | } 35 | } 36 | 37 | // Abstração refinada que usa o padrão Bridge 38 | abstract class ShapeWithColor implements Shape { 39 | protected color: Color; 40 | 41 | constructor(color: Color) { 42 | this.color = color; 43 | } 44 | 45 | draw(): void {} 46 | 47 | abstract drawWithColor(): void; 48 | } 49 | 50 | // Implementação refinada da forma com uma cor específica 51 | class ColoredCircle extends ShapeWithColor { 52 | constructor(color: Color) { 53 | super(color); 54 | } 55 | 56 | draw(): void { 57 | console.log("Drawing a colored circle"); 58 | } 59 | 60 | drawWithColor(): void { 61 | this.draw(); 62 | this.color.applyColor(); 63 | } 64 | } 65 | 66 | class ColoredSquare extends ShapeWithColor { 67 | constructor(color: Color) { 68 | super(color); 69 | } 70 | 71 | draw(): void { 72 | console.log("Drawing a colored square"); 73 | } 74 | 75 | drawWithColor(): void { 76 | this.draw(); 77 | this.color.applyColor(); 78 | } 79 | } 80 | 81 | // Exemplo de uso 82 | const redCircle = new ColoredCircle(new Red()); 83 | const blueSquare = new ColoredSquare(new Blue()); 84 | 85 | redCircle.drawWithColor(); 86 | blueSquare.drawWithColor(); 87 | -------------------------------------------------------------------------------- /structural-patterns/facade.ts: -------------------------------------------------------------------------------- 1 | // Subsistema 1 2 | class CPU { 3 | freeze(): void { 4 | console.log("CPU freezing..."); 5 | } 6 | 7 | execute(): void { 8 | console.log("CPU executing..."); 9 | } 10 | } 11 | 12 | // Subsistema 2 13 | class Memory { 14 | load(): void { 15 | console.log("Memory loading..."); 16 | } 17 | } 18 | 19 | // Subsistema 3 20 | class HardDrive { 21 | read(): void { 22 | console.log("Hard Drive reading..."); 23 | } 24 | } 25 | 26 | // Fachada que simplifica a interação com os subsistemas 27 | class ComputerFacade { 28 | private cpu: CPU; 29 | private memory: Memory; 30 | private hardDrive: HardDrive; 31 | 32 | constructor() { 33 | this.cpu = new CPU(); 34 | this.memory = new Memory(); 35 | this.hardDrive = new HardDrive(); 36 | } 37 | 38 | startComputer(): void { 39 | console.log("Starting computer..."); 40 | this.cpu.freeze(); 41 | this.memory.load(); 42 | this.hardDrive.read(); 43 | this.cpu.execute(); 44 | console.log("Computer started."); 45 | } 46 | } 47 | 48 | // Exemplo de uso 49 | const computer = new ComputerFacade(); 50 | computer.startComputer(); --------------------------------------------------------------------------------