├── 02-typeorm-demo ├── typeorm-demo-vue │ ├── src │ │ ├── views │ │ │ ├── movie │ │ │ │ ├── methods.ts │ │ │ │ ├── CreateView.vue │ │ │ │ └── UpdateView.vue │ │ │ ├── HomeView.vue │ │ │ └── 404.vue │ │ ├── enums │ │ │ ├── index.ts │ │ │ └── http.enum.ts │ │ ├── helpers │ │ │ ├── functions │ │ │ │ ├── index.ts │ │ │ │ └── sleep.ts │ │ │ ├── index.ts │ │ │ └── string.helper.ts │ │ ├── layouts │ │ │ ├── empty.vue │ │ │ ├── index.ts │ │ │ └── main.vue │ │ ├── stores │ │ │ ├── index.ts │ │ │ ├── global.ts │ │ │ └── movie.ts │ │ ├── components │ │ │ ├── movie │ │ │ │ └── index.ts │ │ │ ├── common │ │ │ │ ├── XPage.vue │ │ │ │ ├── XBadge.vue │ │ │ │ ├── XTooltip.vue │ │ │ │ ├── XButton.vue │ │ │ │ ├── XSwitch.vue │ │ │ │ ├── XAlert.vue │ │ │ │ ├── index.ts │ │ │ │ └── x-dialog │ │ │ │ │ └── XDialogTitle.vue │ │ │ ├── index.ts │ │ │ ├── Footer.vue │ │ │ └── ToggleTheme.vue │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── router.ts │ │ │ ├── routes.ts │ │ │ └── route-list.ts │ │ ├── types │ │ │ ├── index.ts │ │ │ ├── movie.type.ts │ │ │ ├── i18n.type.ts │ │ │ └── http.type.ts │ │ ├── assets │ │ │ ├── components │ │ │ │ ├── notification.scss │ │ │ │ ├── index.scss │ │ │ │ ├── x-input.scss │ │ │ │ ├── x-button.scss │ │ │ │ ├── x-textarea.scss │ │ │ │ └── x-select.scss │ │ │ ├── logo.svg │ │ │ └── main.css │ │ ├── i18n │ │ │ └── messages │ │ │ │ ├── pt-BR │ │ │ │ ├── user.ts │ │ │ │ ├── index.ts │ │ │ │ └── common │ │ │ │ │ ├── movie.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── en-US │ │ │ │ ├── index.ts │ │ │ │ ├── user.ts │ │ │ │ ├── common │ │ │ │ ├── movie.ts │ │ │ │ └── index.ts │ │ │ │ └── field.ts │ │ ├── services │ │ │ ├── index.ts │ │ │ ├── movie.service.ts │ │ │ └── user.service.ts │ │ ├── route.d.ts │ │ ├── App.vue │ │ └── main.ts │ ├── .env.local.example │ ├── .lintstagedrc.json │ ├── vercel.json │ ├── docs │ │ └── prints │ │ │ └── unit-coverage.png │ ├── env.d.ts │ ├── postcss.config.js │ ├── tsconfig.config.json │ ├── .editorconfig │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── .gitignore │ ├── public │ │ └── favicon.svg │ ├── .eslintrc.cjs │ ├── components.d.ts │ ├── vite.config.ts │ └── index.html ├── typeorm-demo-ui-react │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── App.tsx │ │ ├── setupTests.ts │ │ ├── App.test.tsx │ │ ├── index.css │ │ ├── reportWebVitals.ts │ │ └── index.tsx │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ └── manifest.json │ ├── tsconfig.json │ └── package.json └── typeorm-demo-api │ ├── src │ ├── entities │ │ ├── base.entity.ts │ │ ├── user.entity.ts │ │ └── movie.entity.ts │ ├── useCases │ │ ├── ping │ │ │ ├── ping.dto.ts │ │ │ ├── ping.module.ts │ │ │ ├── ping.controller.ts │ │ │ └── ping.usecase.ts │ │ ├── user │ │ │ ├── findall │ │ │ │ ├── findall-user.dto.ts │ │ │ │ ├── findall-user.usecase.ts │ │ │ │ └── findall-user.controller.ts │ │ │ ├── create │ │ │ │ ├── create-user.dto.ts │ │ │ │ └── create-user.controller.ts │ │ │ └── user.module.ts │ │ └── movie │ │ │ ├── findAll │ │ │ ├── findall-movie.dto.ts │ │ │ ├── findall-movie.controller.ts │ │ │ └── findall-movie.usecase.ts │ │ │ ├── delete │ │ │ ├── delete-movie.dto.ts │ │ │ ├── delete-movie.controller.ts │ │ │ └── delete-movie.usecase.ts │ │ │ ├── findOne │ │ │ ├── findone-movie.dto.ts │ │ │ ├── findone-movie.controller.ts │ │ │ └── findone-movie.usecase.ts │ │ │ ├── create │ │ │ ├── create-movie.dto.ts │ │ │ ├── create-movie.controller.ts │ │ │ └── create-movie.usecase.ts │ │ │ └── movie.module.ts │ ├── repositories │ │ ├── base-repository.interface.ts │ │ ├── user.repository.ts │ │ └── movie.repository.ts │ ├── providers │ │ ├── orm │ │ │ └── typeorm │ │ │ │ └── postgres │ │ │ │ └── postgresdb.ts │ │ └── application │ │ │ └── application.ts │ ├── app-container.ts │ ├── env.ts │ └── main.ts │ ├── .prettierrc │ ├── .env │ ├── logs │ └── .028ffe1db245944daaafe235d23bb79dab8c7eb3-audit.json │ ├── jest.config.ts │ ├── test │ └── ping.usecase.spec.ts │ ├── .eslintrc.js │ ├── tsconfig.json │ └── package.json ├── .vscode └── settings.json ├── expressots.png ├── 01-history └── project-one │ ├── frontend │ ├── .env.example │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── services │ │ │ └── api │ │ │ │ ├── index.ts │ │ │ │ └── player │ │ │ │ ├── player.ts │ │ │ │ └── createPlayer.dto.ts │ │ ├── setupTests.ts │ │ ├── index.css │ │ ├── App.tsx │ │ ├── reportWebVitals.ts │ │ ├── index.tsx │ │ └── components │ │ │ └── Input.tsx │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ └── manifest.json │ ├── craco.config.js │ ├── tailwind.config.js │ ├── .gitignore │ ├── tsconfig.json │ └── package.json │ ├── src │ ├── useCases │ │ └── user │ │ │ ├── findById │ │ │ ├── IFindById.DTO.ts │ │ │ ├── FindById.Controller.ts │ │ │ └── FindById.UseCase.ts │ │ │ ├── findAll │ │ │ ├── FindAllUsers.DTO.ts │ │ │ ├── FindAllUsers.Controller.ts │ │ │ └── FindAllUsers.UseCase.ts │ │ │ ├── create │ │ │ ├── ICreateUser.DTO.ts │ │ │ └── CreateUser.Controller.ts │ │ │ ├── delete │ │ │ ├── IDeleteUser.DTO.ts │ │ │ └── DeleteUser.Controller.ts │ │ │ ├── update │ │ │ ├── IUpdateUser.DTO.ts │ │ │ └── UpdateUser.Controller.ts │ │ │ └── User.Module.ts │ ├── providers │ │ ├── database │ │ │ ├── IDatabaseProvider.ts │ │ │ └── mongodb │ │ │ │ └── orm │ │ │ │ └── mongoose │ │ │ │ ├── SeedData.ts │ │ │ │ └── MongooseConnectionOptions.ts │ │ ├── email │ │ │ └── mailTrap │ │ │ │ └── IMail.Provider.ts │ │ ├── core │ │ │ ├── error │ │ │ │ ├── ReportError.Provider.ts │ │ │ │ └── ApplicationError.ts │ │ │ ├── containerModule │ │ │ │ └── BaseModule.Provider.ts │ │ │ └── controller │ │ │ │ └── Controller.Provider.ts │ │ └── middlewares │ │ │ └── AuthMiddleware │ │ │ └── AuthMiddleware.Provider.ts │ ├── entities │ │ ├── IBase.Entity.ts │ │ └── User.ts │ ├── AppContainer.ts │ ├── Main.ts │ └── repositories │ │ ├── user │ │ └── User.Repository.ts │ │ └── IBase.Repository.ts │ ├── .docker │ └── docker-compose.yml │ ├── jest.config.ts │ ├── .env.example │ └── tsconfig.json ├── 03-opinionated-with-docker ├── entrypoint.sh ├── src │ ├── entities │ │ ├── base.entity.ts │ │ └── user.entity.ts │ ├── useCases │ │ ├── ping │ │ │ ├── ping.dto.ts │ │ │ ├── ping.module.ts │ │ │ ├── ping.usecase.ts │ │ │ └── ping.controller.ts │ │ └── user │ │ │ ├── findall │ │ │ ├── findall-user.dto.ts │ │ │ ├── findall-user.controller.ts │ │ │ └── findall-user.usecase.ts │ │ │ ├── create │ │ │ ├── create-user.dto.ts │ │ │ └── create-user.controller.ts │ │ │ └── user.module.ts │ ├── providers │ │ ├── bindingType │ │ │ └── provide-singleton.ts │ │ ├── db-in-memory │ │ │ └── db-in-memory.provider.ts │ │ └── application │ │ │ └── application.ts │ ├── repositories │ │ ├── base-repository.interface.ts │ │ ├── user │ │ │ └── user.repository.ts │ │ └── base-repository.ts │ ├── app-container.ts │ ├── env.ts │ └── main.ts ├── .dockerignore ├── .prettierrc ├── .env ├── expressots.config.ts ├── .gitignore ├── register-path.js ├── jest.config.ts ├── .eslintrc.js ├── test │ └── ping.usecase.spec.ts ├── tsconfig.json ├── tsconfig.build.json └── Dockerfile ├── 04-poke-battle-with-prisma ├── .gitattributes ├── .gitignore ├── src │ ├── entities │ │ ├── base.entity.ts │ │ ├── user.entity.ts │ │ └── battle.entity.ts │ ├── providers │ │ ├── database │ │ │ ├── prismaClient.ts │ │ │ └── orm │ │ │ │ └── prisma │ │ │ │ └── prisma-client.provider.ts │ │ ├── encrypt │ │ │ ├── bcrypt │ │ │ │ └── compare-passwords.provider.ts │ │ │ └── jwt │ │ │ │ └── jwt.provider.ts │ │ ├── application │ │ │ └── application.ts │ │ └── middlewares │ │ │ └── auth.ts │ ├── useCases │ │ ├── user │ │ │ ├── findall │ │ │ │ ├── findall-user.dto.ts │ │ │ │ ├── findall-user.usecase.ts │ │ │ │ └── findall-user.controller.ts │ │ │ ├── getUser │ │ │ │ ├── getuser-user.dto.ts │ │ │ │ ├── getuser-user.usecase.ts │ │ │ │ └── getuser-user.controller.ts │ │ │ ├── login │ │ │ │ ├── login-user.dto.ts │ │ │ │ └── login-user.controller.ts │ │ │ ├── create │ │ │ │ ├── create-user.dto.ts │ │ │ │ └── create-user.controller.ts │ │ │ └── user.module.ts │ │ ├── ping │ │ │ ├── ping.dto.ts │ │ │ ├── ping.module.ts │ │ │ ├── ping.usecase.ts │ │ │ └── ping.controller.ts │ │ └── pokebattle │ │ │ ├── pokebattle.module.ts │ │ │ ├── history │ │ │ ├── pokebattle.usecase.ts │ │ │ ├── pokebattle.dto.ts │ │ │ └── pokebattle.controller.ts │ │ │ └── battle │ │ │ ├── pokebattle-battle.dto.ts │ │ │ └── pokebattle-battle.controller.ts │ ├── repositories │ │ ├── user │ │ │ ├── user.dto.ts │ │ │ └── user-repository.interface.ts │ │ ├── base-repository.interface.ts │ │ ├── battle │ │ │ ├── battle-repository.interface.ts │ │ │ └── battle.dto.ts │ │ └── base-repository.ts │ ├── env.ts │ ├── app-container.ts │ └── main.ts ├── .prettierrc ├── prisma │ ├── migrations │ │ ├── migration_lock.toml │ │ └── 20230422172303_init │ │ │ └── migration.sql │ └── schema.prisma ├── expressots.config.ts ├── .env.example ├── jest.config.ts ├── .eslintrc.js ├── test │ └── ping.usecase.spec.ts └── tsconfig.json ├── 05-postgres-connection-pool-repository ├── src │ ├── entities │ │ ├── base.entity.ts │ │ └── user.entity.ts │ ├── useCases │ │ ├── user │ │ │ ├── findall │ │ │ │ ├── user-findall.dto.ts │ │ │ │ ├── user-findall.controller.ts │ │ │ │ └── user-findall.usecase.ts │ │ │ ├── delete │ │ │ │ ├── user-delete.dto.ts │ │ │ │ ├── user-delete.controller.ts │ │ │ │ └── user-delete.usecase.ts │ │ │ ├── find │ │ │ │ ├── user-find.dto.ts │ │ │ │ ├── user-find.controller.ts │ │ │ │ └── user-find.usecase.ts │ │ │ ├── create │ │ │ │ ├── user-create.dto.ts │ │ │ │ └── user-create.controller.ts │ │ │ ├── update │ │ │ │ ├── user-update.dto.ts │ │ │ │ ├── user-update.controller.ts │ │ │ │ └── user-update.usecase.ts │ │ │ └── user.module.ts │ │ └── app │ │ │ ├── app.module.ts │ │ │ ├── app.usecase.ts │ │ │ └── app.controller.ts │ ├── repositories │ │ ├── base-repository.interface.ts │ │ └── user │ │ │ └── user.repository.ts │ ├── app.container.ts │ ├── env.ts │ ├── main.ts │ └── providers │ │ ├── database │ │ └── postgres.provider.ts │ │ └── application │ │ └── application.provider.ts ├── .env ├── .prettierrc ├── expressots.config.ts ├── test │ └── app.usecase.spec.ts ├── .gitignore ├── register-path.js ├── jest.config.ts ├── .eslintrc.js ├── tsconfig.build.json └── tsconfig.json ├── SECURITY.md ├── .gitignore ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md └── LICENSE.md /02-typeorm-demo/typeorm-demo-vue/src/views/movie/methods.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /expressots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/expressots.png -------------------------------------------------------------------------------- /01-history/project-one/frontend/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_API_URL=http://localhost:3000/ -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/enums/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./http.enum"; 2 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npm run prod & 4 | 5 | wait -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/.env.local.example: -------------------------------------------------------------------------------- 1 | VITE_API_URL=http://api.localhost 2 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/helpers/functions/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./sleep"; 2 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/layouts/empty.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/stores/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./global"; 2 | export * from "./movie"; 3 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | logs -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/entities/base.entity.ts: -------------------------------------------------------------------------------- 1 | export interface IEntity { 2 | id: string; 3 | } 4 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/movie/index.ts: -------------------------------------------------------------------------------- 1 | import MovieForm from "./form.vue"; 2 | 3 | export { MovieForm }; 4 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/entities/base.entity.ts: -------------------------------------------------------------------------------- 1 | interface IEntity { 2 | Id: string; 3 | } 4 | 5 | export { IEntity }; 6 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/entities/base.entity.ts: -------------------------------------------------------------------------------- 1 | interface IEntity { 2 | Id: string; 3 | } 4 | 5 | export { IEntity }; 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/.env: -------------------------------------------------------------------------------- 1 | # Application 2 | ENVIRONMENT="Development" #Development, Staging, Production 3 | PORT=3000 -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/entities/base.entity.ts: -------------------------------------------------------------------------------- 1 | interface IEntity { 2 | id: number; 3 | } 4 | 5 | export { IEntity }; 6 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .dockerignore 3 | node_modules 4 | npm-debug.log 5 | README.md 6 | .git 7 | logs 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/router/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./route-list"; 2 | export * from "./router"; 3 | export * from "./routes"; 4 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report a security issue to richard.zampieri@expresso-ts.com 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts,*.vue,*.scss": [ 3 | "prettier --write", 4 | "eslint" 5 | ] 6 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./http.type"; 2 | export * from "./i18n.type"; 3 | export * from "./movie.type"; 4 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/01-history/project-one/frontend/public/favicon.ico -------------------------------------------------------------------------------- /01-history/project-one/frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/01-history/project-one/frontend/public/logo192.png -------------------------------------------------------------------------------- /01-history/project-one/frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/01-history/project-one/frontend/public/logo512.png -------------------------------------------------------------------------------- /03-opinionated-with-docker/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "endOfLine": "auto", 5 | "tabWidth": 4 6 | } -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "endOfLine": "auto", 5 | "tabWidth": 2 6 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "endOfLine": "auto", 5 | "tabWidth": 4 6 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/02-typeorm-demo/typeorm-demo-ui-react/public/favicon.ico -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/02-typeorm-demo/typeorm-demo-ui-react/public/logo192.png -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/02-typeorm-demo/typeorm-demo-ui-react/public/logo512.png -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 2 | Home Page 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/notification.scss: -------------------------------------------------------------------------------- 1 | .vue-notification .notification-content { 2 | font-weight: theme("fontWeight.medium"); 3 | } 4 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/helpers/functions/sleep.ts: -------------------------------------------------------------------------------- 1 | export function sleep(ms: number) { 2 | return new Promise((resolve) => setTimeout(resolve, ms)); 3 | } 4 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./functions"; 2 | 3 | import StringHelper from "./string.helper"; 4 | 5 | export { StringHelper }; 6 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/database/prismaClient.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | 3 | export const prismaClient = new PrismaClient(); 4 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "endOfLine": "auto", 5 | "tabWidth": 4 6 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/docs/prints/unit-coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressots/examples/HEAD/02-typeorm-demo/typeorm-demo-vue/docs/prints/unit-coverage.png -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/layouts/index.ts: -------------------------------------------------------------------------------- 1 | import empty from "./empty.vue"; 2 | import main from "./main.vue"; 3 | 4 | export default { 5 | empty, 6 | main, 7 | }; 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/pt-BR/user.ts: -------------------------------------------------------------------------------- 1 | const fieldMessages = { 2 | alreadyExists: "Usuário {name} já existe", 3 | }; 4 | 5 | export default fieldMessages; 6 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findById/IFindById.DTO.ts: -------------------------------------------------------------------------------- 1 | interface IFindByIdDTO { 2 | id: string; 3 | name: string; 4 | email: string; 5 | } 6 | 7 | export { IFindByIdDTO }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/index.ts: -------------------------------------------------------------------------------- 1 | import ptBR from "./pt-BR"; 2 | import enUS from "./en-US"; 3 | 4 | export default { 5 | "pt-BR": ptBR, 6 | "en-US": enUS, 7 | }; 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/services/index.ts: -------------------------------------------------------------------------------- 1 | import UserService from "./user.service"; 2 | import MovieService from "./movie.service"; 3 | 4 | export { UserService, MovieService }; 5 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/findall/findall-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface IFindAllResponseDTO { 2 | name: string; 3 | email: string; 4 | } 5 | 6 | export { IFindAllResponseDTO }; 7 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/getUser/getuser-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface IGetUserResponseDTO { 2 | name: string; 3 | email: string; 4 | } 5 | 6 | export { IGetUserResponseDTO }; 7 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/findall/user-findall.dto.ts: -------------------------------------------------------------------------------- 1 | export class FindAllUserResponseDTO { 2 | id: string; 3 | name: string; 4 | email: string; 5 | } 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/user/user.dto.ts: -------------------------------------------------------------------------------- 1 | interface IUserDTO { 2 | id?: string; 3 | password: string; 4 | email: string; 5 | name: string; 6 | } 7 | 8 | export { IUserDTO }; 9 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/database/IDatabaseProvider.ts: -------------------------------------------------------------------------------- 1 | interface IDatabaseProvider { 2 | Connect(): Promise; 3 | Disconnect(): Promise; 4 | } 5 | 6 | export { IDatabaseProvider }; -------------------------------------------------------------------------------- /03-opinionated-with-docker/.env: -------------------------------------------------------------------------------- 1 | # Application 2 | ENVIRONMENT="Development" #Development, Staging, Production 3 | PORT=3000 4 | 5 | # Log System 6 | FILE=general #log file name 7 | FOLDER=logs #log folder name -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/ping/ping.dto.ts: -------------------------------------------------------------------------------- 1 | interface PingResponseDTO { 2 | start: string; 3 | end: string; 4 | ttl: string; 5 | message: string; 6 | } 7 | 8 | export { PingResponseDTO }; 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/en-US/index.ts: -------------------------------------------------------------------------------- 1 | import common from "./common"; 2 | import field from "./field"; 3 | import user from "./user"; 4 | 5 | export default { ...common, field, user }; 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/pt-BR/index.ts: -------------------------------------------------------------------------------- 1 | import field from "./field"; 2 | import common from "./common"; 3 | import user from "./user"; 4 | 5 | export default { ...common, field, user }; 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/ping/ping.dto.ts: -------------------------------------------------------------------------------- 1 | interface PingResponseDTO { 2 | start: string; 3 | end: string; 4 | ttl: string; 5 | message: string; 6 | } 7 | 8 | export { PingResponseDTO }; 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/route.d.ts: -------------------------------------------------------------------------------- 1 | type Layout = "empty" | "main"; 2 | 3 | declare module "vue-router" { 4 | interface RouteMeta { 5 | layout?: Layout; 6 | } 7 | } 8 | 9 | export {}; 10 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/ping/ping.dto.ts: -------------------------------------------------------------------------------- 1 | interface PingResponseDTO { 2 | start: string; 3 | end: string; 4 | ttl: string; 5 | message: string; 6 | } 7 | 8 | export { PingResponseDTO }; 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/findall/findall-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface IFindAllResponseDTO { 2 | id: string; 3 | name: string; 4 | email: string; 5 | } 6 | 7 | export { IFindAllResponseDTO }; 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/types/movie.type.ts: -------------------------------------------------------------------------------- 1 | export interface IMovie { 2 | id: number; 3 | title: string; 4 | year: number; 5 | genre: string; 6 | } 7 | 8 | export type IMovieForm = Omit; 9 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/findall/findall-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface IFindAllUserResponseDTO { 2 | id: string; 3 | name: string; 4 | email: string; 5 | } 6 | 7 | export { IFindAllUserResponseDTO }; 8 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/services/api/index.ts: -------------------------------------------------------------------------------- 1 | import { createPlayer } from "./player/player"; 2 | 3 | const api = { 4 | player: { 5 | create: createPlayer, 6 | }, 7 | }; 8 | 9 | export default api; 10 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/en-US/user.ts: -------------------------------------------------------------------------------- 1 | const fieldMessages = { 2 | alreadyExists: "User {name} already exists", 3 | notFoundId: "User {id} not found", 4 | }; 5 | 6 | export default fieldMessages; 7 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/enums/http.enum.ts: -------------------------------------------------------------------------------- 1 | export enum ROUTE_NAMES { 2 | HOME = "home", 3 | MOVIE = "movie", 4 | MOVIE_UPDATE = "movie_update", 5 | MOVIE_CREATE = "movie_create", 6 | NOT_FOUND = "not_found", 7 | } 8 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { AppController } from "./app.controller"; 3 | 4 | export const AppModule = CreateModule([AppController]); 5 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_API_URL: string; 5 | } 6 | 7 | interface ImportMeta { 8 | readonly env: ImportMetaEnv; 9 | } 10 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/index.scss: -------------------------------------------------------------------------------- 1 | @import "./x-button.scss"; 2 | @import "./x-input.scss"; 3 | @import "./x-textarea.scss"; 4 | @import "./x-select.scss"; 5 | @import "./notification.scss"; 6 | @import "./tooltip.scss"; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findAll/findall-movie.dto.ts: -------------------------------------------------------------------------------- 1 | interface IFindAllMovieResponseDTO { 2 | id: number; 3 | title: string; 4 | genre: string; 5 | year: number; 6 | } 7 | 8 | export { IFindAllMovieResponseDTO }; 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/postcss.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | module.exports = { 4 | plugins: { 5 | "postcss-import": {}, 6 | "tailwindcss/nesting": {}, 7 | tailwindcss: {}, 8 | autoprefixer: {}, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/en-US/common/movie.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | title: "Title", 3 | year: "Year", 4 | genre: "Genre", 5 | notification: { 6 | create: { title: "Movie", text: "Movie Created Successfully" }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/pt-BR/common/movie.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | title: "Título", 3 | year: "Ano", 4 | genre: "Gênero", 5 | notification: { 6 | create: { title: "Filme", text: "Filme criado com sucesso" }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findAll/FindAllUsers.DTO.ts: -------------------------------------------------------------------------------- 1 | interface IFindAllUsersResponseDTO { 2 | id: string; 3 | name: string; 4 | email: string; 5 | createdAt: Date; 6 | updatedAt: Date; 7 | }; 8 | 9 | export { IFindAllUsersResponseDTO }; -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/app/app.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | 3 | @provide(AppUseCase) 4 | export class AppUseCase { 5 | execute() { 6 | return "Hello from ExpressoTS!"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/router/router.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from "vue-router"; 2 | import { routes } from "./"; 3 | 4 | export const router = createRouter({ 5 | history: createWebHistory(import.meta.env.BASE_URL), 6 | routes, 7 | }); 8 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/providers/bindingType/provide-singleton.ts: -------------------------------------------------------------------------------- 1 | import { fluentProvide } from "inversify-binding-decorators"; 2 | 3 | export const provideSingleton = (identifier: any) => { 4 | return fluentProvide(identifier).inSingletonScope().done(); 5 | }; 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/tsconfig.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/delete/user-delete.dto.ts: -------------------------------------------------------------------------------- 1 | export class UserDeleteRequestDTO { 2 | id: string; 3 | } 4 | 5 | export class UserDeleteResponseDTO { 6 | name: string; 7 | email: string; 8 | message: string; 9 | } 10 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/craco.config.js: -------------------------------------------------------------------------------- 1 | // craco.config.js 2 | module.exports = { 3 | style: { 4 | postcss: { 5 | plugins: [ 6 | require('tailwindcss'), 7 | require('autoprefixer'), 8 | ], 9 | }, 10 | }, 11 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/.env: -------------------------------------------------------------------------------- 1 | # Application 2 | ENVIRONMENT="Development" #Development, Staging, Production 3 | PORT=3000 4 | 5 | # Log System 6 | FILE=general #log file name 7 | FOLDER=logs #log folder name 8 | 9 | # Cors Origin 10 | CORS_ORIGIN=http://localhost:3001 -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/expressots.config.ts: -------------------------------------------------------------------------------- 1 | import { ExpressoConfig, Pattern } from "@expressots/core"; 2 | 3 | const config: ExpressoConfig = { 4 | sourceRoot: "src", 5 | scaffoldPattern: Pattern.KEBAB_CASE, 6 | opinionated: true, 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/find/user-find.dto.ts: -------------------------------------------------------------------------------- 1 | export class UserFindRequestDTO { 2 | email: string; 3 | } 4 | 5 | export class UserFindResponseDTO { 6 | id: string; 7 | name: string; 8 | email: string; 9 | message: string; 10 | } 11 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = false 9 | insert_final_newline = false 10 | max_line_length = 80 -------------------------------------------------------------------------------- /03-opinionated-with-docker/expressots.config.ts: -------------------------------------------------------------------------------- 1 | import { ExpressoConfig, Pattern } from "@expressots/core"; 2 | 3 | const config: ExpressoConfig = { 4 | sourceRoot: "src", 5 | scaffoldPattern: Pattern.KEBAB_CASE, 6 | opinionated: true, 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/create/ICreateUser.DTO.ts: -------------------------------------------------------------------------------- 1 | export interface ICreateUserDTO { 2 | name: string; 3 | email: string; 4 | password: string; 5 | } 6 | 7 | export interface ICreateUserReturnDTO { 8 | id: string, 9 | email: string, 10 | status: string 11 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import CRUDComponent from './components/CRUD.component'; 3 | 4 | function App() { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | } 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/expressots.config.ts: -------------------------------------------------------------------------------- 1 | import { ExpressoConfig, Pattern } from "@expressots/core"; 2 | 3 | const config: ExpressoConfig = { 4 | sourceRoot: "src", 5 | scaffoldPattern: Pattern.KEBAB_CASE, 6 | opinionated: true, 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'], 3 | darkMode: false, // or 'media' or 'class' 4 | theme: { 5 | extend: {}, 6 | }, 7 | variants: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/delete/delete-movie.dto.ts: -------------------------------------------------------------------------------- 1 | interface IDeleteMovieRequestDTO { 2 | id: number; 3 | } 4 | 5 | interface IDeleteMovieResponseDTO { 6 | id: number; 7 | status: string; 8 | } 9 | 10 | export { IDeleteMovieRequestDTO, IDeleteMovieResponseDTO }; 11 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/pt-BR/common/index.ts: -------------------------------------------------------------------------------- 1 | import movie from "./movie"; 2 | 3 | export default { 4 | button: { 5 | create: "Criar", 6 | }, 7 | header: { 8 | actions: "Ações", 9 | }, 10 | 11 | home: "Início", 12 | movies: "Filmes", 13 | movie, 14 | }; 15 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/ping/ping.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { PingController } from "./ping.controller"; 3 | 4 | const PingModule = CreateModule([ 5 | // Add your modules here 6 | PingController, 7 | ]); 8 | 9 | export { PingModule }; 10 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/encrypt/bcrypt/compare-passwords.provider.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from "bcrypt"; 2 | 3 | export async function comparePasswords( 4 | password: string, 5 | hashedPassword: string, 6 | ): Promise { 7 | return await bcrypt.compare(password, hashedPassword); 8 | } 9 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/base-repository.interface.ts: -------------------------------------------------------------------------------- 1 | interface IBaseRepository { 2 | create(item: T): T | null; 3 | update(item: T): T | null; 4 | delete(id: string): boolean; 5 | find(id: string): T | null; 6 | findAll(): T[]; 7 | } 8 | 9 | export { IBaseRepository }; 10 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/battle/battle-repository.interface.ts: -------------------------------------------------------------------------------- 1 | import { IBattleDTO } from "./battle.dto"; 2 | 3 | interface IBattleRepository { 4 | findAll(id: string): Promise; 5 | create(user: IBattleDTO): Promise; 6 | } 7 | 8 | export { IBattleRepository }; 9 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/ping/ping.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { PingController } from "./ping.controller"; 3 | 4 | const PingModule = CreateModule([ 5 | // Add your modules here 6 | PingController, 7 | ]); 8 | 9 | export { PingModule }; 10 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html { 6 | height: 100%; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | padding: 0; 12 | font-family: sans-serif; 13 | height: 100%; 14 | } 15 | 16 | #root { 17 | height: 100%; 18 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/en-US/common/index.ts: -------------------------------------------------------------------------------- 1 | import movie from "./movie"; 2 | 3 | export default { 4 | button: { 5 | create: "Create", 6 | }, 7 | header: { 8 | actions: "Actions", 9 | }, 10 | 11 | home: "Home", 12 | movies: "Movies", 13 | movie, 14 | }; 15 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/delete/IDeleteUser.DTO.ts: -------------------------------------------------------------------------------- 1 | interface IDeleteRequestDTO { 2 | id: string; 3 | } 4 | 5 | interface IDeleteResponseDTO { 6 | id: string; 7 | name: string; 8 | email: string; 9 | status: string; 10 | } 11 | 12 | export { IDeleteRequestDTO, IDeleteResponseDTO }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | /** @type {import('tailwindcss').Config} */ 4 | module.exports = { 5 | content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 6 | darkMode: "class", 7 | theme: {}, 8 | plugins: [require("@tailwindcss/forms")], 9 | }; 10 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/repositories/base-repository.interface.ts: -------------------------------------------------------------------------------- 1 | interface IBaseRepository { 2 | create(item: T): T | null; 3 | update(item: T): T | null; 4 | delete(id: string): boolean; 5 | find(id: string): T | null; 6 | findAll(): T[]; 7 | } 8 | 9 | export { IBaseRepository }; 10 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/create/user-create.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateUserRequestDTO { 2 | name: string; 3 | email: string; 4 | } 5 | 6 | export class CreateUserResponseDTO { 7 | id: string; 8 | name: string; 9 | email: string; 10 | message: string; 11 | } 12 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/update/user-update.dto.ts: -------------------------------------------------------------------------------- 1 | export class UserUpdateRequestDTO { 2 | name?: string; 3 | email: string; 4 | } 5 | 6 | export class UserUpdateResponseDTO { 7 | id: string; 8 | name: string; 9 | email: string; 10 | message: string; 11 | } 12 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/.env.example: -------------------------------------------------------------------------------- 1 | # Application 2 | ENVIRONMENT="Development" #Development, Staging, Production 3 | PORT=3000 4 | JWT_KEY="Your jwt key" #Base64 5 | 6 | # Data base 7 | DATABASE_URL="Your connection string" #PostgreSQL 8 | 9 | # Log System 10 | FILE=general #log file name 11 | FOLDER=logs #log folder name -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/repositories/base-repository.interface.ts: -------------------------------------------------------------------------------- 1 | export interface IBaseRepository { 2 | create(item: T): Promise; 3 | update(item: T): Promise; 4 | delete(id: string): Promise; 5 | find(id: string): Promise; 6 | findAll(): Promise; 7 | } 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/views/404.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 404 6 | PAGE NOT FOUND 7 | 8 | 9 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/login/login-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface ILoginUserDTO { 2 | email: string; 3 | password: string; 4 | } 5 | 6 | interface ILoginUserResponseDTO { 7 | name: string; 8 | email: string; 9 | token: string; 10 | status: string; 11 | } 12 | 13 | export { ILoginUserDTO, ILoginUserResponseDTO }; 14 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XBadge.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/repositories/base-repository.interface.ts: -------------------------------------------------------------------------------- 1 | interface IBaseRepository { 2 | create(item: T): T | null; 3 | update(item: T): T | null; 4 | delete(id: number | string): Promise; 5 | find(id: number): Promise; 6 | findAll(): Promise; 7 | } 8 | 9 | export { IBaseRepository }; 10 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findOne/findone-movie.dto.ts: -------------------------------------------------------------------------------- 1 | interface IFindOneMovieRequestDTO { 2 | id: number; 3 | } 4 | 5 | interface IFindOneMovieResponseDTO { 6 | id: number; 7 | title: string; 8 | genre: string; 9 | year: number; 10 | } 11 | 12 | export { IFindOneMovieResponseDTO, IFindOneMovieRequestDTO }; 13 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/create/create-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface ICreateUserDTO { 2 | name: string; 3 | email: string; 4 | } 5 | 6 | interface ICreateUserResponseDTO { 7 | id: string; 8 | name: string; 9 | email: string; 10 | status: string; 11 | } 12 | 13 | export { ICreateUserDTO, ICreateUserResponseDTO }; 14 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /01-history/project-one/src/entities/IBase.Entity.ts: -------------------------------------------------------------------------------- 1 | interface IBaseEntity { 2 | // Unique id for the created entity 3 | readonly id: string; 4 | // The date timestamp when the entity was created 5 | readonly createdAt: Date; 6 | // The date timestamp when the entity was updated 7 | readonly updatedAt: Date; 8 | } 9 | 10 | export { IBaseEntity }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./common"; 2 | export * from "./movie"; 3 | 4 | import Footer from "./Footer.vue"; 5 | import ToggleLanguage from "./ToggleLanguage.vue"; 6 | import ToggleTheme from "./ToggleTheme.vue"; 7 | import NavBar from "./navbar/index.vue"; 8 | 9 | export { Footer, NavBar, ToggleTheme, ToggleLanguage }; 10 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/create/create-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface ICreateUserRequestDTO { 2 | name: string; 3 | email: string; 4 | } 5 | 6 | interface ICreateUserResponseDTO { 7 | id: string; 8 | name: string; 9 | email: string; 10 | status: string; 11 | } 12 | 13 | export { ICreateUserRequestDTO, ICreateUserResponseDTO }; 14 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/create/create-user.dto.ts: -------------------------------------------------------------------------------- 1 | interface ICreateUserDTO { 2 | name: string; 3 | email: string; 4 | password: string; 5 | } 6 | 7 | interface ICreateUserResponseDTO { 8 | name: string; 9 | email: string; 10 | token: string; 11 | status: string; 12 | } 13 | 14 | export { ICreateUserDTO, ICreateUserResponseDTO }; 15 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { CreateUserController } from "./create/create-user.controller"; 3 | import { FindAllUserController } from "./findall/findall-user.controller"; 4 | 5 | const UserModule = CreateModule([CreateUserController, FindAllUserController]); 6 | 7 | export { UserModule }; 8 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/ping/ping.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { PingController } from "./ping.controller"; 3 | import { ContainerModule } from "inversify"; 4 | 5 | const PingModule: ContainerModule = CreateModule([ 6 | // Add your modules here 7 | PingController, 8 | ]); 9 | 10 | export { PingModule }; 11 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/types/i18n.type.ts: -------------------------------------------------------------------------------- 1 | import type { LocaleObject as LocaleObjectBase } from "yup/lib/locale"; 2 | import type { Message } from "yup/lib/types"; 3 | 4 | export interface LocaleObject extends Required { 5 | mixed: LocaleObjectBase["mixed"] & { 6 | nullable: Message; 7 | cast: Message<{ value: string }>; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /01-history/project-one/src/AppContainer.ts: -------------------------------------------------------------------------------- 1 | import { buildProviderModule } from "inversify-binding-decorators"; 2 | import { Container } from "inversify"; 3 | import { UserContainerModule } from "@useCases/user/User.Module"; 4 | 5 | const container = new Container(); 6 | 7 | container.load( 8 | buildProviderModule(), 9 | UserContainerModule 10 | ); 11 | 12 | export { container }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XTooltip.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /01-history/project-one/src/Main.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | import { ServerProvider } from "@providers/core/server/Server.Provider"; 4 | import { container } from "AppContainer"; 5 | import { Env } from "env"; 6 | 7 | 8 | async function Boostrap() { 9 | const app = await ServerProvider.Create(container); 10 | app.Listen(Env.Server.DEFAULT_PORT); 11 | } 12 | 13 | Boostrap(); 14 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/services/api/player/player.ts: -------------------------------------------------------------------------------- 1 | import { ICreatePlayerDTO } from "./createPlayer.dto"; 2 | import axios from "axios"; 3 | 4 | const PLAYER_ROUTES = { 5 | create: 'http://localhost:3001/player/create', 6 | }; 7 | 8 | export const createPlayer: (input: ICreatePlayerDTO) => void = async ( 9 | input 10 | ) => { 11 | await axios.post(PLAYER_ROUTES.create, input); 12 | }; 13 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/email/mailTrap/IMail.Provider.ts: -------------------------------------------------------------------------------- 1 | interface IAddress { 2 | email: string; 3 | name: string; 4 | } 5 | 6 | interface IMessage { 7 | from: IAddress; 8 | to: IAddress; 9 | subject: string; 10 | body: string; 11 | } 12 | 13 | interface IMailProvider { 14 | sendEmail(message: IMessage): Promise; 15 | } 16 | 17 | export { IMessage, IMailProvider }; -------------------------------------------------------------------------------- /01-history/project-one/.docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | mongodb_container: 4 | image: mongo:latest 5 | environment: 6 | MONGO_INITDB_ROOT_USERNAME: root 7 | MONGO_INITDB_ROOT_PASSWORD: root 8 | MONGO_INITDB_DATABASE: cleancode 9 | ports: 10 | - 27017:27017 11 | volumes: 12 | - mongodata:/data/db 13 | 14 | volumes: 15 | mongodata: 16 | 17 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/create/create-movie.dto.ts: -------------------------------------------------------------------------------- 1 | interface ICreateMovieRequestDTO { 2 | title: string; 3 | year: number; 4 | genre: string; 5 | } 6 | 7 | interface ICreateMovieResponseDTO { 8 | id: number | string; 9 | title: string; 10 | genre: string; 11 | year: number; 12 | status: string; 13 | } 14 | 15 | export { ICreateMovieRequestDTO, ICreateMovieResponseDTO }; 16 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/app-container.ts: -------------------------------------------------------------------------------- 1 | import { AppContainer } from "@expressots/core"; 2 | import { PingModule } from "@useCases/ping/ping.module"; 3 | import { UserModule } from "@useCases/user/user.module"; 4 | 5 | const appContainer = new AppContainer(); 6 | 7 | const container = appContainer.create([ 8 | // Add your modules here 9 | PingModule, 10 | UserModule, 11 | ]); 12 | 13 | export { container }; 14 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/repositories/user/user.repository.ts: -------------------------------------------------------------------------------- 1 | import { User } from "@entities/user.entity"; 2 | import { BaseRepository } from "@repositories/base-repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | 5 | @provide(UserRepository) 6 | class UserRepository extends BaseRepository { 7 | constructor() { 8 | super(); 9 | } 10 | } 11 | 12 | export { UserRepository }; 13 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { randomUUID } from "node:crypto"; 3 | import { IEntity } from "./base.entity"; 4 | 5 | @provide(User) 6 | export class User implements IEntity { 7 | id: string; 8 | name!: string; 9 | email!: string; 10 | 11 | constructor() { 12 | this.id = randomUUID(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/pokebattle.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { PokebattleBattleController } from "./battle/pokebattle-battle.controller"; 3 | import { PokebattleController } from "./history/pokebattle.controller"; 4 | 5 | const PokebattleModule = CreateModule([ 6 | PokebattleBattleController, 7 | PokebattleController, 8 | ]); 9 | 10 | export { PokebattleModule }; 11 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/providers/db-in-memory/db-in-memory.provider.ts: -------------------------------------------------------------------------------- 1 | import { IEntity } from "@entities/base.entity"; 2 | import { provideSingleton } from "@providers/bindingType/provide-singleton"; 3 | 4 | @provideSingleton(InMemoryDB) 5 | class InMemoryDB { 6 | private readonly USERDB: IEntity[] = []; 7 | 8 | public getUserDB(): IEntity[] { 9 | return this.USERDB; 10 | } 11 | } 12 | 13 | export { InMemoryDB }; 14 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/database/mongodb/orm/mongoose/SeedData.ts: -------------------------------------------------------------------------------- 1 | const SeedData = { 2 | users: [ 3 | { 4 | name: "Admin", 5 | email: "admin@email.com", 6 | password: "password", 7 | }, 8 | { 9 | name: "Contributor", 10 | email: "contributor@email.com", 11 | password: "password", 12 | } 13 | ] 14 | } 15 | 16 | export { SeedData }; -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/update/IUpdateUser.DTO.ts: -------------------------------------------------------------------------------- 1 | interface IUpdateUserRequestDTO { 2 | id: string; 3 | name?: string; 4 | email?: string; 5 | password?: string; 6 | } 7 | 8 | interface IUpdateUserResponseDTO { 9 | id: string; 10 | name: string; 11 | email: string; 12 | status: string; 13 | createdAt: Date; 14 | updatedAt: Date; 15 | } 16 | 17 | export { IUpdateUserRequestDTO, IUpdateUserResponseDTO }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "components.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | }, 9 | "lib": ["ESNext", "DOM", "DOM.Iterable"] 10 | }, 11 | 12 | "references": [ 13 | { 14 | "path": "./tsconfig.config.json" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Form } from "./components/Form"; 3 | 4 | function App() { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/env.ts: -------------------------------------------------------------------------------- 1 | import pkg from "../package.json"; 2 | 3 | const ENV = { 4 | Application: { 5 | APP_NAME: pkg.name, 6 | APP_VERSION: pkg.version, 7 | ENVIRONMENT: process.env.ENVIRONMENT as string, 8 | PORT: Number(process.env.PORT), 9 | }, 10 | Log: { 11 | FILE: process.env.FILE as string, 12 | FOLDER: process.env.FOLDER as string, 13 | }, 14 | }; 15 | 16 | export default ENV; 17 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/repositories/user.repository.ts: -------------------------------------------------------------------------------- 1 | import { User } from "@entities/user.entity"; 2 | import { BaseRepository } from "@repositories/base-repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | 5 | @provide(UserRepository) 6 | class UserRepository extends BaseRepository { 7 | constructor() { 8 | super(); 9 | this.entityClass = User; 10 | } 11 | } 12 | 13 | export { UserRepository }; 14 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/app.container.ts: -------------------------------------------------------------------------------- 1 | import { Container } from "inversify"; 2 | import { AppContainer } from "@expressots/core"; 3 | import { AppModule } from "@useCases/app/app.module"; 4 | import { UserModule } from "@useCases/user/user.module"; 5 | 6 | const appContainer = new AppContainer(); 7 | 8 | export const container: Container = appContainer.create([ 9 | // Add your modules here 10 | AppModule, 11 | UserModule, 12 | ]); 13 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/repositories/movie.repository.ts: -------------------------------------------------------------------------------- 1 | import { Movie } from "@entities/movie.entity"; 2 | import { BaseRepository } from "@repositories/base-repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | 5 | @provide(MovieRepository) 6 | class MovieRepository extends BaseRepository { 7 | constructor() { 8 | super(); 9 | this.entityClass = Movie; 10 | } 11 | } 12 | 13 | export { MovieRepository }; 14 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { CreateUserController } from "./create/create-user.controller"; 3 | import { FindAllUserController } from "./findall/findall-user.controller"; 4 | import { ContainerModule } from "inversify"; 5 | 6 | const UserModule: ContainerModule = CreateModule([ 7 | CreateUserController, 8 | FindAllUserController, 9 | ]); 10 | 11 | export { UserModule }; 12 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/env.ts: -------------------------------------------------------------------------------- 1 | import pkg from "../package.json"; 2 | 3 | const ENV = { 4 | Application: { 5 | APP_NAME: pkg.name, 6 | APP_VERSION: pkg.version, 7 | ENVIRONMENT: process.env.ENVIRONMENT as string, 8 | PORT: Number(process.env.PORT), 9 | }, 10 | Log: { 11 | FILE: process.env.FILE as string, 12 | FOLDER: process.env.FOLDER as string, 13 | }, 14 | }; 15 | 16 | export default ENV; 17 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/env.ts: -------------------------------------------------------------------------------- 1 | import pkg from "../package.json"; 2 | 3 | const ENV = { 4 | Application: { 5 | APP_NAME: pkg.name, 6 | APP_VERSION: pkg.version, 7 | ENVIRONMENT: process.env.ENVIRONMENT as string, 8 | PORT: Number(process.env.PORT), 9 | JWT_KEY: process.env.JWT_KEY as string, 10 | }, 11 | Log: { 12 | FILE: process.env.FILE as string, 13 | FOLDER: process.env.FOLDER as string, 14 | }, 15 | }; 16 | 17 | export default ENV; 18 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/x-input.scss: -------------------------------------------------------------------------------- 1 | @layer components { 2 | .x-input { 3 | @apply block w-full flex-1 rounded-md border-0 py-1.5 px-2 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6; 4 | 5 | &[disabled] { 6 | @apply opacity-50 cursor-not-allowed; 7 | } 8 | 9 | &.has_error { 10 | @apply outline outline-red-500; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/helpers/string.helper.ts: -------------------------------------------------------------------------------- 1 | function randomString({ length = 5 } = {}) { 2 | let result = ""; 3 | const characters = 4 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 5 | const charactersLength = characters.length; 6 | for (let i = 0; i < length; i++) { 7 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 8 | } 9 | return result; 10 | } 11 | 12 | export default { 13 | randomString, 14 | }; 15 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/x-button.scss: -------------------------------------------------------------------------------- 1 | @layer components { 2 | .x-button { 3 | @apply inline-block text-center cursor-pointer rounded-md py-2 px-3 text-sm font-medium leading-4 shadow-sm transition-all hover:bg-opacity-80 text-white bg-slate-500 hover:bg-slate-600; 4 | 5 | &:not([disabled]) { 6 | @apply active:scale-110; 7 | } 8 | 9 | &[disabled] { 10 | @apply cursor-no-drop bg-slate-400 hover:bg-slate-300 opacity-70; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/test/app.usecase.spec.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | import { AppUseCase } from "../src/useCases/app/app.usecase"; 3 | 4 | describe("AppUseCase", () => { 5 | let appUseCase: AppUseCase; 6 | 7 | beforeEach(() => { 8 | appUseCase = new AppUseCase(); 9 | }); 10 | 11 | it("returns a valid AppResponse", () => { 12 | const response = appUseCase.execute(); 13 | expect(response).toBe("Hello from ExpressoTS!"); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/main.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | import { ServerEnvironment } from "@expressots/adapter-express"; 4 | import { AppFactory } from "@expressots/core"; 5 | import { App } from "@providers/application/application.provider"; 6 | import { container } from "./app.container"; 7 | 8 | async function bootstrap() { 9 | const app = await AppFactory.create(container, App); 10 | await app.listen(3000, ServerEnvironment.Development); 11 | } 12 | 13 | bootstrap(); 14 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/app/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController } from "@expressots/core"; 2 | import { Get, controller } from "@expressots/adapter-express"; 3 | import { AppUseCase } from "./app.usecase"; 4 | 5 | @controller("/") 6 | export class AppController extends BaseController { 7 | constructor(private appUseCase: AppUseCase) { 8 | super(); 9 | } 10 | 11 | @Get("/") 12 | execute() { 13 | return this.appUseCase.execute(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/providers/orm/typeorm/postgres/postgresdb.ts: -------------------------------------------------------------------------------- 1 | import { Movie } from "@entities/movie.entity"; 2 | import { DataSourceOptions } from "typeorm"; 3 | 4 | const postgresDBConfig: DataSourceOptions = { 5 | type: "postgres", 6 | host: "localhost", 7 | port: 5432, 8 | username: "postgres", 9 | password: "postgres", 10 | database: "movieapp", 11 | synchronize: true, 12 | entities: [Movie], 13 | }; 14 | 15 | export { postgresDBConfig as PostgresDBConfig }; 16 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/battle/battle.dto.ts: -------------------------------------------------------------------------------- 1 | interface IBattleDTO { 2 | id?: string; 3 | userName: string; 4 | playerId: string; 5 | pokemon1: string; 6 | pokemon2: string; 7 | log: { 8 | turn: number; 9 | attacker: string; 10 | defender: string; 11 | attack: string; 12 | attackType: string; 13 | damage: number; 14 | }[]; 15 | winner: boolean; 16 | winnerName: string; 17 | loserName: string; 18 | isDraw: boolean; 19 | } 20 | 21 | export { IBattleDTO }; 22 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/app-container.ts: -------------------------------------------------------------------------------- 1 | import { AppContainer } from "@expressots/core/"; 2 | import { MovieModule } from "@useCases/movie/movie.module"; 3 | import { PingModule } from "@useCases/ping/ping.module"; 4 | import { UserModule } from "@useCases/user/user.module"; 5 | 6 | const appContainer = new AppContainer(); 7 | 8 | const container = appContainer.create([ 9 | // Add your modules here 10 | PingModule, 11 | //UserModule, 12 | MovieModule, 13 | ]); 14 | 15 | export { container }; 16 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/logs/.028ffe1db245944daaafe235d23bb79dab8c7eb3-audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "keep": { 3 | "days": true, 4 | "amount": 7 5 | }, 6 | "auditLog": "logs\\.028ffe1db245944daaafe235d23bb79dab8c7eb3-audit.json", 7 | "files": [ 8 | { 9 | "date": 1682360934651, 10 | "name": "logs\\general-2023-04-24.log", 11 | "hash": "9fc408c3e1926563404399d60abdbd20f0b057b8d1765d2fe219afdb32376fca" 12 | } 13 | ], 14 | "hashType": "sha256" 15 | } -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/app-container.ts: -------------------------------------------------------------------------------- 1 | import { AppContainer } from "@expressots/core"; 2 | import { PingModule } from "@useCases/ping/ping.module"; 3 | import { PokebattleModule } from "@useCases/pokebattle/pokebattle.module"; 4 | import { UserModule } from "@useCases/user/user.module"; 5 | 6 | const appContainer = new AppContainer(); 7 | 8 | const container = appContainer.create([ 9 | // Add your modules here 10 | PingModule, 11 | UserModule, 12 | PokebattleModule, 13 | ]); 14 | 15 | export { container }; 16 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/x-textarea.scss: -------------------------------------------------------------------------------- 1 | @layer components { 2 | .x-textarea { 3 | @apply block w-full flex-1 rounded-md border-0 py-1.5 px-2 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6; 4 | 5 | &[disabled] { 6 | @apply opacity-50 cursor-not-allowed; 7 | } 8 | 9 | &.has_error { 10 | @apply outline outline-red-500; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/env.ts: -------------------------------------------------------------------------------- 1 | import pkg from "../package.json"; 2 | 3 | const ENV = { 4 | Application: { 5 | APP_NAME: pkg.name, 6 | APP_VERSION: pkg.version, 7 | ENVIRONMENT: process.env.ENVIRONMENT as string, 8 | PORT: Number(process.env.PORT), 9 | }, 10 | Log: { 11 | FILE: process.env.FILE as string, 12 | FOLDER: process.env.FOLDER as string, 13 | }, 14 | Cors: { 15 | ORIGIN: process.env.CORS_ORIGIN, 16 | }, 17 | }; 18 | 19 | export default ENV; 20 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/stores/global.ts: -------------------------------------------------------------------------------- 1 | import type { RouteList } from "@/router"; 2 | import { defineStore } from "pinia"; 3 | import { useRoute } from "vue-router"; 4 | 5 | interface StateTree {} 6 | 7 | const useGlobalStore = defineStore("global", { 8 | state: (): StateTree => ({}), 9 | actions: { 10 | isActivePage(url: RouteList["url"]) { 11 | const route = useRoute(); 12 | 13 | return typeof url === "object" && route.name === url.name; 14 | }, 15 | }, 16 | }); 17 | 18 | export { useGlobalStore }; 19 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/user/user-repository.interface.ts: -------------------------------------------------------------------------------- 1 | import { IUserDTO } from "./user.dto"; 2 | 3 | interface IUserRepository { 4 | find(id: string): Promise<{ name: string; email: string } | null>; 5 | findByEmail(email: string): Promise; 6 | findAll(): Promise<{ name: string; email: string }[]>; 7 | create(user: IUserDTO): Promise; 8 | update(id: string, user: IUserDTO): Promise; 9 | delete(id: string): Promise; 10 | } 11 | 12 | export { IUserRepository }; 13 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { v4 as uuidv4 } from "uuid"; 3 | 4 | @provide(User) 5 | class User { 6 | public id: number; 7 | public name: string; 8 | public email: string; 9 | 10 | constructor(name: string, email: string) { 11 | this.id = uuidv4(); 12 | this.name = name; 13 | this.email = email; 14 | } 15 | 16 | get Id(): number { 17 | return this.id; 18 | } 19 | } 20 | 21 | export { User }; 22 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { randomUUID } from "node:crypto"; 3 | 4 | @provide(User) 5 | class User { 6 | private id: string; 7 | public name: string; 8 | public email: string; 9 | 10 | constructor(name: string, email: string) { 11 | this.id = randomUUID(); 12 | this.name = name; 13 | this.email = email; 14 | } 15 | 16 | get Id(): string { 17 | return this.id; 18 | } 19 | } 20 | 21 | export { User }; 22 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/services/api/player/createPlayer.dto.ts: -------------------------------------------------------------------------------- 1 | import * as yup from "yup"; 2 | 3 | export interface ICreatePlayerDTO { 4 | name: string; 5 | email: string; 6 | faction: string; 7 | } 8 | 9 | export const createPlayerSchema: yup.SchemaOf = yup.object({ 10 | name: yup.string().required("Name is required"), 11 | email: yup 12 | .string() 13 | .required("Please type your email") 14 | .email("Please type a valid email"), 15 | faction: yup.string().required("Please type your faction"), 16 | }); 17 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/encrypt/jwt/jwt.provider.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import jwt from "jsonwebtoken"; 3 | import ENV from "env"; 4 | 5 | @provide(JWTProvider) 6 | class JWTProvider { 7 | public decodeToken(token) { 8 | return jwt.verify(token, ENV.Application.JWT_KEY); 9 | } 10 | 11 | public generateToken(payload) { 12 | return jwt.sign(payload, ENV.Application.JWT_KEY, { 13 | expiresIn: 10800000, // expires in 3hours 14 | }); 15 | } 16 | } 17 | 18 | export { JWTProvider }; 19 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/findall/findall-user.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { User } from "@entities/user.entity"; 3 | import { UserRepository } from "@repositories/user.repository"; 4 | import { IFindAllResponseDTO } from "./findall-user.dto"; 5 | 6 | @provide(CreateUserUseCase) 7 | class CreateUserUseCase { 8 | constructor(private userRepository: UserRepository) {} 9 | 10 | execute(): IFindAllResponseDTO[] | null { 11 | return null; 12 | } 13 | } 14 | 15 | export { CreateUserUseCase }; 16 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/router/routes.ts: -------------------------------------------------------------------------------- 1 | import { ROUTE_NAMES } from "@/enums"; 2 | import i18n from "@/i18n"; 3 | import type { ComputedRef } from "vue"; 4 | import { computed } from "vue"; 5 | import type { RouteList } from "./"; 6 | 7 | const t = i18n.global.t; 8 | 9 | export const enabledRoutes: ComputedRef> = computed(() => { 10 | return [ 11 | { 12 | name: t("home"), 13 | url: { name: ROUTE_NAMES.HOME }, 14 | }, 15 | { 16 | name: t("movies"), 17 | url: { name: ROUTE_NAMES.MOVIE }, 18 | }, 19 | ]; 20 | }); 21 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/services/movie.service.ts: -------------------------------------------------------------------------------- 1 | import type { IMovie, IMovieForm } from "@/types"; 2 | import api from "./api"; 3 | 4 | function createMovie(payload: IMovieForm) { 5 | return api.post("/movie/create", payload); 6 | } 7 | 8 | function deleteMovie(id: number) { 9 | return api.del(`/movie/${id}`); 10 | } 11 | 12 | function getMovies() { 13 | return api.get("/movies"); 14 | } 15 | 16 | function getMovie(id: number) { 17 | return api.get(`/movie/${id}`); 18 | } 19 | 20 | export default { createMovie, deleteMovie, getMovies, getMovie }; 21 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /03-opinionated-with-docker/register-path.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | const path = require("path"); 4 | const tsconfigPaths = require("tsconfig-paths"); 5 | const tsconfig = require("./tsconfig.build.json"); 6 | 7 | const baseUrl = tsconfig.compilerOptions.baseUrl || "."; 8 | const outDir = tsconfig.compilerOptions.outDir || "."; 9 | 10 | let baseUrlPath = path.resolve(outDir, baseUrl); 11 | 12 | const explicitPaths = { 13 | baseUrl: baseUrlPath, 14 | paths: tsconfig.compilerOptions.paths, 15 | }; 16 | 17 | tsconfigPaths.register(explicitPaths); 18 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/database/mongodb/orm/mongoose/MongooseConnectionOptions.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import { Env } from "env"; 3 | 4 | const MongodbUri: string = 5 | "mongodb://" + 6 | Env.Database.USERNAME + 7 | ":" + 8 | Env.Database.PASSWORD + 9 | "@" + 10 | Env.Database.HOST + 11 | "/" + 12 | Env.Database.NAME + 13 | Env.Database.EXTRA_ARGS; 14 | 15 | const ConnectionOptions: mongoose.ConnectOptions = { 16 | keepAlive: true, 17 | keepAliveInitialDelay: 300000 18 | }; 19 | 20 | export { MongodbUri, ConnectionOptions }; 21 | -------------------------------------------------------------------------------- /01-history/project-one/src/repositories/user/User.Repository.ts: -------------------------------------------------------------------------------- 1 | import { IUser, User, UserDocument } from "@entities/User"; 2 | import { MongooseProvider } from "@providers/database/mongodb/orm/mongoose/Mongoose.Provider"; 3 | import { BaseRepository } from "@repositories/Base.Repository"; 4 | import { provide } from "inversify-binding-decorators"; 5 | import mongoose from "mongoose"; 6 | 7 | @provide(UserRepository) 8 | export class UserRepository extends BaseRepository { 9 | 10 | constructor() { 11 | super(); 12 | this.model = User; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/findall/findall-user.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { UserRepository } from "@repositories/user/user.repository"; 3 | import { IFindAllResponseDTO } from "./findall-user.dto"; 4 | 5 | @provide(FindAllUserUseCase) 6 | class FindAllUserUseCase { 7 | constructor(private userRepository: UserRepository) {} 8 | 9 | async execute(): Promise { 10 | const users = await this.userRepository.findAll(); 11 | return users; 12 | } 13 | } 14 | 15 | export { FindAllUserUseCase }; 16 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { CreateUserController } from "./create/create-user.controller"; 3 | import { FindAllUserController } from "./findall/findall-user.controller"; 4 | import { LoginUserController } from "./login/login-user.controller"; 5 | import { GetUserController } from "./getUser/getuser-user.controller"; 6 | 7 | const UserModule = CreateModule([ 8 | CreateUserController, 9 | FindAllUserController, 10 | LoginUserController, 11 | GetUserController, 12 | ]); 13 | 14 | export { UserModule }; 15 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/register-path.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | const path = require("path"); 4 | const tsconfigPaths = require("tsconfig-paths"); 5 | const tsconfig = require("./tsconfig.build.json"); 6 | 7 | const baseUrl = tsconfig.compilerOptions.baseUrl || "."; 8 | const outDir = tsconfig.compilerOptions.outDir || "."; 9 | 10 | let baseUrlPath = path.resolve(outDir, baseUrl); 11 | 12 | const explicitPaths = { 13 | baseUrl: baseUrlPath, 14 | paths: tsconfig.compilerOptions.paths, 15 | }; 16 | 17 | tsconfigPaths.register(explicitPaths); 18 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById("root") 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/layouts/main.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/main.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | import { App } from "@providers/application/application"; 4 | import { container } from "app-container"; 5 | import { ServerEnvironment } from "@expressots/core"; 6 | import ENV from "./env"; 7 | 8 | async function Bootstrap() { 9 | const app = App.create(container); 10 | app.listen( 11 | ENV.Application.PORT, 12 | ServerEnvironment[ENV.Application.ENVIRONMENT], 13 | { 14 | appName: ENV.Application.APP_NAME, 15 | appVersion: ENV.Application.APP_VERSION, 16 | }, 17 | ); 18 | } 19 | 20 | Bootstrap(); 21 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/providers/database/postgres.provider.ts: -------------------------------------------------------------------------------- 1 | import { provideSingleton } from "@expressots/core"; 2 | import { Pool } from "pg"; 3 | 4 | /** 5 | * Configuration of the database pool. 6 | */ 7 | const pool = { 8 | host: "localhost", 9 | port: 5432, 10 | user: "postgres", 11 | password: "postgres", 12 | database: "expressots", 13 | }; 14 | 15 | /** 16 | * Provider to inject the database pool into the container. 17 | */ 18 | @provideSingleton(PostgresProvider) 19 | export class PostgresProvider { 20 | public get Pool(): Pool { 21 | return new Pool(pool); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /01-history/project-one/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from 'ts-jest'; 2 | 3 | const jestConfig: JestConfigWithTsJest = { 4 | preset: 'ts-jest', 5 | testEnvironment: 'node', 6 | verbose: true, 7 | automock: false, 8 | testMatch: ['**/**/*.Test.ts'], 9 | collectCoverage: true, 10 | coverageReporters: ['html', 'json'], 11 | moduleNameMapper: { 12 | '^@entities/(.*)$': '/src/entities/$1', 13 | '^@providers/(.*)$': '/src/providers/$1', 14 | '^@repositories/(.*)$': '/src/repositories/$1', 15 | '^@useCases/(.*)$': '/src/useCases/$1', 16 | }, 17 | }; 18 | 19 | export default jestConfig; 20 | 21 | 22 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/core/error/ReportError.Provider.ts: -------------------------------------------------------------------------------- 1 | import Log, { LogLevel } from '@providers/core/logger/exception/ExceptionLogger.Provider'; 2 | import { AppError } from '@providers/core/error/ApplicationError'; 3 | import { provide } from 'inversify-binding-decorators'; 4 | 5 | @provide(Report) 6 | class Report { 7 | 8 | public static Error(applicationError: AppError, service: string = "api-events"): AppError { 9 | try { 10 | throw applicationError; 11 | 12 | } catch (error: any) { 13 | Log(LogLevel.Error, error, service); 14 | return error; 15 | } 16 | } 17 | } 18 | 19 | export { Report }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement 9 | ); 10 | root.render( 11 | 12 | 13 | 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require("@rushstack/eslint-patch/modern-module-resolution"); 3 | 4 | module.exports = { 5 | root: true, 6 | extends: [ 7 | "plugin:vue/vue3-essential", 8 | "eslint:recommended", 9 | "@vue/eslint-config-typescript", 10 | "@vue/eslint-config-prettier", 11 | ], 12 | parserOptions: { 13 | ecmaVersion: "latest", 14 | }, 15 | rules: { 16 | "no-console": "error", 17 | "vue/multi-word-component-names": "off", 18 | "no-unused-vars": "off", 19 | "@typescript-eslint/no-unused-vars": [ 20 | "error", 21 | { ignoreRestSiblings: true }, 22 | ], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/components/x-select.scss: -------------------------------------------------------------------------------- 1 | @layer components { 2 | .x-select { 3 | @apply flex cursor-default justify-between w-full flex-1 rounded-md border-0 py-1.5 pl-2 pr-3 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6; 4 | 5 | &.has_error { 6 | @apply outline outline-red-500; 7 | } 8 | 9 | &__options { 10 | @apply absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { CreateModule } from "@expressots/core"; 2 | import { UserCreateController } from "./create/user-create.controller"; 3 | import { UserDeleteController } from "./delete/user-delete.controller"; 4 | import { UserUpdateController } from "./update/user-update.controller"; 5 | import { UserFindController } from "./find/user-find.controller"; 6 | import { UserFindallController } from "./findall/user-findall.controller"; 7 | 8 | export const UserModule = CreateModule([ 9 | UserCreateController, 10 | UserDeleteController, 11 | UserUpdateController, 12 | UserFindController, 13 | UserFindallController, 14 | ]); 15 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from "ts-jest"; 2 | 3 | const jestConfig: JestConfigWithTsJest = { 4 | preset: "ts-jest", 5 | testEnvironment: "node", 6 | verbose: true, 7 | automock: false, 8 | testMatch: ["**/*.test.ts", "**/*.spec.ts"], 9 | coverageDirectory: "../coverage", 10 | coverageReporters: ["text", "html", "json"], 11 | moduleNameMapper: { 12 | "^@entities/(.*)$": "/src/entities/$1", 13 | "^@providers/(.*)$": "/src/providers/$1", 14 | "^@repositories/(.*)$": "/src/repositories/$1", 15 | "^@useCases/(.*)$": "/src/useCases/$1", 16 | }, 17 | }; 18 | 19 | export default jestConfig; 20 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/movie.module.ts: -------------------------------------------------------------------------------- 1 | import { ContainerModule } from "inversify"; 2 | import { CreateModule } from "@expressots/core"; 3 | import { CreateMovieController } from "./create/create-movie.controller"; 4 | import { FindAllMovieController } from "./findAll/findall-movie.controller"; 5 | import { FindOneMovieController } from "./findOne/findone-movie.controller"; 6 | import { DeleteMovieController } from "./delete/delete-movie.controller"; 7 | 8 | const MovieModule: ContainerModule = CreateModule([ 9 | CreateMovieController, 10 | FindAllMovieController, 11 | FindOneMovieController, 12 | DeleteMovieController, 13 | ]); 14 | 15 | export { MovieModule }; 16 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from "crypto"; 2 | import { provide } from "inversify-binding-decorators"; 3 | 4 | @provide(User) 5 | class User { 6 | private _id: string; 7 | private _password: string; 8 | public name: string; 9 | public email: string; 10 | 11 | constructor(name: string, email: string, password: string, id?: string) { 12 | this._id = id ?? randomUUID(); 13 | this.name = name; 14 | this.email = email; 15 | this._password = password; 16 | } 17 | 18 | get id(): string { 19 | return this._id; 20 | } 21 | 22 | get password(): string { 23 | return this._password; 24 | } 25 | } 26 | 27 | export { User }; 28 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from "ts-jest"; 2 | 3 | const jestConfig: JestConfigWithTsJest = { 4 | preset: "ts-jest", 5 | testEnvironment: "node", 6 | verbose: true, 7 | automock: false, 8 | testMatch: ["**/*.test.ts", "**/*.spec.ts"], 9 | coverageDirectory: "../coverage", 10 | coverageReporters: ["text", "html", "json"], 11 | moduleNameMapper: { 12 | "^@entities/(.*)$": "/src/entities/$1", 13 | "^@providers/(.*)$": "/src/providers/$1", 14 | "^@repositories/(.*)$": "/src/repositories/$1", 15 | "^@useCases/(.*)$": "/src/useCases/$1", 16 | }, 17 | }; 18 | 19 | export default jestConfig; 20 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/main.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | import { ServerEnvironment } from "@expressots/core"; 4 | import ENV from "./env"; 5 | import { App } from "@providers/application/application"; 6 | import cors from "cors"; 7 | import { container } from "app-container"; 8 | 9 | async function Bootstrap() { 10 | const app = App.create(container, [cors({ origin: ENV.Cors.ORIGIN })]); 11 | app.listen( 12 | ENV.Application.PORT, 13 | ServerEnvironment[ENV.Application.ENVIRONMENT], 14 | { 15 | appName: ENV.Application.APP_NAME, 16 | appVersion: ENV.Application.APP_VERSION, 17 | }, 18 | ); 19 | } 20 | 21 | Bootstrap(); 22 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/entities/movie.entity.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"; 3 | import { IEntity } from "./base.entity"; 4 | 5 | @provide(Movie) 6 | @Entity() 7 | class Movie implements IEntity { 8 | @PrimaryGeneratedColumn() 9 | id!: number; 10 | 11 | @Column() 12 | title: string; 13 | 14 | @Column() 15 | year: number; 16 | 17 | @Column() 18 | genre: string; 19 | 20 | constructor(title: string, year: number, genre: string) { 21 | this.title = title; 22 | this.year = year; 23 | this.genre = genre; 24 | } 25 | } 26 | 27 | export { Movie }; 28 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/application/application.ts: -------------------------------------------------------------------------------- 1 | import { Application, Environments, LogLevel, log } from "@expressots/core"; 2 | import { provide } from "inversify-binding-decorators"; 3 | 4 | @provide(App) 5 | class App extends Application { 6 | protected configureServices(): void { 7 | Environments.checkAll(); 8 | } 9 | 10 | // eslint-disable-next-line @typescript-eslint/no-empty-function 11 | protected postServerInitialization(): void {} 12 | 13 | protected serverShutdown(): void { 14 | log(LogLevel.Info, "Server is shutting down", "logger-provider"); 15 | super.serverShutdown(); 16 | } 17 | } 18 | 19 | const appInstance = new App(); 20 | 21 | export { appInstance as App }; 22 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/User.Module.ts: -------------------------------------------------------------------------------- 1 | import { CreateUserController } from "./create/CreateUser.Controller"; 2 | import { DeleteUserController } from "./delete/DeleteUser.Controller"; 3 | import { FindByIdController } from "./findById/FindById.Controller"; 4 | import { UpdateUserController } from "./update/UpdateUser.Controller"; 5 | import { FindAllUsersController } from "./findAll/FindAllUsers.Controller"; 6 | 7 | import { CreateModule } from "@providers/core/containerModule/BaseModule.Provider"; 8 | 9 | export const UserContainerModule = CreateModule([ 10 | CreateUserController, 11 | DeleteUserController, 12 | FindByIdController, 13 | UpdateUserController, 14 | FindAllUsersController 15 | ]); 16 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from "ts-jest"; 2 | 3 | const jestConfig: JestConfigWithTsJest = { 4 | preset: "ts-jest", 5 | testEnvironment: "node", 6 | verbose: true, 7 | automock: false, 8 | testMatch: ["**/*.test.ts", "**/*.spec.ts"], 9 | coverageDirectory: "./coverage", 10 | coverageReporters: ["text", "html", "json"], 11 | moduleNameMapper: { 12 | "^@entities/(.*)$": "/src/entities/$1", 13 | "^@providers/(.*)$": "/src/providers/$1", 14 | "^@repositories/(.*)$": "/src/repositories/$1", 15 | "^@useCases/(.*)$": "/src/useCases/$1", 16 | }, 17 | }; 18 | 19 | export default jestConfig; 20 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/providers/application/application.ts: -------------------------------------------------------------------------------- 1 | import { Application, Environments, LogLevel, log } from "@expressots/core"; 2 | import { provide } from "inversify-binding-decorators"; 3 | 4 | @provide(App) 5 | class App extends Application { 6 | protected configureServices(): void { 7 | Environments.checkAll(); 8 | } 9 | 10 | // eslint-disable-next-line @typescript-eslint/no-empty-function 11 | protected postServerInitialization(): void {} 12 | 13 | protected serverShutdown(): void { 14 | log(LogLevel.Info, "Server is shutting down", "logger-provider"); 15 | super.serverShutdown(); 16 | } 17 | } 18 | 19 | const appInstance = new App(); 20 | 21 | export { appInstance as App }; 22 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/history/pokebattle.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { 3 | IPokebattleHistoryRequestDTO, 4 | IPokebattleHistoryResponseDTO, 5 | } from "./pokebattle.dto"; 6 | import { BattleRepository } from "@repositories/battle/battle.repository"; 7 | 8 | @provide(PokebattleUseCase) 9 | class PokebattleUseCase { 10 | constructor(private historyRepository: BattleRepository) {} 11 | 12 | async execute( 13 | params: IPokebattleHistoryRequestDTO, 14 | ): Promise { 15 | const response = await this.historyRepository.findAll(params.id); 16 | 17 | return response; 18 | } 19 | } 20 | 21 | export { PokebattleUseCase }; 22 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from "ts-jest"; 2 | 3 | const jestConfig: JestConfigWithTsJest = { 4 | preset: "ts-jest", 5 | testEnvironment: "node", 6 | verbose: true, 7 | automock: false, 8 | testMatch: ["**/*.test.ts", "**/*.spec.ts"], 9 | coverageDirectory: "./coverage", 10 | coverageReporters: ["text", "html", "json"], 11 | moduleNameMapper: { 12 | "^@entities/(.*)$": "/src/entities/$1", 13 | "^@providers/(.*)$": "/src/providers/$1", 14 | "^@repositories/(.*)$": "/src/repositories/$1", 15 | "^@useCases/(.*)$": "/src/useCases/$1", 16 | }, 17 | }; 18 | 19 | export default jestConfig; 20 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/history/pokebattle.dto.ts: -------------------------------------------------------------------------------- 1 | interface IPokebattleHistoryRequestDTO { 2 | id: string; 3 | } 4 | 5 | interface IPokebattleHistoryResponseDTO { 6 | id?: string; 7 | userName: string; 8 | playerId: string; 9 | pokemon1: string; 10 | pokemon2: string; 11 | log: IPokebattleHistoryBattleLogResponseDTO[]; 12 | winner: boolean; 13 | winnerName: string; 14 | loserName: string; 15 | isDraw: boolean; 16 | } 17 | 18 | interface IPokebattleHistoryBattleLogResponseDTO { 19 | turn: number; 20 | attacker: string; 21 | defender: string; 22 | attack: string; 23 | attackType: string; 24 | damage: number; 25 | } 26 | 27 | export { IPokebattleHistoryRequestDTO, IPokebattleHistoryResponseDTO }; 28 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/main.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | import { App } from "@providers/application/application"; 4 | import { container } from "app-container"; 5 | import { ServerEnvironment } from "@expressots/core"; 6 | import ENV from "./env"; 7 | import express from "express"; 8 | import compression from "compression"; 9 | 10 | async function Bootstrap() { 11 | const app = App.create(container, [ 12 | express.json({ limit: "50mb" }), 13 | compression(), 14 | ]); 15 | app.listen( 16 | ENV.Application.PORT, 17 | ServerEnvironment[ENV.Application.ENVIRONMENT], 18 | { 19 | appName: ENV.Application.APP_NAME, 20 | appVersion: ENV.Application.APP_VERSION, 21 | }, 22 | ); 23 | } 24 | 25 | Bootstrap(); 26 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/middlewares/AuthMiddleware/AuthMiddleware.Provider.ts: -------------------------------------------------------------------------------- 1 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 2 | import { Env } from "env"; 3 | import { Request, Response, NextFunction } from "express"; 4 | 5 | const AuthMiddleware = (req: Request, res: Response, next: NextFunction) => { 6 | 7 | const secret = Env.Security.JWT_SECRET; 8 | const authHeader = req.get("Authorization"); 9 | 10 | if (authHeader === secret) { 11 | const token: string = authHeader.split(" ")[1]; 12 | return next(); 13 | } else { 14 | return res.status(StatusCode.Unauthorized).json({ error: StatusCode.Unauthorized, message: "You don't sufficient privileges" }); 15 | } 16 | } 17 | 18 | export default AuthMiddleware; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/providers/application/application.ts: -------------------------------------------------------------------------------- 1 | import { Application, Environments, LogLevel, log } from "@expressots/core"; 2 | import { TypeORMProvider } from "@providers/orm/typeorm/typeorm.provider"; 3 | import { provide } from "inversify-binding-decorators"; 4 | 5 | @provide(App) 6 | class App extends Application { 7 | protected configureServices(): void { 8 | Environments.checkAll(); 9 | } 10 | 11 | protected postServerInitialization(): void { 12 | TypeORMProvider.connect(); 13 | } 14 | 15 | protected serverShutdown(): void { 16 | log(LogLevel.Info, "Server is shutting down", "logger-provider"); 17 | super.serverShutdown(); 18 | } 19 | } 20 | 21 | const appInstance = new App(); 22 | 23 | export { appInstance as App }; 24 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/ping/ping.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { PingResponseDTO } from "./ping.dto"; 3 | 4 | @provide(PingUseCase) 5 | class PingUseCase { 6 | execute(start: Date): PingResponseDTO { 7 | const end: Date = new Date(); 8 | const timeToRespond: number = end.getTime() - start.getTime(); 9 | const ttl: number = timeToRespond / 1000; 10 | 11 | const format = (d: Date) => { 12 | return d.toISOString().replace(/T/, " ").replace(/\..+/, ""); 13 | }; 14 | 15 | const response: PingResponseDTO = { 16 | start: format(start), 17 | end: format(end), 18 | ttl: `${ttl.toFixed(2)} sec`, 19 | message: "Pong!", 20 | }; 21 | 22 | return response; 23 | } 24 | } 25 | 26 | export { PingUseCase }; 27 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/findall/findall-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller, httpGet, response } from "inversify-express-utils"; 3 | import { IFindAllResponseDTO } from "./findall-user.dto"; 4 | import { FindAllUserUseCase } from "./findall-user.usecase"; 5 | 6 | @controller("/user") 7 | class FindAllUserController extends BaseController { 8 | constructor(private FindAllUserUseCase: FindAllUserUseCase) { 9 | super("create-user-controller"); 10 | } 11 | 12 | @httpGet("/") 13 | execute(@response() res: IFindAllResponseDTO[]): any { 14 | return this.callUseCaseAsync( 15 | this.FindAllUserUseCase.execute(), 16 | res, 17 | StatusCode.OK, 18 | ); 19 | } 20 | } 21 | 22 | export { FindAllUserController }; 23 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/prisma/migrations/20230422172303_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "User" ( 3 | "id" TEXT NOT NULL, 4 | "email" TEXT NOT NULL, 5 | "name" TEXT NOT NULL, 6 | "password" TEXT NOT NULL, 7 | 8 | CONSTRAINT "User_pkey" PRIMARY KEY ("id") 9 | ); 10 | 11 | -- CreateTable 12 | CREATE TABLE "Battle" ( 13 | "id" TEXT NOT NULL, 14 | "log" JSONB[], 15 | "playerId" TEXT NOT NULL, 16 | "userName" TEXT NOT NULL, 17 | "winner" BOOLEAN NOT NULL, 18 | "pokemon1" TEXT NOT NULL, 19 | "pokemon2" TEXT NOT NULL, 20 | "winnerName" TEXT NOT NULL, 21 | "loserName" TEXT NOT NULL, 22 | "isDraw" BOOLEAN NOT NULL, 23 | 24 | CONSTRAINT "Battle_pkey" PRIMARY KEY ("id") 25 | ); 26 | 27 | -- CreateIndex 28 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); 29 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/findall/user-findall.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { Get, controller, response } from "@expressots/adapter-express"; 3 | import { Response } from "express"; 4 | import { FindAllUserResponseDTO } from "./user-findall.dto"; 5 | import { FindAllUserUseCase } from "./user-findall.usecase"; 6 | 7 | @controller("/user/findall") 8 | export class UserFindallController extends BaseController { 9 | constructor(private findallUserUseCase: FindAllUserUseCase) { 10 | super(); 11 | } 12 | 13 | @Get("/") 14 | async execute(@response() res: Response): Promise { 15 | const useCase = await this.findallUserUseCase.execute(); 16 | return this.callUseCase(useCase, res, StatusCode.OK); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/findall/findall-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller, httpGet, response } from "inversify-express-utils"; 3 | import { IFindAllResponseDTO } from "./findall-user.dto"; 4 | import { CreateUserUseCase } from "./findall-user.usecase"; 5 | 6 | @controller("/user") 7 | class FindAllUserController extends BaseController { 8 | constructor(private createUserUseCase: CreateUserUseCase) { 9 | super("create-user-controller"); 10 | } 11 | 12 | @httpGet("/") 13 | execute(@response() res: any): IFindAllResponseDTO { 14 | return this.callUseCase( 15 | this.createUserUseCase.execute(), 16 | res, 17 | StatusCode.OK, 18 | ); 19 | } 20 | } 21 | 22 | export { FindAllUserController }; 23 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/ping/ping.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller } from "inversify-express-utils"; 3 | import { httpGet, response } from "inversify-express-utils/lib/decorators"; 4 | import { PingUseCase } from "./ping.usecase"; 5 | import { PingResponseDTO } from "./ping.dto"; 6 | 7 | @controller("/ping") 8 | class PingController extends BaseController { 9 | constructor(private pingUseCase: PingUseCase) { 10 | super("default-router-controller"); 11 | } 12 | 13 | @httpGet("") 14 | execute(@response() res: any): Promise { 15 | const start: Date = new Date(); 16 | 17 | return this.callUseCase( 18 | this.pingUseCase.execute(start), 19 | res, 20 | StatusCode.OK, 21 | ); 22 | } 23 | } 24 | 25 | export { PingController }; 26 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/ping/ping.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller } from "inversify-express-utils"; 3 | import { httpGet, response } from "inversify-express-utils/lib/decorators"; 4 | import { PingResponseDTO } from "./ping.dto"; 5 | import { PingUseCase } from "./ping.usecase"; 6 | 7 | @controller("/ping") 8 | class PingController extends BaseController { 9 | constructor(private pingUseCase: PingUseCase) { 10 | super("default-router-controller"); 11 | } 12 | 13 | @httpGet("") 14 | execute(@response() res: any): Promise { 15 | const start: Date = new Date(); 16 | 17 | return this.callUseCase( 18 | this.pingUseCase.execute(start), 19 | res, 20 | StatusCode.OK, 21 | ); 22 | } 23 | } 24 | 25 | export { PingController }; 26 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/findall/findall-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller, httpGet, response } from "inversify-express-utils"; 3 | import { IFindAllUserResponseDTO } from "./findall-user.dto"; 4 | import { FindAllUserUseCase } from "./findall-user.usecase"; 5 | 6 | @controller("/user/findall") 7 | class FindAllUserController extends BaseController { 8 | constructor(private findallUserUseCase: FindAllUserUseCase) { 9 | super("findall-user-controller"); 10 | } 11 | 12 | @httpGet("/") 13 | execute(@response() res: any): IFindAllUserResponseDTO { 14 | return this.callUseCase( 15 | this.findallUserUseCase.execute(), 16 | res, 17 | StatusCode.OK, 18 | ); 19 | } 20 | } 21 | 22 | export { FindAllUserController }; 23 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/repositories/user/user.repository.ts: -------------------------------------------------------------------------------- 1 | import { User } from "@entities/user.entity"; 2 | import { BaseRepository } from "@repositories/base-repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | 5 | @provide(UserRepository) 6 | export class UserRepository extends BaseRepository { 7 | constructor() { 8 | super(); 9 | this.tableName = "users"; 10 | } 11 | 12 | async findByEmail(email: string): Promise { 13 | const client = await this.db.connect(); 14 | 15 | try { 16 | const res = await client.query( 17 | `SELECT * FROM users WHERE email = $1`, 18 | [email], 19 | ); 20 | 21 | return res.rows[0] as User; 22 | } finally { 23 | client.release(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/ping/ping.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { PingResponseDTO } from "./ping.dto"; 3 | 4 | @provide(PingUseCase) 5 | class PingUseCase { 6 | execute(start: Date): PingResponseDTO { 7 | const end: Date = new Date(); 8 | const timeToRespond: number = end.getTime() - start.getTime(); 9 | const ttl: number = timeToRespond / 1000; 10 | 11 | const format = (d: Date) => { 12 | return d.toISOString().replace(/T/, " ").replace(/\..+/, ""); 13 | }; 14 | 15 | const response: PingResponseDTO = { 16 | start: format(start), 17 | end: format(end), 18 | ttl: `${ttl.toFixed(2)} sec`, 19 | message: "Pong!", 20 | }; 21 | 22 | return response; 23 | } 24 | } 25 | 26 | export { PingUseCase }; 27 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findAll/FindAllUsers.Controller.ts: -------------------------------------------------------------------------------- 1 | import { controller, httpGet, response } from "inversify-express-utils"; 2 | import { FindAllUsersUseCase } from "./FindAllUsers.UseCase"; 3 | import { IFindAllUsersResponseDTO } from "./FindAllUsers.DTO"; 4 | import { BaseController } from "@providers/core/controller/Controller.Provider"; 5 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 6 | 7 | @controller("/users") 8 | class FindAllUsersController extends BaseController { 9 | constructor(private updateUserUseCase: FindAllUsersUseCase) { 10 | super("user-find-all-controller"); 11 | } 12 | 13 | @httpGet("/") 14 | async Execute(@response() res): Promise { 15 | 16 | return this.CallUseCase(this.updateUserUseCase.Execute(), res, StatusCode.OK); 17 | } 18 | } 19 | 20 | export { FindAllUsersController }; -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findById/FindById.Controller.ts: -------------------------------------------------------------------------------- 1 | import { controller, httpGet, requestParam, response } from "inversify-express-utils"; 2 | import { FindByIdUseCase } from "./FindById.UseCase"; 3 | import { IFindByIdDTO } from "./IFindById.DTO"; 4 | import { BaseController } from "@providers/core/controller/Controller.Provider"; 5 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 6 | 7 | @controller("/user") 8 | class FindByIdController extends BaseController { 9 | constructor(private findByIdUseCase: FindByIdUseCase) { 10 | super("user-find-by-id-controller"); 11 | } 12 | 13 | @httpGet("/find/:id") 14 | async Execute(@requestParam("id") id: string, @response() res): Promise { 15 | 16 | return this.CallUseCase(this.findByIdUseCase.Execute(id), res, StatusCode.OK); 17 | } 18 | } 19 | 20 | export { FindByIdController }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/ping/ping.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { PingResponseDTO } from "./ping.dto"; 3 | 4 | @provide(PingUseCase) 5 | class PingUseCase { 6 | execute(start: Date): PingResponseDTO { 7 | const end: Date = new Date(); 8 | const timeToRespond: number = end.getTime() - start.getTime(); 9 | const ttl: number = timeToRespond / 1000; 10 | 11 | const format = (d: Date) => { 12 | return d.toISOString().replace(/T/, " ").replace(/\..+/, ""); 13 | }; 14 | 15 | const response: PingResponseDTO = { 16 | start: format(start), 17 | end: format(end), 18 | ttl: `${ttl.toFixed(2)} sec`, 19 | message: "Hello Expresso TS!", 20 | }; 21 | 22 | return response; 23 | } 24 | } 25 | 26 | export { PingUseCase }; 27 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/ping/ping.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller } from "inversify-express-utils"; 3 | import { httpGet, response } from "inversify-express-utils/lib/decorators"; 4 | import { PingUseCase } from "./ping.usecase"; 5 | import { PingResponseDTO } from "./ping.dto"; 6 | 7 | @controller("/ping") 8 | class PingController extends BaseController { 9 | constructor(private pingUseCase: PingUseCase) { 10 | super("default-router-controller"); 11 | } 12 | 13 | @httpGet("") 14 | execute(@response() res: any): Promise { 15 | const start: Date = new Date(); 16 | 17 | return this.callUseCase( 18 | this.pingUseCase.execute(start), 19 | res, 20 | StatusCode.OK, 21 | ); 22 | } 23 | } 24 | 25 | export { PingController }; 26 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findAll/findall-movie.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { controller, httpGet, response } from "inversify-express-utils"; 3 | import { IFindAllMovieResponseDTO } from "./findall-movie.dto"; 4 | import { FindAllMovieUseCase } from "./findall-movie.usecase"; 5 | 6 | @controller("/movies") 7 | class FindAllMovieController extends BaseController { 8 | constructor(private findallMovieUseCase: FindAllMovieUseCase) { 9 | super("findall-movie-controller"); 10 | } 11 | 12 | @httpGet("/") 13 | async execute(@response() res: any): Promise { 14 | return this.callUseCaseAsync( 15 | this.findallMovieUseCase.execute(), 16 | res, 17 | StatusCode.OK, 18 | ); 19 | } 20 | } 21 | 22 | export { FindAllMovieController }; 23 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/components.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | XPage, 3 | XButton, 4 | XSelect, 5 | XInput, 6 | XTextarea, 7 | XAlert, 8 | XPagination, 9 | XDialog, 10 | XTable, 11 | XSwitch, 12 | XTooltip, 13 | XBadge, 14 | } from "@/components"; 15 | import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; 16 | 17 | declare module "@vue/runtime-core" { 18 | export interface GlobalComponents { 19 | XPage: typeof XPage; 20 | XButton: typeof XButton; 21 | XSelect: typeof XSelect; 22 | XInput: typeof XInput; 23 | XTextarea: typeof XTextarea; 24 | XAlert: typeof XAlert; 25 | XPagination: typeof XPagination; 26 | XDialog: typeof XDialog; 27 | XTable: typeof XTable; 28 | XSwitch: typeof XSwitch; 29 | XTooltip: typeof XTooltip; 30 | XBadge: typeof XBadge; 31 | FontAwesomeIcon: typeof FontAwesomeIcon; 32 | } 33 | } 34 | 35 | export {}; 36 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import "./base.css"; 2 | @import "./components/index.scss"; 3 | 4 | a { 5 | color: theme('colors.blue.400'); 6 | } 7 | 8 | #app { 9 | min-height: 100vh; 10 | display: flex; 11 | flex-direction: column; 12 | } 13 | 14 | b, 15 | strong { 16 | font-weight: theme('fontWeight.bold'); 17 | } 18 | 19 | /* CODE */ 20 | 21 | code { 22 | font-family: inherit; 23 | text-shadow: 0 0 1px theme("colors.red.400"); 24 | padding: 0 2px; 25 | @apply text-red-400 bg-red-100 px-1 rounded-md dark:text-gray-400 dark:bg-gray-800 text-xs; 26 | } 27 | 28 | .dark code { 29 | text-shadow: 0 0 1px theme("colors.gray.400"); 30 | } 31 | 32 | /* INPUT */ 33 | 34 | .required::after { 35 | content: "*"; 36 | margin-left: 3px; 37 | position: absolute; 38 | top: 58%; 39 | transform: translateY(-42%); 40 | @apply text-red-500 dark:text-red-400 text-xl; 41 | } 42 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | plugins: ["@typescript-eslint/eslint-plugin"], 4 | extends: [ 5 | "plugin:@typescript-eslint/recommended", 6 | "plugin:prettier/recommended", 7 | ], 8 | root: true, 9 | env: { 10 | node: true, 11 | jest: true, 12 | }, 13 | ignorePatterns: [".eslintrc.js"], 14 | rules: { 15 | "@typescript-eslint/interface-name-prefix": "off", 16 | "@typescript-eslint/explicit-function-return-type": "off", 17 | "@typescript-eslint/explicit-module-boundary-types": "off", 18 | "@typescript-eslint/no-explicit-any": "off", 19 | "no-trailing-spaces": ["error", { skipBlankLines: true }], 20 | "no-multi-spaces": ["error", { ignoreEOLComments: true }], 21 | "no-multi-spaces": "off", 22 | "prettier/prettier": ["error", { endOfLine: "auto" }, { tabWidth: 4 }], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/getUser/getuser-user.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { UserRepository } from "@repositories/user/user.repository"; 3 | import { IGetUserResponseDTO } from "./getuser-user.dto"; 4 | import { AppError, Report, StatusCode } from "@expressots/core"; 5 | 6 | @provide(GetUserUseCase) 7 | class GetUserUseCase { 8 | constructor(private userRepository: UserRepository) {} 9 | 10 | async execute(req): Promise { 11 | const { id } = req; 12 | const user = await this.userRepository.find(id); 13 | 14 | if (!user) { 15 | Report.Error( 16 | new AppError( 17 | StatusCode.NotFound, 18 | "User not found", 19 | "create-user-usecase", 20 | ), 21 | ); 22 | } 23 | 24 | return user; 25 | } 26 | } 27 | 28 | export { GetUserUseCase }; 29 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/test/ping.usecase.spec.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | import { PingUseCase } from "@useCases/ping/ping.usecase"; 3 | 4 | describe("PingUseCase", () => { 5 | let pingUseCase: PingUseCase; 6 | 7 | beforeEach(() => { 8 | pingUseCase = new PingUseCase(); 9 | }); 10 | 11 | it("should return a valid PingResponseDTO", () => { 12 | const start: Date = new Date(); 13 | const response = pingUseCase.execute(start); 14 | const end: Date = new Date(response.end); 15 | const ttl = parseFloat(response.ttl.split(" ")[0]); 16 | 17 | expect(response).toHaveProperty("start"); 18 | expect(response).toHaveProperty("end"); 19 | expect(response).toHaveProperty("ttl"); 20 | expect(response).toHaveProperty("message"); 21 | expect(response.message).toBe("Pong!"); 22 | expect(start <= end).toBe(true); 23 | expect(ttl >= 0).toBe(true); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/delete/DeleteUser.Controller.ts: -------------------------------------------------------------------------------- 1 | import { controller, httpDelete, requestParam, response } from 'inversify-express-utils'; 2 | import { DeleteUserUseCase } from './DeleteUser.UseCase'; 3 | import { IDeleteResponseDTO } from './IDeleteUser.DTO'; 4 | 5 | import { BaseController } from '@providers/core/controller/Controller.Provider'; 6 | import { StatusCode } from '@providers/core/error/ErrorTypes'; 7 | 8 | @controller('/user') 9 | export class DeleteUserController extends BaseController { 10 | 11 | constructor(private deleteUserUseCase: DeleteUserUseCase) { 12 | super("user-delete-controller"); 13 | } 14 | 15 | @httpDelete('/delete/:id') 16 | async Execute(@requestParam("id") id: string, @response() res): Promise { 17 | 18 | return this.CallUseCase(this.deleteUserUseCase.Execute({ id: id }), res, StatusCode.OK); 19 | } 20 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XSwitch.vue: -------------------------------------------------------------------------------- 1 | 2 | $emit('update:modelValue', !modelValue)" 5 | > 6 | 12 | 16 | 17 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/test/ping.usecase.spec.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | import { PingUseCase } from "@useCases/ping/ping.usecase"; 3 | 4 | describe("PingUseCase", () => { 5 | let pingUseCase: PingUseCase; 6 | 7 | beforeEach(() => { 8 | pingUseCase = new PingUseCase(); 9 | }); 10 | 11 | it("should return a valid PingResponseDTO", () => { 12 | const start: Date = new Date(); 13 | const response = pingUseCase.execute(start); 14 | const end: Date = new Date(response.end); 15 | const ttl = parseFloat(response.ttl.split(" ")[0]); 16 | 17 | expect(response).toHaveProperty("start"); 18 | expect(response).toHaveProperty("end"); 19 | expect(response).toHaveProperty("ttl"); 20 | expect(response).toHaveProperty("message"); 21 | expect(response.message).toBe("Hello Expresso TS!"); 22 | expect(start <= end).toBe(true); 23 | expect(ttl >= 0).toBe(true); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/XAlert.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 36 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/battle/pokebattle-battle.dto.ts: -------------------------------------------------------------------------------- 1 | import { TPokemonContentEndpoint } from "@providers/types/battle"; 2 | 3 | interface IPokebattleBattleRequestDTO { 4 | pokemon1: TPokemonContentEndpoint; 5 | pokemon2: TPokemonContentEndpoint; 6 | } 7 | 8 | interface IPokebattleBattleLogResponseDTO { 9 | turn: number; 10 | attacker: string; 11 | defender: string; 12 | attack: string; 13 | attackType: string; 14 | damage: number; 15 | } 16 | 17 | interface IPokebattleBattleResponseDTO { 18 | id?: string; 19 | userName: string; 20 | playerId: string; 21 | pokemon1: string; 22 | pokemon2: string; 23 | log: IPokebattleBattleLogResponseDTO[]; 24 | winner: boolean; 25 | winnerName: string; 26 | loserName: string; 27 | isDraw: boolean; 28 | } 29 | 30 | export { 31 | IPokebattleBattleLogResponseDTO, 32 | IPokebattleBattleRequestDTO, 33 | IPokebattleBattleResponseDTO, 34 | }; 35 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/login/login-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { ILoginUserDTO, ILoginUserResponseDTO } from "./login-user.dto"; 9 | import { LoginUserUsecase } from "./login-user.usecase"; 10 | 11 | @controller("/user/login") 12 | class LoginUserController extends BaseController { 13 | constructor(private loginUserUseCase: LoginUserUsecase) { 14 | super("login-user-controller"); 15 | } 16 | 17 | @httpPost("/") 18 | execute( 19 | @requestBody() data: ILoginUserDTO, 20 | @response() res: ILoginUserResponseDTO, 21 | ): any { 22 | return this.callUseCaseAsync( 23 | this.loginUserUseCase.execute(data), 24 | res, 25 | StatusCode.OK, 26 | ); 27 | } 28 | } 29 | 30 | export { LoginUserController }; 31 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/types/http.type.ts: -------------------------------------------------------------------------------- 1 | export interface ResponseSuccess { 2 | message: string; 3 | } 4 | 5 | export interface ResponseSuccessWithModel extends ResponseSuccess { 6 | model: T; 7 | } 8 | 9 | export interface ResponseError extends ResponseSuccess { 10 | errors?: { [field: string]: string }; 11 | } 12 | 13 | export interface Meta { 14 | "x-pagination-current-page": string; 15 | "x-pagination-page-count": string; 16 | } 17 | 18 | export const DEFAULT_META: Meta = Object.freeze({ 19 | "x-pagination-current-page": "1", 20 | "x-pagination-page-count": "1", 21 | }); 22 | 23 | export function isMeta(object: unknown): object is Meta { 24 | return ( 25 | !object || 26 | typeof object !== "object" || 27 | !Object.keys(DEFAULT_META).every((key) => key in object) 28 | ); 29 | } 30 | 31 | export interface BaseParams { 32 | page?: number | string; 33 | "per-page"?: number | string; 34 | } 35 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/middlewares/auth.ts: -------------------------------------------------------------------------------- 1 | import { JWTProvider } from "@providers/encrypt/jwt/jwt.provider"; 2 | import { Request, Response, NextFunction } from "express"; 3 | 4 | function authMiddleware( 5 | req: Request, 6 | res: Response, 7 | next: NextFunction, 8 | ): Response> | void { 9 | const jwtProvider: JWTProvider = new JWTProvider(); 10 | 11 | const token = req.headers["authorization"]; 12 | 13 | if (!token) { 14 | return res 15 | .status(401) 16 | .json({ auth: false, message: "Sem token na requisição" }); 17 | } 18 | 19 | try { 20 | const decoded = jwtProvider.decodeToken(token); 21 | 22 | req.headers["decoded"] = decoded as string; 23 | next(); 24 | } catch (error) { 25 | return res 26 | .status(401) 27 | .json({ auth: false, message: "Token expirado ou incorreto." }); 28 | } 29 | } 30 | 31 | export default authMiddleware; 32 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2017", 5 | "declaration": true, 6 | "removeComments": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "resolveJsonModule": true, 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "rootDir": "./", 13 | "baseUrl": "./src", 14 | "paths": { 15 | "@entities/*": ["entities/*"], 16 | "@providers/*": ["providers/*"], 17 | "@repositories/*": ["repositories/*"], 18 | "@useCases/*": ["useCases/*"] 19 | }, 20 | "esModuleInterop": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "strict": true, 23 | "noImplicitAny": false, 24 | "skipLibCheck": true, 25 | "types": ["reflect-metadata", "node", "jest"] 26 | }, 27 | "include": [".", "src/**/*.ts", ".eslintrc.js"], 28 | "exclude": ["node_modules", "dist"] 29 | } 30 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint/eslint-plugin'], 4 | extends: [ 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:prettier/recommended', 7 | ], 8 | root: true, 9 | env: { 10 | node: true, 11 | jest: true, 12 | }, 13 | ignorePatterns: ['.eslintrc.js'], 14 | rules: { 15 | '@typescript-eslint/interface-name-prefix': 'off', 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@typescript-eslint/explicit-module-boundary-types': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | "no-trailing-spaces": ["error", { "skipBlankLines": true}], 20 | "no-multi-spaces": ["error", { "ignoreEOLComments": true }], 21 | "no-multi-spaces": "off", 22 | "prettier/prettier": ["error", { "endOfLine": "auto", "tabWidth": 4 }], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint/eslint-plugin'], 4 | extends: [ 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:prettier/recommended', 7 | ], 8 | root: true, 9 | env: { 10 | node: true, 11 | jest: true, 12 | }, 13 | ignorePatterns: ['.eslintrc.js'], 14 | rules: { 15 | '@typescript-eslint/interface-name-prefix': 'off', 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@typescript-eslint/explicit-module-boundary-types': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | "no-trailing-spaces": ["error", { "skipBlankLines": true}], 20 | "no-multi-spaces": ["error", { "ignoreEOLComments": true }], 21 | "no-multi-spaces": "off", 22 | "prettier/prettier": ["error", { "endOfLine": "auto" }, { "tabWidth": 4}], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/create/create-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { ICreateUserDTO, ICreateUserResponseDTO } from "./create-user.dto"; 9 | import { CreateUserUseCase } from "./create-user.usecase"; 10 | 11 | @controller("/user/create") 12 | class CreateUserController extends BaseController { 13 | constructor(private createUserUseCase: CreateUserUseCase) { 14 | super("create-user-controller"); 15 | } 16 | 17 | @httpPost("/") 18 | execute( 19 | @requestBody() data: ICreateUserDTO, 20 | @response() res: ICreateUserResponseDTO, 21 | ): any { 22 | return this.callUseCaseAsync( 23 | this.createUserUseCase.execute(data), 24 | res, 25 | StatusCode.Created, 26 | ); 27 | } 28 | } 29 | 30 | export { CreateUserController }; 31 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/find/user-find.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { Response } from "express"; 3 | import { UserFindRequestDTO, UserFindResponseDTO } from "./user-find.dto"; 4 | import { UserFindUseCase } from "./user-find.usecase"; 5 | import { Get, controller, param, response } from "@expressots/adapter-express"; 6 | 7 | @controller("/user/find") 8 | export class UserFindController extends BaseController { 9 | constructor(private userFindUseCase: UserFindUseCase) { 10 | super(); 11 | } 12 | 13 | @Get("/:email") 14 | async execute( 15 | @param() payload: UserFindRequestDTO, 16 | @response() res: Response, 17 | ): Promise { 18 | return this.callUseCase( 19 | await this.userFindUseCase.execute(payload), 20 | res, 21 | StatusCode.OK, 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { fileURLToPath, URL } from "node:url"; 4 | 5 | import { defineConfig } from "vite"; 6 | import vue from "@vitejs/plugin-vue"; 7 | import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"; 8 | import { dirname, resolve } from "node:path"; 9 | 10 | // https://vitejs.dev/config/ 11 | export default defineConfig({ 12 | plugins: [ 13 | vue(), 14 | VueI18nPlugin({ 15 | include: resolve( 16 | dirname(fileURLToPath(import.meta.url)), 17 | "./src/messages/**" 18 | ), 19 | }), 20 | ], 21 | resolve: { 22 | alias: { 23 | "@": fileURLToPath(new URL("./src", import.meta.url)), 24 | }, 25 | }, 26 | test: { 27 | globals: true, 28 | environment: "happy-dom", 29 | coverage: { 30 | all: true, 31 | include: ["src/**/*"], 32 | exclude: ["src/**/index.ts", "src/**/*.d.ts"], 33 | }, 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/test/ping.usecase.spec.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | import { PingUseCase } from "@useCases/ping/ping.usecase"; 3 | 4 | describe("PingUseCase", () => { 5 | let pingUseCase: PingUseCase; 6 | 7 | beforeEach(() => { 8 | pingUseCase = new PingUseCase(); 9 | }); 10 | 11 | it("should return a valid PingResponseDTO", () => { 12 | const start: Date = new Date(); 13 | const response = pingUseCase.execute(start); 14 | const end: Date = new Date(response.end); 15 | const ttl = parseFloat(response.ttl.split(" ")[0]); 16 | 17 | expect(response).toHaveProperty("start"); 18 | expect(response).toHaveProperty("end"); 19 | expect(response).toHaveProperty("ttl"); 20 | expect(response).toHaveProperty("message"); 21 | expect(response.message).toBe("Pong!"); 22 | expect(start <= end).toBe(true); 23 | expect(ttl >= 0).toBe(true); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "postgres" 10 | url = env("DATABASE_URL") 11 | relationMode = "prisma" 12 | } 13 | 14 | model User { 15 | id String @id @default(uuid()) 16 | email String @unique 17 | name String 18 | password String 19 | Battle Battle[] 20 | } 21 | 22 | model Battle { 23 | id String @id @default(uuid()) 24 | player User @relation(fields: [playerId], references: [id]) 25 | log Json[] 26 | playerId String // relation scalar field (used in the `@relation` attribute above) 27 | userName String 28 | winner Boolean 29 | pokemon1 String 30 | pokemon2 String 31 | winnerName String 32 | loserName String 33 | isDraw Boolean 34 | } 35 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/user/getUser/getuser-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpGet, 5 | requestHeaders, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { IGetUserResponseDTO } from "./getuser-user.dto"; 9 | import { GetUserUseCase } from "./getuser-user.usecase"; 10 | import authMiddleware from "@providers/middlewares/auth"; 11 | 12 | @controller("/user/info") 13 | class GetUserController extends BaseController { 14 | constructor(private GetUserUseCase: GetUserUseCase) { 15 | super("get-user-controller"); 16 | } 17 | @httpGet("/", authMiddleware) 18 | execute( 19 | @response() res: IGetUserResponseDTO[], 20 | @requestHeaders("decoded") req, 21 | ): any { 22 | return this.callUseCaseAsync( 23 | this.GetUserUseCase.execute(req), 24 | res, 25 | StatusCode.OK, 26 | ); 27 | } 28 | } 29 | 30 | export { GetUserController }; 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | 02-typeorm-demo/typeorm-demo-api/node_modules/ 5 | 02-typeorm-demo/typeorm-demo-ui-react/node_modules/ 6 | 02-typeorm-demo/typeorm-demo-vue/node_modules/ 7 | 01-history/project-one/node_modules/ 8 | 01-history/project-one/log 9 | 01-history/project-one/public 10 | 01-history/project-one/.vscode 11 | 03-opinionated-with-docker/node_modules 12 | 13 | /.pnp 14 | .pnp.js 15 | 16 | # Logs 17 | typeorm-demo/typeorm-demo-api/logs/ 18 | 19 | # testing 20 | /coverage 21 | 22 | # production 23 | /build 24 | 25 | # misc 26 | .DS_Store 27 | .env.local 28 | .env.development.local 29 | .env.test.local 30 | .env.production.local 31 | 01-history/project-one/.env 32 | 33 | npm-debug.log* 34 | yarn-debug.log* 35 | yarn-error.log* 36 | 37 | # lock files 38 | typeorm-demo/typeorm-demo-api/yarn.lock 39 | typeorm-demo/typeorm-demo-vue/package-lock.json 40 | history/project-one/yarn.lock 41 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/create/user-create.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { Post, body, controller, response } from "@expressots/adapter-express"; 3 | import { Response } from "express"; 4 | import { CreateUserRequestDTO, CreateUserResponseDTO } from "./user-create.dto"; 5 | import { CreateUserUseCase } from "./user-create.usecase"; 6 | 7 | @controller("/user/create") 8 | export class UserCreateController extends BaseController { 9 | constructor(private createUserUseCase: CreateUserUseCase) { 10 | super(); 11 | } 12 | 13 | @Post("/") 14 | async execute( 15 | @body() payload: CreateUserRequestDTO, 16 | @response() res: Response, 17 | ): Promise { 18 | return this.callUseCase( 19 | await this.createUserUseCase.execute(payload), 20 | res, 21 | StatusCode.Created, 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/user/create/create-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { ICreateUserDTO, ICreateUserResponseDTO } from "./create-user.dto"; 9 | import { CreateUserUseCase } from "./create-user.usecase"; 10 | 11 | @controller("/user/create") 12 | class CreateUserController extends BaseController { 13 | constructor(private createUserUseCase: CreateUserUseCase) { 14 | super("create-user-controller"); 15 | } 16 | 17 | @httpPost("/") 18 | execute( 19 | @requestBody() data: ICreateUserDTO, 20 | @response() res: any, 21 | ): ICreateUserResponseDTO { 22 | return this.callUseCase( 23 | this.createUserUseCase.execute(data), 24 | res, 25 | StatusCode.Created, 26 | ); 27 | } 28 | } 29 | 30 | export { CreateUserController }; 31 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Template Vue JS 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/views/movie/CreateView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/delete/user-delete.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { Response } from "express"; 3 | import { UserDeleteRequestDTO, UserDeleteResponseDTO } from "./user-delete.dto"; 4 | import { UserDeleteUseCase } from "./user-delete.usecase"; 5 | import { 6 | Delete, 7 | controller, 8 | param, 9 | response, 10 | } from "@expressots/adapter-express"; 11 | 12 | @controller("/user/delete") 13 | export class UserDeleteController extends BaseController { 14 | constructor(private userDeleteUseCase: UserDeleteUseCase) { 15 | super(); 16 | } 17 | 18 | @Delete("/:id") 19 | async execute( 20 | @param() payload: UserDeleteRequestDTO, 21 | @response() res: Response, 22 | ): Promise { 23 | return this.callUseCase( 24 | await this.userDeleteUseCase.execute(payload), 25 | res, 26 | StatusCode.OK, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/history/pokebattle.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpGet, 5 | queryParam, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { PokebattleUseCase } from "./pokebattle.usecase"; 9 | import { 10 | IPokebattleHistoryRequestDTO, 11 | IPokebattleHistoryResponseDTO, 12 | } from "./pokebattle.dto"; 13 | 14 | @controller("/pokebattle/history") 15 | class PokebattleController extends BaseController { 16 | constructor(private pokebattleUseCase: PokebattleUseCase) { 17 | super("pokebattle-controller"); 18 | } 19 | 20 | @httpGet("/") 21 | execute( 22 | @response() res: any, 23 | @queryParam() params: IPokebattleHistoryRequestDTO, 24 | ): Promise { 25 | return this.callUseCaseAsync( 26 | this.pokebattleUseCase.execute(params), 27 | res, 28 | StatusCode.OK, 29 | ); 30 | } 31 | } 32 | 33 | export { PokebattleController }; 34 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/update/UpdateUser.Controller.ts: -------------------------------------------------------------------------------- 1 | import { controller, httpPut, requestBody, requestParam, response } from "inversify-express-utils"; 2 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 3 | import { UpdateUserUseCase } from "./UpdateUser.UseCase"; 4 | import { IUpdateUserRequestDTO, IUpdateUserResponseDTO } from "./IUpdateUser.DTO"; 5 | import { BaseController } from "@providers/core/controller/Controller.Provider"; 6 | 7 | @controller("/user") 8 | class UpdateUserController extends BaseController { 9 | constructor(private updateUserUseCase: UpdateUserUseCase) { 10 | super("user-update-controller"); 11 | } 12 | 13 | @httpPut("/update/:id") 14 | async Execute(@requestParam("id") id: string, @requestBody() data: IUpdateUserRequestDTO, @response() res): Promise { 15 | 16 | data.id = id; 17 | 18 | return this.CallUseCase(this.updateUserUseCase.Execute(data), res, StatusCode.OK); 19 | } 20 | } 21 | 22 | export { UpdateUserController }; -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/create/create-user.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { 9 | ICreateUserRequestDTO, 10 | ICreateUserResponseDTO, 11 | } from "./create-user.dto"; 12 | import { CreateUserUseCase } from "./create-user.usecase"; 13 | 14 | @controller("/user/create") 15 | class CreateUserController extends BaseController { 16 | constructor(private createUserUseCase: CreateUserUseCase) { 17 | super("create-user-controller"); 18 | } 19 | 20 | @httpPost("/") 21 | execute( 22 | @requestBody() data: ICreateUserRequestDTO, 23 | @response() res: any, 24 | ): ICreateUserResponseDTO { 25 | return this.callUseCase( 26 | this.createUserUseCase.execute(data), 27 | res, 28 | StatusCode.Created, 29 | ); 30 | } 31 | } 32 | 33 | export { CreateUserController }; 34 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/repositories/base-repository.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { IBaseRepository } from "./base-repository.interface"; 3 | import { IEntity } from "@entities/base.entity"; 4 | 5 | @provide(BaseRepository) 6 | class BaseRepository implements IBaseRepository { 7 | private readonly DB: T[] = []; 8 | 9 | create(item: T): T | null { 10 | this.DB.push(item); 11 | return item; 12 | } 13 | 14 | update(item: T) { 15 | this.DB.push(item); 16 | return item; 17 | } 18 | 19 | delete(id: string): boolean { 20 | const index: number = this.DB.findIndex((item) => item.Id === id); 21 | 22 | if (index != -1) { 23 | this.DB.splice(index, 1); 24 | return true; 25 | } 26 | return false; 27 | } 28 | 29 | find(id: string): T | null { 30 | const user = this.DB.find((item) => item.Id === id); 31 | return user || null; 32 | } 33 | 34 | findAll(): T[] { 35 | return this.DB; 36 | } 37 | } 38 | 39 | export { BaseRepository }; 40 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/providers/application/application.provider.ts: -------------------------------------------------------------------------------- 1 | import { IMiddleware, Middleware, IProvider, Provider } from "@expressots/core"; 2 | import { AppExpress } from "@expressots/adapter-express"; 3 | import { provide } from "inversify-binding-decorators"; 4 | import { container } from "../../app.container"; 5 | 6 | @provide(App) 7 | export class App extends AppExpress { 8 | private middleware: IMiddleware; 9 | private provider: IProvider; 10 | 11 | constructor() { 12 | super(); 13 | this.middleware = container.get(Middleware); 14 | this.provider = container.get(Provider); 15 | } 16 | 17 | protected configureServices(): void { 18 | this.middleware.addBodyParser(); 19 | this.middleware.setErrorHandler(); 20 | } 21 | 22 | protected postServerInitialization(): void { 23 | if (this.isDevelopment()) { 24 | this.provider.envValidator.checkAll(); 25 | } 26 | } 27 | 28 | protected serverShutdown(): void {} 29 | } 30 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/create/create-movie.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { 9 | ICreateMovieRequestDTO, 10 | ICreateMovieResponseDTO, 11 | } from "./create-movie.dto"; 12 | import { CreateMovieUseCase } from "./create-movie.usecase"; 13 | 14 | @controller("/movie/create") 15 | class CreateMovieController extends BaseController { 16 | constructor(private createMovieUseCase: CreateMovieUseCase) { 17 | super("create-movie-controller"); 18 | } 19 | 20 | @httpPost("/") 21 | execute( 22 | @requestBody() payload: ICreateMovieRequestDTO, 23 | @response() res: any, 24 | ): ICreateMovieResponseDTO { 25 | return this.callUseCase( 26 | this.createMovieUseCase.execute(payload), 27 | res, 28 | StatusCode.Created, 29 | ); 30 | } 31 | } 32 | 33 | export { CreateMovieController }; 34 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/findall/user-findall.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { User } from "@entities/user.entity"; 3 | import { UserRepository } from "@repositories/user/user.repository"; 4 | import { FindAllUserResponseDTO } from "./user-findall.dto"; 5 | 6 | @provide(FindAllUserUseCase) 7 | export class FindAllUserUseCase { 8 | constructor(private userRepository: UserRepository) {} 9 | 10 | async execute(): Promise { 11 | try { 12 | const users = await this.userRepository.findAll(); 13 | const response: FindAllUserResponseDTO[] = []; 14 | 15 | users.forEach((user: User) => { 16 | response.push({ 17 | id: user.id, 18 | name: user.name, 19 | email: user.email, 20 | }); 21 | }); 22 | 23 | return response; 24 | } catch (error: any) { 25 | throw error; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/useCases/user/findall/findall-user.usecase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { User } from "@entities/user.entity"; 3 | import { UserRepository } from "@repositories/user/user.repository"; 4 | import { IFindAllUserResponseDTO } from "./findall-user.dto"; 5 | 6 | @provide(FindAllUserUseCase) 7 | class FindAllUserUseCase { 8 | constructor(private userRepository: UserRepository) {} 9 | 10 | execute(): IFindAllUserResponseDTO[] | null { 11 | try { 12 | const users = this.userRepository.findAll(); 13 | const response: IFindAllUserResponseDTO[] = []; 14 | 15 | users.forEach((user: User) => { 16 | response.push({ 17 | id: user.Id, 18 | name: user.name, 19 | email: user.email, 20 | }); 21 | }); 22 | 23 | return response; 24 | } catch (error: any) { 25 | throw error; 26 | } 27 | } 28 | } 29 | 30 | export { FindAllUserUseCase }; 31 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/delete/delete-movie.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpDelete, 5 | requestParam, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { 9 | IDeleteMovieRequestDTO, 10 | IDeleteMovieResponseDTO, 11 | } from "./delete-movie.dto"; 12 | import { DeleteMovieUseCase } from "./delete-movie.usecase"; 13 | 14 | @controller("/movie") 15 | class DeleteMovieController extends BaseController { 16 | constructor(private deleteMovieUseCase: DeleteMovieUseCase) { 17 | super("delete-movie-controller"); 18 | } 19 | 20 | @httpDelete("/:id") 21 | async execute( 22 | @requestParam() id: IDeleteMovieRequestDTO, 23 | @response() res: any, 24 | ): Promise { 25 | return this.callUseCaseAsync( 26 | this.deleteMovieUseCase.execute(id), 27 | res, 28 | StatusCode.OK, 29 | ); 30 | } 31 | } 32 | 33 | export { DeleteMovieController }; 34 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findOne/findone-movie.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpGet, 5 | requestParam, 6 | response, 7 | } from "inversify-express-utils"; 8 | import { 9 | IFindOneMovieRequestDTO, 10 | IFindOneMovieResponseDTO, 11 | } from "./findone-movie.dto"; 12 | import { FindOneMovieUseCase } from "./findone-movie.usecase"; 13 | 14 | @controller("/movie") 15 | class FindOneMovieController extends BaseController { 16 | constructor(private findoneMovieUseCase: FindOneMovieUseCase) { 17 | super("findone-movie-controller"); 18 | } 19 | 20 | @httpGet("/:id") 21 | async execute( 22 | @requestParam() id: IFindOneMovieRequestDTO, 23 | @response() res: any, 24 | ): Promise { 25 | return this.callUseCaseAsync( 26 | this.findoneMovieUseCase.execute(id), 27 | res, 28 | StatusCode.OK, 29 | ); 30 | } 31 | } 32 | 33 | export { FindOneMovieController }; 34 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import { createPinia } from "pinia"; 3 | import { library } from "@fortawesome/fontawesome-svg-core"; 4 | import { fab } from "@fortawesome/free-brands-svg-icons"; 5 | import { fas } from "@fortawesome/free-solid-svg-icons"; 6 | import { far } from "@fortawesome/free-regular-svg-icons"; 7 | import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; 8 | import Notifications from "@kyvg/vue3-notification"; 9 | import { autoAnimatePlugin } from "@formkit/auto-animate/vue"; 10 | 11 | import App from "./App.vue"; 12 | import { router } from "@/router"; 13 | 14 | import "./assets/main.css"; 15 | 16 | import { registerComponents } from "@/components/common"; 17 | import i18n from "@/i18n"; 18 | 19 | library.add(fab, fas, far); 20 | 21 | const app = createApp(App); 22 | 23 | app.use(createPinia()); 24 | app.use(router); 25 | app.use(Notifications); 26 | app.use(autoAnimatePlugin); 27 | app.use(i18n); 28 | 29 | registerComponents(app); 30 | 31 | app.component("font-awesome-icon", FontAwesomeIcon); 32 | 33 | app.mount("#app"); 34 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/create/CreateUser.Controller.ts: -------------------------------------------------------------------------------- 1 | import { CreateUserUseCase } from "./CreateUser.UseCase"; 2 | import { controller, httpPost, interfaces, requestBody, response } from "inversify-express-utils"; 3 | import { ICreateUserDTO, ICreateUserReturnDTO } from "./ICreateUser.DTO"; 4 | import AuthMiddleware from "@providers/middlewares/AuthMiddleware/AuthMiddleware.Provider"; 5 | import { BaseController } from "@providers/core/controller/Controller.Provider"; 6 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 7 | 8 | @controller('/user/create') 9 | class CreateUserController extends BaseController { 10 | 11 | constructor(private createUserUseCase: CreateUserUseCase) { 12 | super("user-create-controller"); 13 | } 14 | 15 | @httpPost('/', AuthMiddleware) 16 | async execute(@requestBody() data: ICreateUserDTO, @response() res): Promise { 17 | console.log("payload: ", data); 18 | return this.CallUseCase(this.createUserUseCase.Execute(data), res, StatusCode.Created); 19 | } 20 | } 21 | 22 | export { CreateUserController }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findAll/findall-movie.usecase.ts: -------------------------------------------------------------------------------- 1 | import { MovieRepository } from "@repositories/movie.repository"; 2 | import { provide } from "inversify-binding-decorators"; 3 | import { IFindAllMovieResponseDTO } from "./findall-movie.dto"; 4 | 5 | @provide(FindAllMovieUseCase) 6 | class FindAllMovieUseCase { 7 | constructor(private movieRepository: MovieRepository) {} 8 | 9 | async execute(): Promise { 10 | try { 11 | const movies = await this.movieRepository.findAll(); 12 | const moviesMapped: IFindAllMovieResponseDTO[] = []; 13 | 14 | movies.forEach((movie) => { 15 | moviesMapped.push({ 16 | id: movie.id, 17 | title: movie.title, 18 | genre: movie.genre, 19 | year: movie.year, 20 | }); 21 | }); 22 | 23 | return moviesMapped; 24 | } catch (error: any) { 25 | throw error; 26 | } 27 | } 28 | } 29 | 30 | export { FindAllMovieUseCase }; 31 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | plugins: ["@typescript-eslint/eslint-plugin"], 4 | extends: [ 5 | "plugin:@typescript-eslint/recommended", 6 | "plugin:prettier/recommended", 7 | ], 8 | root: true, 9 | env: { 10 | node: true, 11 | jest: true, 12 | }, 13 | ignorePatterns: [".eslintrc.js"], 14 | rules: { 15 | "@typescript-eslint/interface-name-prefix": "off", 16 | "@typescript-eslint/explicit-function-return-type": "off", 17 | "@typescript-eslint/explicit-module-boundary-types": "off", 18 | "@typescript-eslint/no-explicit-any": "off", 19 | "@typescript-eslint/no-empty-function": "off", 20 | "@typescript-eslint/no-empty-interface": "off", 21 | "@typescript-eslint/no-unused-vars": "off", 22 | "no-trailing-spaces": ["error", { skipBlankLines: true }], 23 | "no-multi-spaces": ["error", { ignoreEOLComments: true }], 24 | "no-multi-spaces": "off", 25 | "prettier/prettier": "off", 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/findOne/findone-movie.usecase.ts: -------------------------------------------------------------------------------- 1 | import { MovieRepository } from "@repositories/movie.repository"; 2 | import { provide } from "inversify-binding-decorators"; 3 | import { 4 | IFindOneMovieRequestDTO, 5 | IFindOneMovieResponseDTO, 6 | } from "./findone-movie.dto"; 7 | 8 | @provide(FindOneMovieUseCase) 9 | class FindOneMovieUseCase { 10 | constructor(private movieRepository: MovieRepository) {} 11 | 12 | async execute( 13 | payload: IFindOneMovieRequestDTO, 14 | ): Promise { 15 | try { 16 | const movie = await this.movieRepository.find(payload.id); 17 | 18 | if (movie) { 19 | return { 20 | id: movie.id, 21 | title: movie.title, 22 | genre: movie.genre, 23 | year: movie.year, 24 | }; 25 | } 26 | 27 | return null; 28 | } catch (error: any) { 29 | throw error; 30 | } 31 | } 32 | } 33 | 34 | export { FindOneMovieUseCase }; 35 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/stores/movie.ts: -------------------------------------------------------------------------------- 1 | import { MovieService } from "@/services"; 2 | import type { IMovie, IMovieForm } from "@/types"; 3 | import { defineStore } from "pinia"; 4 | 5 | interface IState { 6 | movies: Array; 7 | } 8 | 9 | const useMovieStore = defineStore("movie", { 10 | state: (): IState => ({ 11 | movies: [], 12 | }), 13 | actions: { 14 | async add(movie: IMovieForm) { 15 | await MovieService.createMovie(movie); 16 | }, 17 | async remove(movie_id: number) { 18 | await MovieService.deleteMovie(movie_id); 19 | this.loadMovies(); 20 | }, 21 | update(movie_id: number, payload: IMovieForm) { 22 | const index = this.movies.findIndex((movie) => movie.id === movie_id); 23 | 24 | if (index !== -1) { 25 | this.movies.splice(index, 1, { 26 | ...this.movies[index], 27 | ...payload, 28 | }); 29 | } 30 | }, 31 | async loadMovies() { 32 | const movies = await MovieService.getMovies(); 33 | this.movies = movies.data; 34 | }, 35 | }, 36 | }); 37 | 38 | export { useMovieStore }; 39 | -------------------------------------------------------------------------------- /01-history/project-one/.env.example: -------------------------------------------------------------------------------- 1 | # Server 2 | ENVIRONMENT="Development" # Development, Production, Staging 3 | TIMEZONE="America/New_york" 4 | DEFAULT_LANGUAGE="en" 5 | DEFAULT_PORT=3001 6 | SECURE_PORT=4000 7 | ADMIN_EMAIL="your-email@email.com" 8 | CORS_ORIGIN="*" 9 | 10 | # Database 11 | DB_TYPE="mongodb" 12 | DATABASE="cleancode" 13 | DB_HOST="localhost" 14 | DB_PORT=27017 15 | DB_USERNAME="cleancode" 16 | DB_PASSWORD="cleancode" 17 | DB_EXTRA_ARGS="?authSource=admin" 18 | DB_SEED="false" 19 | 20 | #Logging 21 | LOG_FILE="general" # file name 22 | LOG_FOLDER="Log" # folder name 23 | 24 | # MailTarp 25 | MAILTRAP_INBOX_ALIAS= 26 | MAILTRAP_HOST=smtp.mailtrap.io 27 | MAILTRAP_PORT=2525 28 | MAILTRAP_USERNAME= 29 | MAILTRAP_PASSWORD= 30 | 31 | # Security JWT 32 | SECURITY_JWT_PRIVATE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImVkZDUzNmU4LTliZDctNDNjMS1hODMyLTg4ZWEyNmRhZGMxZCIsImVtYWlsIjoiY2xlYW5AYXJjaGl0ZWN0dXJlLmNvbSIsImlhdCI6MTYzMDYzNzQ5OSwiZXhwIjoxNjMwNzIzODk5fQ.nYzMgzEiNZvpyLP-HF9Iwj2qDnP33LNdYAKDECLtmHE 33 | 34 | # Security Auth0 35 | SECURITY_AUTH0_KEY= 36 | 37 | # Crypto Hash Salt 38 | SALT_FOR_HASH="private salt" -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/update/user-update.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { Response } from "express"; 3 | import { UserUpdateRequestDTO, UserUpdateResponseDTO } from "./user-update.dto"; 4 | import { UserUpdateUseCase } from "./user-update.usecase"; 5 | import { 6 | Patch, 7 | body, 8 | controller, 9 | param, 10 | response, 11 | } from "@expressots/adapter-express"; 12 | 13 | @controller("/user/update") 14 | export class UserUpdateController extends BaseController { 15 | constructor(private userUpdateUseCase: UserUpdateUseCase) { 16 | super(); 17 | } 18 | 19 | @Patch("/:email") 20 | async execute( 21 | @param("email") email: string, 22 | @body() payload: UserUpdateRequestDTO, 23 | @response() res: Response, 24 | ): Promise { 25 | const data = { ...payload, email }; 26 | 27 | return this.callUseCase( 28 | await this.userUpdateUseCase.execute(data), 29 | res, 30 | StatusCode.OK, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import { ROUTE_NAMES } from "@/enums"; 2 | import { getRoutePath } from "@/router"; 3 | // import type { UserType } from "@/types"; 4 | // import { isUserType } from "@/types"; 5 | 6 | const USER_KEY = "user-credentials"; 7 | 8 | interface LogoutProps { 9 | redirect_to?: ROUTE_NAMES | null; 10 | } 11 | 12 | function logout({ redirect_to = null }: LogoutProps = {}) { 13 | localStorage.removeItem(USER_KEY); 14 | 15 | const defaultPath: string = getRoutePath(ROUTE_NAMES.HOME)!; 16 | const redirectPath: string | null = redirect_to && getRoutePath(redirect_to); 17 | 18 | location.replace(redirectPath || defaultPath); 19 | } 20 | 21 | // async function load(): Promise { 22 | // let data: UserType | string | null = localStorage.getItem(USER_KEY); 23 | 24 | // if (typeof data === "string") { 25 | // data = JSON.parse(data); 26 | 27 | // if (isUserType(data)) { 28 | // return data; 29 | // } 30 | // } 31 | 32 | // return undefined; 33 | // } 34 | 35 | export default { 36 | USER_KEY, 37 | 38 | logout, 39 | // load, 40 | }; 41 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "sourceMap": false, 7 | "removeComments": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "resolveJsonModule": true, 11 | "outDir": "./dist", 12 | "rootDir": "./", 13 | "baseUrl": "./src", 14 | "paths": { 15 | "@entities/*": ["entities/*"], 16 | "@providers/*": ["providers/*"], 17 | "@repositories/*": ["repositories/*"], 18 | "@useCases/*": ["useCases/*"] 19 | }, 20 | "esModuleInterop": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "strict": true, 23 | "allowJs": true, 24 | "noImplicitAny": false, 25 | "strictPropertyInitialization": false, 26 | "skipLibCheck": true, 27 | "types": ["reflect-metadata", "node", "jest"] 28 | }, 29 | "include": ["src/**/*.ts"], 30 | "exclude": ["node_modules", "dist", "test"] 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Richard Zampieri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/i18n/messages/en-US/field.ts: -------------------------------------------------------------------------------- 1 | import type { LocaleObject } from "@/types"; 2 | import * as locale from "yup/lib/locale"; 3 | 4 | /** 5 | * Replaces all `${path}` by `{label}` and remove all "$" of "${}" to be compatible with vue-i18n 6 | */ 7 | function parse(locale: LocaleObject): LocaleObject { 8 | const result = Object.entries(locale).map(([key, value]) => { 9 | if (typeof value === "string") { 10 | value = value.replaceAll("${path}", "{label}").replaceAll("${", "{"); 11 | } else if (value && typeof value === "object") { 12 | value = parse(value); 13 | } 14 | 15 | return [key, value]; 16 | }); 17 | 18 | return Object.fromEntries(result); 19 | } 20 | 21 | const fieldMessages: LocaleObject = parse({ 22 | ...locale, 23 | mixed: { 24 | ...locale.mixed, 25 | notType: 26 | "{label} must be a `{type}` type, but the final value was: `{finalValue}`{cast}.{nullable}", 27 | cast: "(cast from the value `{value}`)", 28 | nullable: 29 | 'If "null" is intended as an empty value be sure to mark the schema as `.nullable()`', 30 | }, 31 | }); 32 | 33 | export default fieldMessages; 34 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/ToggleTheme.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 14 | 15 | 16 | 40 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "commonjs", 5 | "lib": ["es2017"], 6 | "declaration": false, 7 | "removeComments": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "resolveJsonModule": true, 11 | "sourceMap": false, 12 | "outDir": "./dist", 13 | "rootDir": "./", 14 | "baseUrl": "./src", 15 | "paths": { 16 | "@entities/*": ["entities/*"], 17 | "@providers/*": ["providers/*"], 18 | "@repositories/*": ["repositories/*"], 19 | "@useCases/*": ["useCases/*"] 20 | }, 21 | "esModuleInterop": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "strict": true, 24 | "allowJs": true, 25 | "noImplicitAny": false, 26 | "strictPropertyInitialization": false, 27 | "skipLibCheck": true, 28 | "types": ["reflect-metadata", "node", "jest"] 29 | }, 30 | "include": [".", "src/**/*.ts"], 31 | "exclude": ["node_modules", "dist", "test"] 32 | } 33 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/delete/delete-movie.usecase.ts: -------------------------------------------------------------------------------- 1 | import { MovieRepository } from "@repositories/movie.repository"; 2 | import { provide } from "inversify-binding-decorators"; 3 | import { 4 | IDeleteMovieRequestDTO, 5 | IDeleteMovieResponseDTO, 6 | } from "./delete-movie.dto"; 7 | 8 | @provide(DeleteMovieUseCase) 9 | class DeleteMovieUseCase { 10 | constructor(private movieRepository: MovieRepository) {} 11 | 12 | async execute( 13 | payload: IDeleteMovieRequestDTO, 14 | ): Promise { 15 | try { 16 | const movie = await this.movieRepository.find(payload.id); 17 | 18 | if (movie) { 19 | await this.movieRepository.delete(payload.id); 20 | } 21 | 22 | if (movie) { 23 | return { 24 | id: payload.id, 25 | status: `Movie id: ${payload.id} deleted successfully`, 26 | }; 27 | } 28 | 29 | return null; 30 | } catch (error: any) { 31 | throw error; 32 | } 33 | } 34 | } 35 | 36 | export { DeleteMovieUseCase }; 37 | -------------------------------------------------------------------------------- /01-history/project-one/src/repositories/IBase.Repository.ts: -------------------------------------------------------------------------------- 1 | import { IBaseEntity } from "@entities/IBase.Entity"; 2 | import mongoose, { Document, FilterQuery, PopulateOptions } from "mongoose"; 3 | 4 | interface IBaseRepository { 5 | Create(item: U, 6 | refEntities: (Document | Document[])[], 7 | embeddedRelations: string[], 8 | refBack: boolean, 9 | ): Promise; 10 | 11 | Update(item: U, 12 | refEntities: (Document | Document[])[], 13 | embeddedRelations: string[], 14 | refBack: boolean, 15 | ): Promise; 16 | 17 | Delete(id: string): Promise; 18 | 19 | DeleteReferences(parent: U, referenceField: string, ids: string[]): Promise; 20 | 21 | FindOne(query: FilterQuery, embeddedRelations: string[] | PopulateOptions | PopulateOptions[]): Promise; 22 | 23 | FindById(id: string, embeddedRelations: string[] | PopulateOptions | PopulateOptions[]): Promise; 24 | 25 | FindAll(query: FilterQuery, embeddedRelations: string[] | PopulateOptions | PopulateOptions[]): Promise; 26 | } 27 | 28 | export { IBaseRepository }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/router/route-list.ts: -------------------------------------------------------------------------------- 1 | import { ROUTE_NAMES } from "@/enums"; 2 | import type { RouteRecordRaw } from "vue-router"; 3 | 4 | export interface RouteList { 5 | name: string; 6 | url: { name: ROUTE_NAMES }; 7 | } 8 | 9 | export function getRoutePath(routeName: ROUTE_NAMES): string | null { 10 | const route = routes.find((route) => route.name === routeName); 11 | 12 | return route?.path || null; 13 | } 14 | 15 | export const routes: Readonly = [ 16 | { 17 | path: "/", 18 | name: ROUTE_NAMES.HOME, 19 | component: () => import("@/views/HomeView.vue"), 20 | }, 21 | { 22 | path: "/movies", 23 | name: ROUTE_NAMES.MOVIE, 24 | component: () => import("@/views/movie/IndexView.vue"), 25 | }, 26 | { 27 | path: "/movie/:id", 28 | name: ROUTE_NAMES.MOVIE_UPDATE, 29 | component: () => import("@/views/movie/UpdateView.vue"), 30 | }, 31 | { 32 | path: "/movie/create", 33 | name: ROUTE_NAMES.MOVIE_CREATE, 34 | component: () => import("@/views/movie/CreateView.vue"), 35 | }, 36 | { 37 | path: "/:pathMatch(.*)*", 38 | name: ROUTE_NAMES.NOT_FOUND, 39 | component: () => import("@/views/404.vue"), 40 | }, 41 | ]; 42 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-ui-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typeorm-demo-ui", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "@types/jest": "^27.5.2", 10 | "@types/node": "^16.18.16", 11 | "@types/react": "^18.0.28", 12 | "@types/react-dom": "^18.0.11", 13 | "axios": "^1.3.4", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "react-scripts": "5.0.1", 17 | "typescript": "^4.9.5", 18 | "web-vitals": "^2.1.4" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/find/user-find.usecase.ts: -------------------------------------------------------------------------------- 1 | import { Report, StatusCode } from "@expressots/core"; 2 | import { UserRepository } from "@repositories/user/user.repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | import { UserFindRequestDTO, UserFindResponseDTO } from "./user-find.dto"; 5 | 6 | @provide(UserFindUseCase) 7 | export class UserFindUseCase { 8 | constructor( 9 | private userRepository: UserRepository, 10 | private report: Report, 11 | ) {} 12 | 13 | async execute( 14 | payload: UserFindRequestDTO, 15 | ): Promise { 16 | const userExists = await this.userRepository.findByEmail(payload.email); 17 | 18 | if (!userExists) { 19 | const error = this.report.error( 20 | "User not found", 21 | StatusCode.NotFound, 22 | "user-find-usecase", 23 | ); 24 | throw error; 25 | } 26 | 27 | return { 28 | id: userExists.id, 29 | name: userExists.name, 30 | email: userExists.email, 31 | message: "user found successfully", 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/useCases/pokebattle/battle/pokebattle-battle.controller.ts: -------------------------------------------------------------------------------- 1 | import { BaseController, StatusCode } from "@expressots/core"; 2 | import { 3 | controller, 4 | httpPost, 5 | requestBody, 6 | requestHeaders, 7 | response, 8 | } from "inversify-express-utils"; 9 | import { PokebattleBattleUseCase } from "./pokebattle-battle.usecase"; 10 | import { 11 | IPokebattleBattleRequestDTO, 12 | IPokebattleBattleResponseDTO, 13 | } from "./pokebattle-battle.dto"; 14 | 15 | import authMiddleware from "@providers/middlewares/auth"; 16 | 17 | @controller("/pokebattle/battle") 18 | class PokebattleBattleController extends BaseController { 19 | constructor(private pokebattleBattleUseCase: PokebattleBattleUseCase) { 20 | super("pokebattle-battle-controller"); 21 | } 22 | 23 | @httpPost("/", authMiddleware) 24 | execute( 25 | @requestBody() data: IPokebattleBattleRequestDTO, 26 | @response() res: any, 27 | @requestHeaders("decoded") req, 28 | ): Promise { 29 | return this.callUseCaseAsync( 30 | this.pokebattleBattleUseCase.execute({ body: data, token: req }), 31 | res, 32 | StatusCode.OK, 33 | ); 34 | } 35 | } 36 | 37 | export { PokebattleBattleController }; 38 | -------------------------------------------------------------------------------- /01-history/project-one/src/entities/User.ts: -------------------------------------------------------------------------------- 1 | 2 | import { IBaseEntity } from "./IBase.Entity"; 3 | import { Document, Schema, model } from "mongoose"; 4 | 5 | /* Represents the model of a user and its property types */ 6 | interface IUser extends IBaseEntity { 7 | name: string; 8 | email: string; 9 | password: string; 10 | } 11 | 12 | type UserDocument = Document & IUser; 13 | 14 | const userSchema = new Schema( 15 | { 16 | name: { 17 | type: String, 18 | required: [true, "Name is required"], 19 | }, 20 | email: { 21 | type: String, 22 | required: [true, "Email is required"], 23 | unique: true, 24 | lowercase: true, 25 | match: [/\S+@\S+\.\S+/, "Email is invalid"], 26 | }, 27 | password: { 28 | type: String, 29 | required: [true, "Password is required"], 30 | minlength: [6, "Password must be at least 6 characters"], 31 | }, 32 | }, 33 | { 34 | timestamps: true, 35 | versionKey: false, 36 | } 37 | ); 38 | 39 | // The actual model in which we instantiate the user 40 | const User = model("User", userSchema); 41 | 42 | export { User, IUser, UserDocument }; -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/delete/user-delete.usecase.ts: -------------------------------------------------------------------------------- 1 | import { Report, StatusCode } from "@expressots/core"; 2 | import { UserRepository } from "@repositories/user/user.repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | import { UserDeleteRequestDTO, UserDeleteResponseDTO } from "./user-delete.dto"; 5 | 6 | @provide(UserDeleteUseCase) 7 | export class UserDeleteUseCase { 8 | constructor( 9 | private userRepository: UserRepository, 10 | private report: Report, 11 | ) {} 12 | 13 | async execute( 14 | payload: UserDeleteRequestDTO, 15 | ): Promise { 16 | const userExists = await this.userRepository.find(payload.id); 17 | 18 | if (userExists) { 19 | this.userRepository.delete(userExists?.id); 20 | return { 21 | name: userExists.name, 22 | email: userExists.email, 23 | message: "user deleted successfully", 24 | }; 25 | } 26 | 27 | const error = this.report.error( 28 | "User not found", 29 | StatusCode.NotFound, 30 | "user-delete-usecase", 31 | ); 32 | 33 | throw error; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/core/containerModule/BaseModule.Provider.ts: -------------------------------------------------------------------------------- 1 | import { ContainerModule } from "inversify"; 2 | import { provide } from "inversify-binding-decorators"; 3 | 4 | type ControllerType = Map any>; 5 | 6 | @provide(BaseModuleProvider) 7 | class BaseModuleProvider { 8 | 9 | constructor() { 10 | } 11 | 12 | private static CreateSymbols(controllers: any[]): ControllerType { 13 | 14 | const symbols = new Map any>(); 15 | 16 | for (const controller of controllers) { 17 | const target = controller; 18 | const symbol = Symbol.for(target.name); 19 | symbols.set(symbol, target); 20 | } 21 | 22 | return symbols; 23 | } 24 | 25 | static CreateContainerModule(controllers: any[]): ContainerModule { 26 | 27 | const symbols = BaseModuleProvider.CreateSymbols(controllers); 28 | 29 | return new ContainerModule(bind => { 30 | for (const symbol of symbols) { 31 | const target = symbol.valueOf(); 32 | 33 | bind(target[0]).to(target[1]); 34 | } 35 | }); 36 | } 37 | } 38 | 39 | const CreateModule = BaseModuleProvider.CreateContainerModule; 40 | 41 | export { CreateModule }; -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/providers/database/orm/prisma/prisma-client.provider.ts: -------------------------------------------------------------------------------- 1 | import { Battle } from "@entities/battle.entity"; 2 | import { User } from "@entities/user.entity"; 3 | import { PrismaClient } from "@prisma/client"; 4 | import { IBattleDTO } from "@repositories/battle/battle.dto"; 5 | import { IUserDTO } from "@repositories/user/user.dto"; 6 | import { provide } from "inversify-binding-decorators"; 7 | 8 | type PrismaType = User | Battle; 9 | type DTOType = IUserDTO | IBattleDTO | Battle; 10 | export const prismaClient: PrismaClient = new PrismaClient(); 11 | 12 | @provide(PrismaClientProvider) 13 | class PrismaClientProvider { 14 | public mapToPrisma(dto: DTOType): PrismaType { 15 | const mappedObject = {} as PrismaType; 16 | 17 | for (const [key, value] of Object.entries(dto as any)) { 18 | if (key === "_id") { 19 | mappedObject["id"] = value as PrismaType[keyof PrismaType]; 20 | } else if (key === "_password") { 21 | mappedObject["password"] = value as PrismaType[keyof PrismaType]; 22 | } else { 23 | mappedObject[key as keyof PrismaType] = 24 | value as PrismaType[keyof PrismaType]; 25 | } 26 | } 27 | 28 | return mappedObject; 29 | } 30 | } 31 | 32 | export { PrismaClientProvider }; 33 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findById/FindById.UseCase.ts: -------------------------------------------------------------------------------- 1 | import { UserRepository } from "@repositories/user/User.Repository"; 2 | import { provide } from "inversify-binding-decorators"; 3 | import { IFindByIdDTO } from "./IFindById.DTO"; 4 | import { AppError } from "@providers/core/error/ApplicationError"; 5 | import { UserDocument } from "@entities/User"; 6 | import { Report } from "@providers/core/error/ReportError.Provider"; 7 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 8 | 9 | @provide(FindByIdUseCase) 10 | class FindByIdUseCase { 11 | constructor(private userRepository: UserRepository) { } 12 | 13 | async Execute(id: string): Promise { 14 | 15 | const user: UserDocument | null = await this.userRepository.FindById(id); 16 | 17 | if (!user) { 18 | const error: AppError = Report.Error(new AppError(StatusCode.BadRequest, 19 | "User not found!"), 20 | "user-find-by-id"); 21 | return error; 22 | } 23 | 24 | const dataReturn: IFindByIdDTO = { 25 | id: user._id, 26 | name: user.name, 27 | email: user.email 28 | }; 29 | 30 | return Promise.resolve(dataReturn); 31 | } 32 | } 33 | 34 | export { FindByIdUseCase }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2017", 5 | "declaration": true, 6 | "removeComments": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "resolveJsonModule": true, 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "rootDir": "./", 13 | "baseUrl": "./src", 14 | "paths": { 15 | "@entities/*": ["entities/*"], 16 | "@providers/*": ["providers/*"], 17 | "@repositories/*": ["repositories/*"], 18 | "@useCases/*": ["useCases/*"], 19 | }, 20 | "esModuleInterop": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "strict": true, 23 | "noImplicitAny": false, 24 | "skipLibCheck": true, 25 | "types": ["reflect-metadata","node", "jest"] 26 | }, 27 | "include": [ 28 | ".", 29 | "src/**/*.ts", 30 | ".eslintrc.js", 31 | ], 32 | "exclude": [ 33 | "node_modules", 34 | "dist" 35 | ] 36 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/views/movie/UpdateView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 29 | 30 | 48 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/core/error/ApplicationError.ts: -------------------------------------------------------------------------------- 1 | import { StatusCode } from "./ErrorTypes"; 2 | 3 | class ApplicationError extends Error { 4 | private errorType: number = StatusCode.Unknown; 5 | 6 | constructor(errorType: number, errorMessage?: string) { 7 | super(errorMessage); 8 | 9 | if (errorMessage === undefined) { 10 | this.ParseErrorType(errorType); 11 | } else { 12 | this.errorType = errorType; 13 | this.message = errorMessage; 14 | } 15 | } 16 | 17 | public get Message(): string { 18 | return this.message; 19 | } 20 | 21 | public get ErrorType(): number { 22 | return this.errorType; 23 | } 24 | 25 | private ParseErrorType(errorType: number): void { 26 | 27 | const errorTypesListIds = Object.keys(StatusCode).filter(key => !isNaN(Number(key))); 28 | const errorTypesListNames = Object.keys(StatusCode).filter(key => isNaN(Number(key))); 29 | 30 | for (let i: number = 0; i < errorTypesListIds.length; i++) { 31 | if (Number(errorTypesListIds[i]) === errorType) { 32 | this.errorType = errorType; 33 | this.message = errorTypesListNames[i].split(/(?=[A-Z])/).join(" "); 34 | } 35 | } 36 | } 37 | } 38 | 39 | export { ApplicationError as AppError }; -------------------------------------------------------------------------------- /03-opinionated-with-docker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "commonjs", 5 | "lib": ["es2017", "dom"], 6 | "declaration": false, 7 | "removeComments": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "resolveJsonModule": true, 11 | "sourceMap": false, 12 | "outDir": "./dist", 13 | "rootDir": "./", 14 | "baseUrl": "./src", 15 | "paths": { 16 | "@entities/*": ["entities/*"], 17 | "@providers/*": ["providers/*"], 18 | "@repositories/*": ["repositories/*"], 19 | "@useCases/*": ["useCases/*"] 20 | }, 21 | "esModuleInterop": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "strict": true, 24 | "allowJs": true, 25 | "noImplicitAny": false, 26 | "skipLibCheck": true, 27 | "types": ["reflect-metadata","node", "jest"] 28 | }, 29 | "include": [ 30 | ".", 31 | "src/**/*.ts" 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "dist", 36 | "test" 37 | ] 38 | } -------------------------------------------------------------------------------- /03-opinionated-with-docker/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "sourceMap": false, 7 | "removeComments": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "resolveJsonModule": true, 11 | "outDir": "./dist", 12 | "rootDir": "./", 13 | "baseUrl": "./src", 14 | "paths": { 15 | "@entities/*": ["entities/*"], 16 | "@providers/*": ["providers/*"], 17 | "@repositories/*": ["repositories/*"], 18 | "@useCases/*": ["useCases/*"] 19 | }, 20 | "esModuleInterop": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "strict": true, 23 | "allowJs": true, 24 | "noImplicitAny": false, 25 | "skipLibCheck": true, 26 | "types": ["reflect-metadata","node", "jest"] 27 | }, 28 | "include": [ 29 | "src/**/*.ts" 30 | ], 31 | "exclude": [ 32 | "node_modules", 33 | "dist", 34 | "test" 35 | ] 36 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/index.ts: -------------------------------------------------------------------------------- 1 | import XButton from "./XButton.vue"; 2 | import XInput from "./XInput.vue"; 3 | import XSelect from "./XSelect.vue"; 4 | import XAlert from "./XAlert.vue"; 5 | import XPage from "./XPage.vue"; 6 | import XPagination from "./XPagination.vue"; 7 | import XDialog from "./x-dialog/index.vue"; 8 | import XTable from "./XTable.vue"; 9 | import XSwitch from "./XSwitch.vue"; 10 | import XTooltip from "./XTooltip.vue"; 11 | import XTextarea from "./XTextarea.vue"; 12 | import XBadge from "./XBadge.vue"; 13 | 14 | import type { App } from "vue"; 15 | 16 | function registerComponents(app: App) { 17 | app.component("x-button", XButton); 18 | app.component("x-input", XInput); 19 | app.component("x-textarea", XTextarea); 20 | app.component("x-select", XSelect); 21 | app.component("x-alert", XAlert); 22 | app.component("x-page", XPage); 23 | app.component("x-pagination", XPagination); 24 | app.component("x-dialog", XDialog); 25 | app.component("x-table", XTable); 26 | app.component("x-switch", XSwitch); 27 | app.component("x-tooltip", XTooltip); 28 | app.component("x-badge", XBadge); 29 | } 30 | 31 | export { 32 | XButton, 33 | XInput, 34 | XTextarea, 35 | XSelect, 36 | XAlert, 37 | XPage, 38 | XPagination, 39 | XDialog, 40 | XTable, 41 | XSwitch, 42 | XTooltip, 43 | XBadge, 44 | registerComponents, 45 | }; 46 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/src/repositories/base-repository.ts: -------------------------------------------------------------------------------- 1 | import { inject } from "inversify"; 2 | import { provide } from "inversify-binding-decorators"; 3 | import { IBaseRepository } from "./base-repository.interface"; 4 | import { IEntity } from "@entities/base.entity"; 5 | import { InMemoryDB } from "@providers/db-in-memory/db-in-memory.provider"; 6 | 7 | @provide(BaseRepository) 8 | class BaseRepository implements IBaseRepository { 9 | @inject(InMemoryDB) private inMemoryDB!: InMemoryDB; 10 | 11 | private get USERDB(): T[] { 12 | return this.inMemoryDB.getUserDB() as T[]; 13 | } 14 | 15 | create(item: T): T | null { 16 | this.USERDB.push(item); 17 | return item; 18 | } 19 | 20 | update(item: T) { 21 | this.USERDB.push(item); 22 | return item; 23 | } 24 | 25 | delete(id: string): boolean { 26 | const index: number = this.USERDB.findIndex((item) => item.Id === id); 27 | 28 | if (index != -1) { 29 | this.USERDB.splice(index, 1); 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | find(id: string): T | null { 36 | const user = this.USERDB.find((item) => item.Id === id); 37 | return user || null; 38 | } 39 | 40 | findAll(): T[] { 41 | return this.USERDB; 42 | } 43 | } 44 | 45 | export { BaseRepository }; 46 | -------------------------------------------------------------------------------- /05-postgres-connection-pool-repository/src/useCases/user/update/user-update.usecase.ts: -------------------------------------------------------------------------------- 1 | import { User } from "@entities/user.entity"; 2 | import { Report, StatusCode } from "@expressots/core"; 3 | import { UserRepository } from "@repositories/user/user.repository"; 4 | import { provide } from "inversify-binding-decorators"; 5 | import { UserUpdateRequestDTO, UserUpdateResponseDTO } from "./user-update.dto"; 6 | 7 | @provide(UserUpdateUseCase) 8 | export class UserUpdateUseCase { 9 | constructor( 10 | private userRepository: UserRepository, 11 | private report: Report, 12 | ) {} 13 | 14 | async execute( 15 | payload: UserUpdateRequestDTO, 16 | ): Promise { 17 | const userExists: User | null = await this.userRepository.findByEmail( 18 | payload.email, 19 | ); 20 | 21 | if (!userExists) { 22 | const error = this.report.error( 23 | "User not found", 24 | StatusCode.NotFound, 25 | "user-update-usecase", 26 | ); 27 | 28 | throw error; 29 | } 30 | 31 | userExists.name = payload.name || userExists.name; 32 | 33 | return { 34 | id: userExists.id, 35 | name: userExists.name, 36 | email: userExists.email, 37 | message: "user updated successfully", 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /01-history/project-one/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs", 5 | "lib": ["ES6", "DOM"], 6 | "allowJs": true, 7 | "outDir": "./dist", 8 | "strict": true, 9 | "noImplicitAny": false, 10 | "strictFunctionTypes": false, 11 | "strictBindCallApply": false, 12 | "strictPropertyInitialization": false, 13 | "resolveJsonModule": true, 14 | "moduleResolution": "node", 15 | "esModuleInterop": true, 16 | "skipLibCheck": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "baseUrl": "./src", 19 | "paths": { 20 | "@entities/*": ["entities/*"], 21 | "@providers/*": ["providers/*"], 22 | "@repositories/*": ["repositories/*"], 23 | "@useCases/*": ["useCases/*"], 24 | }, 25 | "types": ["reflect-metadata", "node", "jest"], 26 | "experimentalDecorators": true, 27 | "emitDecoratorMetadata": true, 28 | }, 29 | "include": [".", "src/**/*.ts"], 30 | "exclude": ["node_modules", "dist"], 31 | "typedocOptions": { 32 | "entryPoints": ["src/"], 33 | "name": "Expresso TS Documentation", 34 | "entryPointStrategy": "expand", 35 | "readme": "README.md", 36 | "out": "public/docs" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /01-history/project-one/src/providers/core/controller/Controller.Provider.ts: -------------------------------------------------------------------------------- 1 | import { AppError } from "@providers/core/error/ApplicationError"; 2 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 3 | import Log, { LogLevel } from "@providers/core/logger/exception/ExceptionLogger.Provider"; 4 | import { provide } from "inversify-binding-decorators"; 5 | import { interfaces } from "inversify-express-utils"; 6 | 7 | @provide(BaseController) 8 | class BaseController implements interfaces.Controller { 9 | private serviceName: string; 10 | 11 | constructor(serviceName: string) { 12 | this.serviceName = serviceName; 13 | } 14 | 15 | protected async CallUseCase(useCase: Promise, res: any, successStatusCode: number) { 16 | let dataReturn: any; 17 | 18 | try { 19 | dataReturn = await useCase; 20 | 21 | if (dataReturn instanceof AppError) { 22 | return res.status(dataReturn.ErrorType).json({ error: dataReturn.ErrorType, message: dataReturn.Message }); 23 | } 24 | 25 | return res.status(successStatusCode).json(dataReturn); 26 | } catch (error: any) { 27 | Log(LogLevel.Error, error, this.serviceName); 28 | return res.status(StatusCode.GeneralAppError).json({ 29 | error: StatusCode.GeneralAppError, message: error.message 30 | }); 31 | } 32 | } 33 | } 34 | 35 | export { BaseController }; -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/src/useCases/movie/create/create-movie.usecase.ts: -------------------------------------------------------------------------------- 1 | import { Movie } from "@entities/movie.entity"; 2 | import { MovieRepository } from "@repositories/movie.repository"; 3 | import { provide } from "inversify-binding-decorators"; 4 | import { 5 | ICreateMovieRequestDTO, 6 | ICreateMovieResponseDTO, 7 | } from "./create-movie.dto"; 8 | 9 | @provide(CreateMovieUseCase) 10 | class CreateMovieUseCase { 11 | constructor(private movieRepository: MovieRepository) {} 12 | 13 | execute(payload: ICreateMovieRequestDTO): ICreateMovieResponseDTO | null { 14 | try { 15 | const { title, year, genre } = payload; 16 | 17 | const movie: Movie = new Movie(title, year, genre); 18 | 19 | const isMovieExist = this.movieRepository.create(movie); 20 | 21 | let response: ICreateMovieResponseDTO; 22 | 23 | if (isMovieExist) { 24 | response = { 25 | id: isMovieExist.id, 26 | title: isMovieExist.title, 27 | year: isMovieExist.year, 28 | genre: isMovieExist.genre, 29 | status: "Movie created successfully", 30 | }; 31 | 32 | return response; 33 | } 34 | 35 | return null; 36 | } catch (error: any) { 37 | throw error; 38 | } 39 | } 40 | } 41 | 42 | export { CreateMovieUseCase }; 43 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/src/components/Input.tsx: -------------------------------------------------------------------------------- 1 | import classNames from "classnames"; 2 | import { ChangeEvent } from "react"; 3 | 4 | interface TextInputProps { 5 | id: string; 6 | name: string; 7 | error?: string; 8 | label: string; 9 | touched: boolean | undefined; 10 | value: string; 11 | onBlur: (input: ChangeEvent) => any; 12 | onChange: (input: ChangeEvent) => any; 13 | } 14 | 15 | const Input: React.FC = (props) => { 16 | const classes = classNames( 17 | "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline", 18 | { 19 | "border border-red-600": props.error && props.touched, 20 | } 21 | ); 22 | return ( 23 | <> 24 | 25 | 26 | {props.label} 27 | 28 | 37 | {props.error && props.touched && ( 38 | 39 | {props.error} 40 | 41 | )} 42 | 43 | > 44 | ); 45 | }; 46 | 47 | export default Input; 48 | -------------------------------------------------------------------------------- /01-history/project-one/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "license": "MIT", 5 | "private": true, 6 | "dependencies": { 7 | "@craco/craco": "^6.2.0", 8 | "@testing-library/jest-dom": "^5.11.4", 9 | "@testing-library/react": "^11.1.0", 10 | "@testing-library/user-event": "^12.1.10", 11 | "@types/jest": "^26.0.15", 12 | "@types/node": "^12.0.0", 13 | "@types/react": "^17.0.0", 14 | "@types/react-dom": "^17.0.0", 15 | "axios": "^0.21.1", 16 | "classnames": "^2.3.1", 17 | "formik": "^2.2.9", 18 | "react": "^17.0.2", 19 | "react-dom": "^17.0.2", 20 | "react-scripts": "4.0.3", 21 | "typescript": "^4.1.2", 22 | "web-vitals": "^1.0.1", 23 | "yup": "^0.32.9" 24 | }, 25 | "scripts": { 26 | "start": "craco start", 27 | "build": "craco build", 28 | "test": "craco test" 29 | }, 30 | "eslintConfig": { 31 | "extends": [ 32 | "react-app", 33 | "react-app/jest" 34 | ] 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.2%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | }, 48 | "devDependencies": { 49 | "@types/yup": "^0.29.13", 50 | "autoprefixer": "^9", 51 | "postcss": "^7", 52 | "tailwindcss": "npm:@tailwindcss/postcss7-compat" 53 | } 54 | } -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typeorm-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "build": "tsc", 10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 11 | "lint": "eslint \"src/**/*.ts\" --fix", 12 | "start": "tsnd -r tsconfig-paths/register -r dotenv/config ./src/main.ts", 13 | "start:prod": "node ./dist/main.js", 14 | "test": "jest", 15 | "test:watch": "jest --watch", 16 | "test:cov": "jest --coverage" 17 | }, 18 | "keywords": [], 19 | "devDependencies": { 20 | "@types/express": "^4.17.17", 21 | "@types/jest": "^29.4.0", 22 | "@types/node": "^18.13.0", 23 | "@typescript-eslint/eslint-plugin": "^5.52.0", 24 | "@typescript-eslint/parser": "^5.52.0", 25 | "eslint": "^8.34.0", 26 | "eslint-config-prettier": "^8.6.0", 27 | "eslint-plugin-prettier": "^4.2.1", 28 | "jest": "^29.5.0", 29 | "prettier": "^2.8.4", 30 | "ts-jest": "^29.0.5", 31 | "ts-node-dev": "^2.0.0", 32 | "typescript": "^4.9.5" 33 | }, 34 | "dependencies": { 35 | "@expressots/core": "^1.0.1", 36 | "cors": "^2.8.5", 37 | "dotenv": "^16.0.3", 38 | "inversify": "6.0.1", 39 | "inversify-binding-decorators": "^4.0.0", 40 | "inversify-express-utils": "^6.3.2", 41 | "pg": "^8.10.0", 42 | "reflect-metadata": "^0.1.13", 43 | "tsconfig-paths": "^4.2.0", 44 | "typeorm": "^0.3.12", 45 | "uuid": "^9.0.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /02-typeorm-demo/typeorm-demo-vue/src/components/common/x-dialog/XDialogTitle.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | 16 | 20 | 21 | 25 | 29 | 30 | 31 | 35 | {{ title }} 36 | 37 | 38 | 39 | 40 | 46 | -------------------------------------------------------------------------------- /01-history/project-one/src/useCases/user/findAll/FindAllUsers.UseCase.ts: -------------------------------------------------------------------------------- 1 | import { provide } from "inversify-binding-decorators"; 2 | import { IFindAllUsersResponseDTO } from "./FindAllUsers.DTO"; 3 | import { AppError } from "@providers/core/error/ApplicationError"; 4 | import { UserRepository } from "@repositories/user/User.Repository"; 5 | import { UserDocument } from "@entities/User"; 6 | import { Report } from "@providers/core/error/ReportError.Provider"; 7 | import { StatusCode } from "@providers/core/error/ErrorTypes"; 8 | 9 | 10 | @provide(FindAllUsersUseCase) 11 | class FindAllUsersUseCase { 12 | 13 | constructor(private usersRepository: UserRepository) { } 14 | 15 | async Execute(): Promise { 16 | 17 | const users: UserDocument[] = await this.usersRepository.FindAll(); 18 | 19 | if (users.length === 0) { 20 | const error: AppError = Report.Error(new AppError(StatusCode.BadRequest, 21 | "There is no users!"), 22 | "user-find-all"); 23 | return error; 24 | } 25 | 26 | const dataReturn: IFindAllUsersResponseDTO[] = users.map((user: UserDocument) => { 27 | return { 28 | id: user._id, 29 | name: user.name, 30 | email: user.email, 31 | createdAt: user.createdAt, 32 | updatedAt: user.updatedAt 33 | }; 34 | }); 35 | 36 | return Promise.resolve(dataReturn); 37 | } 38 | } 39 | 40 | export { FindAllUsersUseCase }; -------------------------------------------------------------------------------- /04-poke-battle-with-prisma/src/entities/battle.entity.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from "crypto"; 2 | import { provide } from "inversify-binding-decorators"; 3 | 4 | @provide(Battle) 5 | class Battle { 6 | private _id: string; 7 | private _playerId: string; 8 | public log: { 9 | turn: number; 10 | attacker: string; 11 | defender: string; 12 | attack: string; 13 | attackType: string; 14 | damage: number; 15 | }[]; 16 | public userName: string; 17 | public winner: boolean; 18 | public pokemon1: string; 19 | public pokemon2: string; 20 | public winnerName: string; 21 | public loserName: string; 22 | public isDraw: boolean; 23 | 24 | constructor( 25 | log: { 26 | turn: number; 27 | attacker: string; 28 | defender: string; 29 | attack: string; 30 | attackType: string; 31 | damage: number; 32 | }[], 33 | userName: string, 34 | playerId: string, 35 | winner: boolean, 36 | pokemon1: string, 37 | pokemon2: string, 38 | id: string, 39 | winnerName: string, 40 | loserName: string, 41 | isDraw: boolean, 42 | ) { 43 | this._id = id ?? randomUUID(); 44 | this.userName = userName; 45 | this._playerId = playerId; 46 | this.winner = winner; 47 | this.pokemon1 = pokemon1; 48 | this.pokemon2 = pokemon2; 49 | this.winnerName = winnerName; 50 | this.loserName = loserName; 51 | this.isDraw = isDraw; 52 | this.log = log; 53 | } 54 | 55 | get id(): string { 56 | return this._id; 57 | } 58 | 59 | get playerId(): string { 60 | return this._playerId; 61 | } 62 | } 63 | 64 | export { Battle }; 65 | -------------------------------------------------------------------------------- /03-opinionated-with-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine AS base 2 | 3 | # Install dependencies only when needed 4 | FROM base AS deps 5 | # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. 6 | RUN apk add --no-cache libc6-compat 7 | WORKDIR /app 8 | 9 | # Install dependencies based on the preferred package manager 10 | COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ 11 | RUN \ 12 | if [ -f yarn.lock ]; then yarn --frozen-lockfile --production; \ 13 | elif [ -f package-lock.json ]; then npm ci --production; \ 14 | elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile --production; \ 15 | else echo "Lockfile not found." && exit 1; \ 16 | fi 17 | 18 | # Rebuild the source code only when needed 19 | FROM base AS builder 20 | 21 | WORKDIR /app 22 | 23 | COPY --from=deps /app/node_modules ./node_modules 24 | COPY . . 25 | 26 | RUN mkdir logs 27 | RUN npm run build 28 | 29 | # Production image, copy all the files and run expressots 30 | FROM base AS runner 31 | 32 | WORKDIR /app 33 | 34 | RUN addgroup --system --gid 1001 nodejs 35 | RUN adduser --system --uid 1001 expressots 36 | 37 | COPY --from=deps --chown=expressots:nodejs /app/node_modules ./node_modules 38 | COPY --from=builder --chown=expressots:nodejs /app/logs ./logs 39 | COPY --from=builder --chown=expressots:nodejs /app/dist ./dist 40 | COPY --from=builder --chown=expressots:nodejs app/entrypoint.sh app/register-path.js app/.env app/tsconfig.json app/package.json ./ 41 | 42 | USER expressots 43 | 44 | EXPOSE 3000 45 | 46 | ENTRYPOINT ["sh", "entrypoint.sh"] --------------------------------------------------------------------------------