├── README.md
├── auth-example
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── auth
│ │ ├── auth.controller.ts
│ │ ├── auth.module.ts
│ │ ├── auth.service.ts
│ │ ├── local-auth.guard.ts
│ │ └── local.strategy.ts
│ ├── main.ts
│ └── types
│ │ └── User.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
├── clase01-intro
├── node-hello-world
│ ├── .readme
│ ├── index.js
│ └── package.json
└── node-ts-hello-world
│ ├── .readme
│ ├── index.ts
│ ├── package-lock.json
│ └── package.json
├── clase02-repaso-js
├── algoritmia-resuelto.js
├── algoritmia.js
├── demo-typescript.ts
├── ecma.js
├── primitivos.js
├── prototipos-clases.js
├── prototipos.js
└── strict-mode.js
└── clase09-nestapi
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
├── Examples
│ ├── express
│ │ ├── mvc.ts
│ │ └── no-mvc.ts
│ ├── patrones
│ │ ├── factory.ts
│ │ ├── observable.ts
│ │ ├── singleton.ts
│ │ ├── srtrategy.ts
│ │ └── strategy.ts
│ ├── poo
│ │ ├── abtraction.ts
│ │ ├── encapsulation.ts
│ │ ├── inheritance.ts
│ │ └── polymorphism.ts
│ └── solid
│ │ └── isp.ts
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
├── pokemon.controller.ts
├── pokemon.module.ts
└── pokemon.service.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
/README.md:
--------------------------------------------------------------------------------
1 | [](https://i.ibb.co/pxkk9Fk/portada.png)
2 |
3 | ### ¡Bienvenido al repositorio de Ejemplos de Código para JavaScript en el Backend del Bootcamp! 🐊
4 |
5 | Aquí encontrarás una colección de valiosos fragmentos de código, vistos en clase, y ejemplos prácticos diseñados para mejorar tus habilidades en JavaScript en el ámbito del desarrollo backend. Ya sea que estés empezando y necesites comprender los conceptos fundamentales o si eres un desarrollador experimentado deseando explorar técnicas avanzadas, esta colección es tu recurso central para perfeccionar tus habilidades de desarrollo backend en JavaScript/TypeScript.
6 |
7 | - ##### Clase 1: "Bienvenidos al bootcamp".
8 | - ##### Clase 1: "Repaso de JavaScript".
9 |
--------------------------------------------------------------------------------
/auth-example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir: __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/auth-example/.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
--------------------------------------------------------------------------------
/auth-example/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/auth-example/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/auth-example/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "deleteOutDir": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auth-example",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "build": "nest build",
10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11 | "start": "nest start",
12 | "start:dev": "nest start --watch",
13 | "start:debug": "nest start --debug --watch",
14 | "start:prod": "node dist/main",
15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --config ./test/jest-e2e.json"
21 | },
22 | "dependencies": {
23 | "@nestjs/common": "^10.0.0",
24 | "@nestjs/core": "^10.0.0",
25 | "@nestjs/platform-express": "^10.0.0",
26 | "reflect-metadata": "^0.1.13",
27 | "rxjs": "^7.8.1"
28 | },
29 | "devDependencies": {
30 | "@nestjs/cli": "^10.0.0",
31 | "@nestjs/schematics": "^10.0.0",
32 | "@nestjs/testing": "^10.0.0",
33 | "@types/express": "^4.17.17",
34 | "@types/jest": "^29.5.2",
35 | "@types/node": "^20.3.1",
36 | "@types/supertest": "^2.0.12",
37 | "@typescript-eslint/eslint-plugin": "^6.0.0",
38 | "@typescript-eslint/parser": "^6.0.0",
39 | "eslint": "^8.42.0",
40 | "eslint-config-prettier": "^9.0.0",
41 | "eslint-plugin-prettier": "^5.0.0",
42 | "jest": "^29.5.0",
43 | "prettier": "^3.0.0",
44 | "source-map-support": "^0.5.21",
45 | "supertest": "^6.3.3",
46 | "ts-jest": "^29.1.0",
47 | "ts-loader": "^9.4.3",
48 | "ts-node": "^10.9.1",
49 | "tsconfig-paths": "^4.2.0",
50 | "typescript": "^5.1.3"
51 | },
52 | "jest": {
53 | "moduleFileExtensions": [
54 | "js",
55 | "json",
56 | "ts"
57 | ],
58 | "rootDir": "src",
59 | "testRegex": ".*\\.spec\\.ts$",
60 | "transform": {
61 | "^.+\\.(t|j)s$": "ts-jest"
62 | },
63 | "collectCoverageFrom": [
64 | "**/*.(t|j)s"
65 | ],
66 | "coverageDirectory": "../coverage",
67 | "testEnvironment": "node"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/auth-example/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/auth-example/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/auth-example/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { AuthModule } from './auth/auth.module';
5 | import { AuthController } from './auth/auth.controller';
6 |
7 | @Module({
8 | imports: [AuthModule],
9 | controllers: [AppController, AuthController],
10 | providers: [AppService],
11 | })
12 | export class AppModule {}
13 |
--------------------------------------------------------------------------------
/auth-example/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/auth-example/src/auth/auth.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Request, Post, UseGuards } from '@nestjs/common';
2 | import { LocalAuthGuard } from './local-auth.guard';
3 |
4 | @Controller('auth')
5 | export class AuthController {
6 | constructor() {}
7 |
8 | @UseGuards(LocalAuthGuard)
9 | @Post('login')
10 | login(@Request() req) {
11 | console.log('Controller');
12 | return req.user;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/auth-example/src/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AuthService } from './auth.service';
3 | import { LocalStrategy } from './local.strategy';
4 | import { PassportModule } from '@nestjs/passport';
5 |
6 | @Module({
7 | imports: [PassportModule],
8 | providers: [AuthService, LocalStrategy],
9 | exports: [AuthService],
10 | })
11 | export class AuthModule {}
12 |
--------------------------------------------------------------------------------
/auth-example/src/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { User } from '../types/User';
3 |
4 | @Injectable()
5 | export class AuthService {
6 | testUser: User;
7 |
8 | constructor() {
9 | this.testUser = {
10 | id: 10,
11 | name: 'juani',
12 | password: 'test',
13 | };
14 | }
15 |
16 | //ACA TRAEMOS AL USUARIO DE MONGO
17 | validateUser(username: string, password: string): any {
18 | console.log('AuthService validateUser()');
19 | if (
20 | this.testUser.name.toLowerCase() == username.toLowerCase() &&
21 | this.testUser.password == password
22 | ) {
23 | return {
24 | userId: this.testUser.id,
25 | name: this.testUser.name,
26 | };
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/auth-example/src/auth/local-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { AuthGuard } from '@nestjs/passport';
3 |
4 | @Injectable()
5 | export class LocalAuthGuard extends AuthGuard('local') {
6 | constructor() {
7 | super();
8 | console.log('LocalAuthGuard');
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/auth-example/src/auth/local.strategy.ts:
--------------------------------------------------------------------------------
1 | import { Strategy } from 'passport-local';
2 | import { PassportStrategy } from '@nestjs/passport';
3 | import { Injectable, UnauthorizedException } from '@nestjs/common';
4 | import { AuthService } from './auth.service';
5 |
6 | @Injectable()
7 | export class LocalStrategy extends PassportStrategy(Strategy) {
8 | constructor(private authService: AuthService) {
9 | super({ usernameField: 'username' });
10 | }
11 |
12 | validate(username: string, password: string): any {
13 | console.log('LocalStrategy validate()');
14 | const user = this.authService.validateUser(username, password);
15 | if (!user) {
16 | throw new UnauthorizedException();
17 | }
18 | return user;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/auth-example/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | await app.listen(3000);
7 | }
8 | bootstrap();
9 |
--------------------------------------------------------------------------------
/auth-example/src/types/User.ts:
--------------------------------------------------------------------------------
1 | export interface User {
2 | id: number;
3 | name: string;
4 | password: string;
5 | }
6 |
--------------------------------------------------------------------------------
/auth-example/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/auth-example/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/auth-example/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/auth-example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "ES2021",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/clase01-intro/node-hello-world/.readme:
--------------------------------------------------------------------------------
1 | # Los pasos para crear este proyecto fueron:
2 |
3 | 1. Crear el repositorio del proyecto
4 | 2. Ejecutar en la terminal el comando `npm init --y` (Inicializa un proyecto en node, creando un package.json)
5 | 3. Crear el archivo index.json
6 | 4. Escribir nuestro código
7 | 5. Ejecutar el código con el comando `node index.js`
8 |
--------------------------------------------------------------------------------
/clase01-intro/node-hello-world/index.js:
--------------------------------------------------------------------------------
1 | // Defino la función sayHello que acepta como parámetro un nombre
2 | function sayHello(name) {
3 | // imprimo en pantalla
4 | console.log(`Hola ${name}`);
5 | }
6 |
7 | // ejecuto la función
8 | sayHello("mundo");
9 |
--------------------------------------------------------------------------------
/clase01-intro/node-hello-world/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hello-world",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC"
12 | }
13 |
--------------------------------------------------------------------------------
/clase01-intro/node-ts-hello-world/.readme:
--------------------------------------------------------------------------------
1 | # Los pasos para crear este proyecto fueron:
2 |
3 | 1. Crear el repositorio del proyecto
4 | 2. Ejecutar en la terminal el comando `npm init --y` (Inicializa un proyecto en node, creando un package.json)
5 | 3. Crear el archivo index.json
6 | 4. Escribir nuestro código
7 | 5. Ejecutar el código con el comando `node index.js`
8 |
--------------------------------------------------------------------------------
/clase01-intro/node-ts-hello-world/index.ts:
--------------------------------------------------------------------------------
1 | function sayHi(name: string) {
2 | console.log(`Hola ${name}`);
3 | }
4 |
5 | sayHi("Bel");
6 |
--------------------------------------------------------------------------------
/clase01-intro/node-ts-hello-world/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-ts-hello-world",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "devDependencies": {
8 | "typescript": "^5.2.2"
9 | }
10 | },
11 | "node_modules/typescript": {
12 | "version": "5.2.2",
13 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
14 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
15 | "dev": true,
16 | "bin": {
17 | "tsc": "bin/tsc",
18 | "tsserver": "bin/tsserver"
19 | },
20 | "engines": {
21 | "node": ">=14.17"
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/clase01-intro/node-ts-hello-world/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "typescript": "^5.2.2"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/clase02-repaso-js/algoritmia-resuelto.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Tenemos una funcion que sirve para determinar si una palabra es un palindromo sin utilizar funciones predefinidas de javascript
3 | * Se les ocurre como mejorarla?
4 | */
5 |
6 | const word = "reconocer"
7 |
8 | // Inicial
9 | function isPalindrome(word) {
10 | let reversedWord = ""
11 |
12 | for (let i = 0; i < word.length; i++) {
13 | reversedWord += word[word.length - i - 1]
14 | }
15 |
16 | return reversedWord === word
17 | }
18 |
19 | // Primera mejora
20 | function isPalindrome(word) {
21 | for (let i = word.length - 1; i >= 0; i--) {
22 | if (word[i] !== word[word.length - i - 1]) {
23 | return false
24 | }
25 | }
26 |
27 | return true
28 | }
29 |
30 | // Segunda mejora
31 | function isPalindrome(word) {
32 | for (let i = 0; i < Math.floor(word.length / 2); i++) {
33 | if (word[i] !== word[word.length - 1 - i]) {
34 | return false;
35 | }
36 | }
37 |
38 | return true
39 | }
40 |
41 | console.log(isPalindrome(word))
42 |
43 |
44 |
45 | /*
46 | * Tenemos un array de estudiantes con su nombre, edad y numero de pasaporte. Tambien tenemos una funcion que nos devuelve la edad de
47 | * un estudiante a partir de su numero de pasaporte.
48 | * Como podemos mejorar nuestra funcion? Total libertad para cambiar lo que quieran
49 | */
50 |
51 |
52 | // Inicial
53 | const students = [
54 | {
55 | name: "Juani",
56 | passportId: 1,
57 | age: 29
58 | },
59 | {
60 | name: "Carla",
61 | passportId: 2,
62 | age: 25
63 | }
64 | ]
65 |
66 | function getStudentAge(passportId) {
67 | for (let i = 0; i < students.length; i++) {
68 | if (students[i].passportId === passportId) {
69 | return students[i].age
70 | }
71 | }
72 | }
73 |
74 |
75 | // Mejora
76 | const improvedStudents = {
77 | 1: {
78 | name: "Juani",
79 | age: 29
80 | },
81 | 2: {
82 | name: "Carla",
83 | age: 25
84 | }
85 | }
86 |
87 |
88 | function getStudentAge(passportId) {
89 | return improvedStudents[passportId].age
90 | }
91 |
92 |
93 | console.log(getStudentAge(1))
94 |
--------------------------------------------------------------------------------
/clase02-repaso-js/algoritmia.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Tenemos una funcion que sirve para determinar si una palabra es un palindromo sin utilizar funciones predefinidas de javascript
3 | * Se les ocurre como mejorarla?
4 | */
5 |
6 | const word = "reconocer"
7 |
8 | function isPalindrome(word) {
9 | let reversedWord = ""
10 |
11 | for (let i = 0; i < word.length; i++) {
12 | reversedWord += word[word.length - i - 1]
13 | }
14 |
15 | return reversedWord === word
16 | }
17 |
18 | console.log(isPalindrome(word))
19 |
20 |
21 | /*
22 | * Tenemos un array de estudiantes con su nombre, edad y numero de pasaporte. Tambien tenemos una funcion que nos devuelve la edad de
23 | * un estudiante a partir de su numero de pasaporte.
24 | * Como podemos mejorar nuestra funcion? Total libertad para cambiar lo que quieran
25 | */
26 |
27 | const students = [
28 | {
29 | name: "Juani",
30 | passportId: 1,
31 | age: 29
32 | },
33 | {
34 | name: "Carla",
35 | passportId: 2,
36 | age: 25
37 | }
38 | ]
39 |
40 | function getStudentAge(passportId) {
41 | for (let i = 0; i < students.length; i++) {
42 | if (students[i].passportId === passportId) {
43 | return students[i].age
44 | }
45 | }
46 | }
47 |
48 |
49 | console.log(getStudentAge(1))
50 |
--------------------------------------------------------------------------------
/clase02-repaso-js/demo-typescript.ts:
--------------------------------------------------------------------------------
1 | // Number
2 | const thisIsANumber: number = 1;
3 |
4 | // String
5 | const thisIsAString: string = "hello";
6 |
7 | // Boolean
8 | const thisIsABoolean: boolean = true;
9 |
10 | // Array
11 | const firstArray: number[] = [1, 2, 3];
12 | const secondArray: (number | string | boolean)[] = [1, "a", false];
13 |
14 | // Object
15 | interface IObject {
16 | name: string;
17 | age: number;
18 | }
19 | const thisIsAnObject: IObject = {
20 | name: "Juani",
21 | age: 29,
22 | };
23 |
24 | // Undefined
25 | const thisIsUndefined: undefined = undefined;
26 |
27 | // Null
28 | const thisIsNull: null = null;
29 |
--------------------------------------------------------------------------------
/clase02-repaso-js/ecma.js:
--------------------------------------------------------------------------------
1 | // const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2 |
3 | // // Map, filter, etc
4 | // const even = arr.filter((number) => number % 2 === 0)
5 | // console.log(even)
6 |
7 |
8 | // Optional chaining (?.)
9 | // const firstStudent = {
10 | // name: "Juani",
11 | // age: 29,
12 | // passport: {
13 | // number: 123456,
14 | // country: "Argentina"
15 | // }
16 | // }
17 |
18 | // const secondStudent = {
19 | // name: "Juani",
20 | // age: 29,
21 | // }
22 |
23 | // console.log(firstStudent?.passport?.country)
24 | // console.log(secondStudent?.passport?.country)
25 |
26 |
27 | // Nullish operator (??)
28 |
29 | const age = 20;
30 |
31 | //Sin nullish operator
32 | const canDrive = age >= 18 ? true : false
33 |
34 | //Con nullish operator
35 | const canDrive2 = age >= 18 ?? false
36 |
37 | console.log(canDrive)
38 | console.log(canDrive2)
39 |
--------------------------------------------------------------------------------
/clase02-repaso-js/primitivos.js:
--------------------------------------------------------------------------------
1 | // // Number
2 | // const thisIsANumber = 1;
3 |
4 | // // String
5 | // const thisIsAString = 'hello';
6 |
7 | // // Boolean
8 | // const thisIsABoolean = true;
9 |
10 | // // Array
11 | // const firstArray = [1, 2, 3];
12 | // const secondArray = [1, 'a', false];
13 |
14 | // // Object
15 | // const thisIsAnObject = {
16 | // name: "Juani",
17 | // age: 29
18 | // }
19 |
20 |
21 | // // Undefined
22 | // const thisIsUndefined = undefined;
23 |
24 | // // Null
25 | // const thisIsNull = null;
26 |
27 | // const numbers = [1, 2, 3];
28 |
29 | // const newNumbers = []
30 |
31 | // numbers.forEach((number) => {
32 | // newNumbers.push(number * 2);
33 | // })
34 |
35 | // console.log(numbers);
36 | // console.log(newNumbers)
37 |
38 |
39 | function Persona(nombre) {
40 | this.nombre = nombre;
41 | }
42 |
43 | Persona.prototype.saludar = function () {
44 | return `Hola, mi nombre es ${this.nombre}`
45 | }
46 |
47 | const newPersona = new Persona("Juani");
48 | const newPersona2 = new Persona("Juani2");
49 |
50 | console.log(newPersona)
51 | console.log(newPersona.nombre);
52 | console.log(newPersona.saludar())
53 | console.log(newPersona.__proto__)
54 |
55 |
56 | console.log(newPersona2.saludar())
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/clase02-repaso-js/prototipos-clases.js:
--------------------------------------------------------------------------------
1 | class LikesService {
2 | constructor() {
3 | this.likes = 0;
4 | this.dislikes = 0;
5 | }
6 |
7 | like() {
8 | this.likes++;
9 | }
10 |
11 | dislike() {
12 | this.dislikes++;
13 | }
14 |
15 | getLikes() {
16 | return this.likes;
17 | }
18 |
19 | getDislikes() {
20 | return this.dislikes;
21 | }
22 | }
23 |
24 | class Comment extends LikesService {
25 | constructor(msg) {
26 | super();
27 | this.message = msg;
28 | }
29 | }
30 |
31 | class CommentsService {
32 | constructor() {
33 | this.comments = [];
34 | this.commentsQty = 0;
35 | }
36 |
37 | addComment(comment) {
38 | this.commentsQty++;
39 |
40 | this.comments.push({ id: this.commentsQty, comment });
41 | }
42 |
43 | getComments() {
44 | return this.comments;
45 | }
46 | }
47 |
48 |
49 | console.log('\n')
50 |
51 | console.log("Creamos una nueva instancia de nuestro servicio de comentarios")
52 | const thread = new CommentsService();
53 | console.log(thread)
54 | console.log('\n')
55 |
56 | console.log("Si llamamos a la funcion getComments vemos que viene vacia porque todavia no agregamos nada")
57 | console.log(thread.getComments())
58 | console.log('\n')
59 |
60 | console.log("Creamos una nueva instancia de un comentario con un mensaje que querramos")
61 | const firstComment = new Comment("this is a test")
62 | console.log(firstComment)
63 | console.log('\n')
64 |
65 | console.log("Agregamos nuestro comentario a nuestro thread")
66 | thread.addComment(firstComment)
67 | console.log(thread)
68 | console.log('\n')
69 |
70 | console.log("Ahora nuestro thread tiene un comentario")
71 | console.log(thread.getComments())
72 | console.log('\n')
73 |
74 | console.log("Le damos like a nuestro comentario")
75 | firstComment.like();
76 | console.log(firstComment)
77 | console.log('\n')
78 |
79 | console.log("Vemos que nuestro comentario tiene un like dentro de nuestro thread")
80 | console.log(thread.getComments())
81 |
82 |
--------------------------------------------------------------------------------
/clase02-repaso-js/prototipos.js:
--------------------------------------------------------------------------------
1 | // Un sistema de comentarios
2 |
3 | //LikesService
4 | function LikesService() {
5 | this.likes = 0;
6 | this.dislikes = 0;
7 | }
8 |
9 | LikesService.prototype.like = function () {
10 | this.likes++;
11 | }
12 |
13 | LikesService.prototype.dislike = function () {
14 | this.dislikes++;
15 | }
16 |
17 | LikesService.prototype.getLikes = function () {
18 | return this.likes;
19 | }
20 |
21 | LikesService.prototype.getDislikes = function () {
22 | return this.dislikes;
23 | }
24 |
25 | //Comment
26 | function Comment(msg) {
27 | LikesService.call(this)
28 | this.message = msg
29 | }
30 |
31 | Comment.prototype = Object.create(LikesService.prototype);
32 | Comment.prototype.constructor = Comment;
33 |
34 |
35 | // CommentsService
36 | function CommentsService() {
37 | this.comments = [];
38 | this.commentsQty = 0;
39 | }
40 |
41 | CommentsService.prototype.addComment = function (comment) {
42 | this.commentsQty++;
43 |
44 | this.comments.push({ id: this.commentsQty, comment });
45 | }
46 |
47 | CommentsService.prototype.getComments = function () {
48 | return this.comments;
49 | }
50 |
51 | console.log('\n')
52 |
53 | console.log("Creamos una nueva instancia de nuestro servicio de comentarios")
54 | const thread = new CommentsService();
55 | console.log(thread)
56 | console.log('\n')
57 |
58 | console.log("Si llamamos a la funcion getComments vemos que viene vacia porque todavia no agregamos nada")
59 | console.log(thread.getComments())
60 | console.log('\n')
61 |
62 | console.log("Creamos una nueva instancia de un comentario con un mensaje que querramos")
63 | const firstComment = new Comment("this is a test")
64 | console.log(firstComment)
65 | console.log('\n')
66 |
67 | console.log("Agregamos nuestro comentario a nuestro thread")
68 | thread.addComment(firstComment)
69 | console.log(thread)
70 | console.log('\n')
71 |
72 | console.log("Ahora nuestro thread tiene un comentario")
73 | console.log(thread.getComments())
74 | console.log('\n')
75 |
76 | console.log("Le damos like a nuestro comentario")
77 | firstComment.like();
78 | console.log(firstComment)
79 | console.log('\n')
80 |
81 | console.log("Vemos que nuestro comentario tiene un like dentro de nuestro thread")
82 | console.log(thread.getComments())
83 |
84 |
--------------------------------------------------------------------------------
/clase02-repaso-js/strict-mode.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | x = 1;
3 | console.log(x);
4 |
--------------------------------------------------------------------------------
/clase09-nestapi/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir: __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/clase09-nestapi/.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
--------------------------------------------------------------------------------
/clase09-nestapi/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/clase09-nestapi/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/clase09-nestapi/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "deleteOutDir": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/clase09-nestapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nestapi",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "build": "nest build",
10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11 | "start": "nest start",
12 | "start:dev": "nest start --watch",
13 | "start:debug": "nest start --debug --watch",
14 | "start:prod": "node dist/main",
15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --config ./test/jest-e2e.json"
21 | },
22 | "dependencies": {
23 | "@nestjs/axios": "^3.0.1",
24 | "@nestjs/common": "^10.2.8",
25 | "@nestjs/config": "^3.1.1",
26 | "@nestjs/core": "^10.0.0",
27 | "@nestjs/jwt": "^10.1.1",
28 | "@nestjs/passport": "^10.0.2",
29 | "@nestjs/platform-express": "^10.0.0",
30 | "axios": "^1.6.0",
31 | "passport": "^0.6.0",
32 | "passport-jwt": "^4.0.1",
33 | "reflect-metadata": "^0.1.13",
34 | "rxjs": "^7.8.1"
35 | },
36 | "devDependencies": {
37 | "@nestjs/cli": "^10.0.0",
38 | "@nestjs/schematics": "^10.0.0",
39 | "@nestjs/testing": "^10.0.0",
40 | "@types/express": "^4.17.17",
41 | "@types/jest": "^29.5.2",
42 | "@types/node": "^20.3.1",
43 | "@types/supertest": "^2.0.12",
44 | "@typescript-eslint/eslint-plugin": "^6.0.0",
45 | "@typescript-eslint/parser": "^6.0.0",
46 | "eslint": "^8.42.0",
47 | "eslint-config-prettier": "^9.0.0",
48 | "eslint-plugin-prettier": "^5.0.0",
49 | "jest": "^29.5.0",
50 | "prettier": "^3.0.0",
51 | "source-map-support": "^0.5.21",
52 | "supertest": "^6.3.3",
53 | "ts-jest": "^29.1.0",
54 | "ts-loader": "^9.4.3",
55 | "ts-node": "^10.9.1",
56 | "tsconfig-paths": "^4.2.0",
57 | "typescript": "^5.1.3"
58 | },
59 | "jest": {
60 | "moduleFileExtensions": [
61 | "js",
62 | "json",
63 | "ts"
64 | ],
65 | "rootDir": "src",
66 | "testRegex": ".*\\.spec\\.ts$",
67 | "transform": {
68 | "^.+\\.(t|j)s$": "ts-jest"
69 | },
70 | "collectCoverageFrom": [
71 | "**/*.(t|j)s"
72 | ],
73 | "coverageDirectory": "../coverage",
74 | "testEnvironment": "node"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/express/mvc.ts:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 | const PORT = 3000;
4 |
5 | // Permite a Express entender datos de formularios y JSON
6 | app.use(express.urlencoded({ extended: true }));
7 | app.use(express.json());
8 |
9 | // Configuración para usar EJS como motor de plantillas
10 | app.set('view engine', 'ejs');
11 |
12 | // Modelo
13 | const messages = [];
14 |
15 | // Controlador
16 | const MessagesController = {
17 | findAll: (req, res) => {
18 | res.render('messages', { messages });
19 | },
20 | create: (req, res) => {
21 | const { text } = req.body;
22 | if (text) {
23 | const message = { id: messages.length + 1, text };
24 | messages.push(message);
25 | res.redirect('/messages');
26 | } else {
27 | res.status(400).send('Bad Request');
28 | }
29 | },
30 | };
31 |
32 | // Rutas
33 | app.get('/messages', MessagesController.findAll);
34 | app.post('/messages', MessagesController.create);
35 |
36 | // Vista simple para mostrar mensajes y un formulario para enviarlos
37 | app.get('/', (req, res) => {
38 | res.render('index');
39 | });
40 |
41 | // Iniciando el servidor
42 | app.listen(PORT, () => {
43 | console.log(`Servidor escuchando en el puerto ${PORT}`);
44 | });
45 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/express/no-mvc.ts:
--------------------------------------------------------------------------------
1 | // const express = require('express');
2 | // const app = express();
3 | // const PORT = 3000;
4 |
5 | // // Permite a Express entender datos de formularios y JSON
6 | // app.use(express.urlencoded({ extended: true }));
7 | // app.use(express.json());
8 |
9 | // // Configuración para usar EJS como motor de plantillas
10 | // app.set('view engine', 'ejs');
11 |
12 | // // Datos almacenados en memoria
13 | // const messages = [];
14 |
15 | // // Ruta para mostrar el formulario y los mensajes
16 | // app.get('/', (req, res) => {
17 | // res.render('index', { messages });
18 | // });
19 |
20 | // // Ruta para manejar la creación de un mensaje
21 | // app.post('/messages', (req, res) => {
22 | // const { text } = req.body;
23 | // if (text) {
24 | // const message = { id: messages.length + 1, text };
25 | // messages.push(message);
26 | // res.redirect('/');
27 | // } else {
28 | // res.status(400).send('Bad Request');
29 | // }
30 | // });
31 |
32 | // // Iniciar el servidor
33 | // app.listen(PORT, () => {
34 | // console.log(`Servidor escuchando en el puerto ${PORT}`);
35 | // });
36 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/patrones/factory.ts:
--------------------------------------------------------------------------------
1 | import { Module, Injectable, Global } from '@nestjs/common';
2 |
3 | // Este servicio podría ser responsable de cargar y validar las opciones de configuración.
4 | @Injectable()
5 | class ConfigOptionsService {
6 | private readonly envConfig: { [key: string]: string };
7 |
8 | constructor() {
9 | // Aquí podrías cargar las configuraciones de un archivo .env o cualquier otra fuente
10 | // y realizar validaciones necesarias.
11 | this.envConfig = {
12 | NODE_ENV: process.env.NODE_ENV || 'development',
13 | PORT: process.env.PORT || '3000',
14 | // Aquí agregarías más configuraciones según sea necesario
15 | };
16 | }
17 |
18 | get(key: string): string {
19 | return this.envConfig[key];
20 | }
21 | }
22 |
23 | // El módulo que utiliza el servicio de ConfigOptionsService para proporcionar las configuraciones.
24 | @Global()
25 | @Module({
26 | providers: [
27 | {
28 | provide: 'CONFIG_OPTIONS',
29 | useFactory: (configService: ConfigOptionsService) => {
30 | // La factory podría devolver un objeto de configuración más complejo o personalizado.
31 | // y lo crea dependiendo de sus necesidades al momento de la ejecución
32 | return {
33 | nodeEnv: configService.get('NODE_ENV'),
34 | port: parseInt(configService.get('PORT'), 10),
35 | };
36 | },
37 | inject: [ConfigOptionsService],
38 | },
39 | ConfigOptionsService,
40 | ],
41 | exports: ['CONFIG_OPTIONS', ConfigOptionsService], // Exportamos CONFIG_OPTIONS para que pueda ser inyectado en otros módulos.
42 | })
43 | export class ConfigModule {}
44 |
45 | // En otros lugares de tu aplicación, podrías inyectar 'CONFIG_OPTIONS' para obtener acceso a estas configuraciones.
46 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/patrones/observable.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller,
3 | Get,
4 | Param,
5 | Res,
6 | HttpException,
7 | HttpStatus,
8 | } from '@nestjs/common';
9 | import { PokemonService } from './pokemon.service';
10 | import { Response } from 'express';
11 |
12 | @Controller()
13 | export class PokemonController {
14 | constructor(private readonly pokemonService: PokemonService) {}
15 |
16 | @Get('/pokemon/:name')
17 | getPokemon(@Param('name') name: string, @Res() response: Response) {
18 | this.pokemonService.getPokemonByName(name).subscribe({
19 | next: (data) => {
20 | response.send(data);
21 | },
22 | error: () => {
23 | throw new HttpException(
24 | 'Error al obtener el Pokémon',
25 | HttpStatus.INTERNAL_SERVER_ERROR,
26 | );
27 | },
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/patrones/singleton.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Scope, Controller, Get } from '@nestjs/common';
2 |
3 | // Este es un servicio singleton, el cual es el ámbito por defecto en NestJS.
4 | // Nest creará una única instancia de este servicio y la compartirá en toda la aplicación.
5 | @Injectable()
6 | export class SingletonService {
7 | private count = 0;
8 |
9 | increment() {
10 | this.count++;
11 | }
12 |
13 | getCount() {
14 | return this.count;
15 | }
16 | }
17 |
18 | // Este es un servicio con ámbito transitorio.
19 | // Nest creará una nueva instancia del servicio cada vez que se inyecte.
20 | @Injectable({ scope: Scope.TRANSIENT })
21 | export class TransientService {
22 | private count = 0;
23 |
24 | increment() {
25 | this.count++;
26 | }
27 |
28 | getCount() {
29 | return this.count;
30 | }
31 | }
32 |
33 | // Un controlador para demostrar el uso de ambos servicios.
34 | @Controller('counter')
35 | export class AppController {
36 | constructor(
37 | private readonly singletonService: SingletonService,
38 | private readonly transientService: TransientService,
39 | ) {}
40 |
41 | @Get('/singleton')
42 | getSingletonCount(): string {
43 | this.singletonService.increment();
44 | return `Singleton count is now: ${this.singletonService.getCount()}`;
45 | }
46 |
47 | @Get('/transient')
48 | getTransientCount(): string {
49 | this.transientService.increment();
50 | return `Transient count is now: ${this.transientService.getCount()}`;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/patrones/srtrategy.ts:
--------------------------------------------------------------------------------
1 | // jwt.strategy.ts
2 | import { Injectable } from '@nestjs/common';
3 | import { PassportStrategy } from '@nestjs/passport';
4 | import { Strategy, ExtractJwt } from 'passport-jwt';
5 | import { ConfigService } from '@nestjs/config';
6 |
7 | @Injectable()
8 | export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
9 | constructor(private configService: ConfigService) {
10 | super({
11 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
12 | ignoreExpiration: false,
13 | secretOrKey: configService.get('JWT_SECRET'),
14 | });
15 | }
16 |
17 | async validate(payload: any) {
18 | return { userId: payload.sub, username: payload.username };
19 | }
20 | }
21 |
22 | // auth.module.ts
23 | import { Module } from '@nestjs/common';
24 | import { PassportModule } from '@nestjs/passport';
25 | import { JwtModule } from '@nestjs/jwt';
26 | import { JwtStrategy } from './jwt.strategy';
27 | import { ConfigModule, ConfigService } from '@nestjs/config';
28 |
29 | @Module({
30 | imports: [
31 | PassportModule,
32 | JwtModule.registerAsync({
33 | imports: [ConfigModule],
34 | useFactory: async (configService: ConfigService) => ({
35 | secret: configService.get('JWT_SECRET'),
36 | signOptions: { expiresIn: '60s' },
37 | }),
38 | inject: [ConfigService],
39 | }),
40 | ConfigModule,
41 | ],
42 | providers: [JwtStrategy],
43 | })
44 | export class AuthModule {}
45 |
46 | // profile.controller.ts
47 | import { Controller, Get, UseGuards, Request } from '@nestjs/common';
48 | import { AuthGuard } from '@nestjs/passport';
49 |
50 | @Controller('profile')
51 | export class ProfileController {
52 | @UseGuards(AuthGuard('jwt'))
53 | @Get()
54 | getProfile(@Request() req) {
55 | return req.user;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/patrones/strategy.ts:
--------------------------------------------------------------------------------
1 | // jwt.strategy.ts
2 | import { Injectable } from '@nestjs/common';
3 | import { PassportStrategy } from '@nestjs/passport';
4 | import { Strategy, ExtractJwt } from 'passport-jwt';
5 | import { ConfigService } from '@nestjs/config';
6 |
7 | @Injectable()
8 | class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
9 | constructor(private configService: ConfigService) {
10 | super({
11 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
12 | ignoreExpiration: false,
13 | secretOrKey: configService.get('JWT_SECRET'),
14 | });
15 | }
16 |
17 | async validate(payload: any) {
18 | return { userId: payload.sub, username: payload.username };
19 | }
20 | }
21 |
22 | // auth.module.ts
23 | import { Module } from '@nestjs/common';
24 | import { PassportModule } from '@nestjs/passport';
25 | import { JwtModule } from '@nestjs/jwt';
26 | import { JwtStrategy } from './jwt.strategy';
27 | import { ConfigModule, ConfigService } from '@nestjs/config';
28 |
29 | @Module({
30 | imports: [
31 | PassportModule,
32 | JwtModule.registerAsync({
33 | imports: [ConfigModule],
34 | useFactory: async (configService: ConfigService) => ({
35 | secret: configService.get('JWT_SECRET'),
36 | signOptions: { expiresIn: '60s' },
37 | }),
38 | inject: [ConfigService],
39 | }),
40 | ConfigModule,
41 | ],
42 | providers: [JwtStrategy],
43 | })
44 | class AuthModule {}
45 |
46 | // profile.controller.ts
47 | import { Controller, Get, UseGuards, Request } from '@nestjs/common';
48 | import { AuthGuard } from '@nestjs/passport';
49 |
50 | @Controller('profile')
51 | class ProfileController {
52 | @UseGuards(AuthGuard('jwt'))
53 | @Get()
54 | getProfile(@Request() req) {
55 | return req.user;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/poo/abtraction.ts:
--------------------------------------------------------------------------------
1 | // Esto normalmente estaría en un archivo llamado create-user.dto.ts
2 | export class CreateUserDto {
3 | readonly name: string;
4 | readonly email: string;
5 | readonly password: string;
6 | }
7 |
8 | // Esto normalmente estaría en un archivo llamado update-user.dto.ts
9 | export class UpdateUserDto {
10 | readonly name?: string;
11 | readonly email?: string;
12 | readonly password?: string;
13 | }
14 |
15 | // Esto normalmente estaría en un archivo llamado user.entity.ts
16 | export class User {
17 | id: string;
18 | name: string;
19 | email: string;
20 | password: string;
21 | // Otras propiedades y métodos de la entidad User
22 | }
23 |
24 | // Esto normalmente estaría en un archivo llamado user.repository.ts
25 | // Definimos una clase abstracta con los métodos esperados
26 | export abstract class UserRepository {
27 | abstract findAllUsers(): Promise;
28 | abstract findUserById(id: string): Promise;
29 | abstract createUser(user: CreateUserDto): Promise;
30 | abstract updateUser(id: string, updateUserDto: UpdateUserDto): Promise;
31 | abstract deleteUser(id: string): Promise;
32 | }
33 |
34 | // Esto normalmente estaría en un archivo llamado sql.user.repository.ts
35 | // Tenemos una definición concreta para manejar específicamente los usuarios que vengan desde SQL
36 | // podemos tener otra para Mongo y fácilmente desacoplar nuestras decisiones de datos del código
37 | import { Injectable } from '@nestjs/common';
38 |
39 | @Injectable()
40 | export class SqlUserRepository extends UserRepository {
41 | private users: User[] = []; // Simula una base de datos con un array en memoria
42 |
43 | // implementaciones concretas
44 |
45 | async findAllUsers(): Promise {
46 | return this.users;
47 | }
48 |
49 | async findUserById(id: string): Promise {
50 | return this.users.find((user) => user.id === id) || null;
51 | }
52 |
53 | async createUser(createUserDto: CreateUserDto): Promise {
54 | const newUser = {
55 | ...createUserDto,
56 | id: Date.now().toString(), // Generación simple de ID para fines de ejemplo
57 | };
58 | this.users.push(newUser);
59 | return newUser;
60 | }
61 |
62 | async updateUser(id: string, updateUserDto: UpdateUserDto): Promise {
63 | let user = await this.findUserById(id);
64 | if (!user) throw new Error('Usuario no encontrado');
65 | user = { ...user, ...updateUserDto };
66 | const index = this.users.findIndex((user) => user.id === id);
67 | this.users[index] = user;
68 | return user;
69 | }
70 |
71 | async deleteUser(id: string): Promise {
72 | const index = this.users.findIndex((user) => user.id === id);
73 | if (index > -1) {
74 | this.users.splice(index, 1);
75 | }
76 | }
77 | }
78 |
79 | // Esto normalmente estaría en un archivo llamado app.module.ts o user.module.ts
80 | import { Module } from '@nestjs/common';
81 |
82 | @Module({
83 | providers: [
84 | {
85 | provide: UserRepository,
86 | useClass: SqlUserRepository,
87 | },
88 | ],
89 | exports: [UserRepository],
90 | })
91 | export class UserModule {}
92 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/poo/encapsulation.ts:
--------------------------------------------------------------------------------
1 | // Este código normalmente se dividiría en varios archivos:
2 |
3 | // user.entity.ts
4 | export class User {
5 | private password: string; // Encapsulado, no accesible fuera de esta clase
6 | constructor(
7 | public readonly id: string,
8 | public readonly email: string,
9 | password: string,
10 | ) {
11 | this.password = password;
12 | }
13 |
14 | validatePassword(password: string): boolean {
15 | return this.password === password;
16 | }
17 |
18 | // ... Otros métodos y propiedades
19 | }
20 |
21 | // user.service.ts
22 | import { Injectable } from '@nestjs/common';
23 |
24 | @Injectable()
25 | class UserService {
26 | private users: User[] = []; // Datos encapsulados, no directamente accesibles
27 |
28 | createUser(email: string, password: string): User {
29 | const newUser = new User(Date.now().toString(), email, password);
30 | this.users.push(newUser);
31 | return newUser;
32 | }
33 |
34 | // ... Otros métodos
35 | }
36 |
37 | // user.module.ts
38 | import { Module } from '@nestjs/common';
39 |
40 | @Module({
41 | providers: [UserService],
42 | exports: [UserService], // UserService está disponible para otros módulos
43 | })
44 | class UserModule {}
45 |
46 | // En un ejemplo de uso, tendrías algo como esto:
47 |
48 | // user.controller.ts
49 | import { Controller, Post, Body } from '@nestjs/common';
50 | //import { UserService } from './user.service';
51 |
52 | @Controller('users')
53 | export class UserController {
54 | constructor(private userService: UserService) {}
55 |
56 | @Post()
57 | createUser(@Body() body: { email: string; password: string }) {
58 | return this.userService.createUser(body.email, body.password);
59 | }
60 |
61 | // ... Otros endpoints
62 | }
63 |
64 | // app.module.ts
65 | //import { Module } from '@nestjs/common';
66 | //import { UserModule } from './user.module';
67 |
68 | @Module({
69 | imports: [UserModule],
70 | controllers: [],
71 | providers: [],
72 | })
73 | export class AppModule {}
74 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/poo/inheritance.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Controller, Get, Module } from '@nestjs/common';
2 | import { NestFactory } from '@nestjs/core';
3 | import { HttpService } from '@nestjs/axios';
4 | import { firstValueFrom } from 'rxjs';
5 |
6 | // Servicio base para obtener información de Pokémon de la PokeAPI.
7 | @Injectable()
8 | class PokemonService {
9 | constructor(private httpService: HttpService) {}
10 |
11 | // Método para obtener un Pokémon por nombre.
12 | async getPokemonByName(name: string): Promise {
13 | // Realiza la petición HTTP y devuelve la respuesta.
14 | const response = await firstValueFrom(
15 | this.httpService.get(`https://pokeapi.co/api/v2/pokemon/${name}`),
16 | );
17 | return response.data;
18 | }
19 | }
20 |
21 | // Servicio especializado para Pokémon de tipo agua que extiende de PokemonService.
22 | @Injectable()
23 | class WaterPokemonService extends PokemonService {
24 | // Sobreescribe el método getPokemonByName para filtrar solo los Pokémon de tipo agua.
25 | async getPokemonByName(name: string): Promise {
26 | const pokemon = await super.getPokemonByName(name);
27 | // Verifica si el Pokémon es de tipo agua, si no, lanza un error.
28 | if (!pokemon.types.some((typeInfo) => typeInfo.type.name === 'water')) {
29 | throw new Error('This is not a water-type Pokémon.');
30 | }
31 | return pokemon;
32 | }
33 | }
34 |
35 | // Controlador con las rutas de la API.
36 | @Controller()
37 | class PokemonController {
38 | constructor(
39 | private pokemonService: PokemonService,
40 | private waterPokemonService: WaterPokemonService,
41 | ) {}
42 |
43 | // Ruta para obtener cualquier Pokémon.
44 | @Get('pokemon/:name')
45 | async getPokemon(name: string) {
46 | return this.pokemonService.getPokemonByName(name);
47 | }
48 |
49 | // Ruta para obtener solo Pokémon de tipo agua.
50 | @Get('water-pokemon/:name')
51 | async getWaterPokemon(name: string) {
52 | return this.waterPokemonService.getPokemonByName(name);
53 | }
54 | }
55 |
56 | // Módulo
57 |
58 | @Module({
59 | controllers: [PokemonController],
60 | providers: [PokemonService, WaterPokemonService, HttpService],
61 | })
62 | class AppModule {}
63 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/poo/polymorphism.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | // Clase base User
4 | class User {
5 | constructor(
6 | public id: number,
7 | public email: string,
8 | protected password: string, // Cambiado a protected para permitir el acceso en clases derivadas
9 | ) {}
10 |
11 | // Método para validar la contraseña
12 | validatePassword(password: string): boolean {
13 | return this.password === password;
14 | }
15 | }
16 |
17 | // Clase derivada para AdminUser
18 | class AdminUser extends User {
19 | public readonly privileges: string[];
20 |
21 | constructor(
22 | id: number,
23 | email: string,
24 | password: string,
25 | privileges: string[],
26 | ) {
27 | super(id, email, password);
28 | this.privileges = privileges;
29 | }
30 |
31 | // Sobrescribiendo el método validatePassword
32 | validatePassword(password: string): boolean {
33 | const valid = super.validatePassword(password);
34 | console.log(
35 | `Administrador ${
36 | valid ? 'validó' : 'no validó'
37 | } correctamente la contraseña.`,
38 | );
39 | return valid;
40 | }
41 |
42 | // Método específico de Admin para agregar privilegios
43 | addPrivilege(privilege: string): void {
44 | this.privileges.push(privilege);
45 | }
46 | }
47 |
48 | // Ejemplo de uso:
49 | const admin = new AdminUser(1, 'admin@example.com', 'securepassword', [
50 | 'manage-system',
51 | ]);
52 | const isValid = admin.validatePassword('securepassword'); // Esto también imprimirá un mensaje en la consola.
53 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/Examples/solid/isp.ts:
--------------------------------------------------------------------------------
1 | // interfaces.ts
2 | // Definición de la interfaz Readable para las operaciones de lectura.
3 | export interface Readable {
4 | findAll(): Promise;
5 | findById(id: string): Promise;
6 | }
7 |
8 | // Definición de la interfaz Writable para las operaciones de escritura.
9 | export interface Writable {
10 | create(item: T): Promise;
11 | update(id: string, item: T): Promise;
12 | delete(id: string): Promise;
13 | }
14 |
15 | // user.service.ts
16 | import { Injectable } from '@nestjs/common';
17 |
18 | // Definición de la estructura de datos para un Usuario.
19 | export interface User {
20 | id: string;
21 | name: string;
22 | // Otras propiedades del usuario
23 | }
24 |
25 | // Servicio que implementa las interfaces Readable y Writable para usuarios.
26 | @Injectable()
27 | export class UserService implements Readable, Writable {
28 | private users: User[] = []; // Almacenamiento en memoria para ejemplificar.
29 |
30 | // Método para obtener todos los usuarios.
31 | async findAll(): Promise {
32 | return this.users;
33 | }
34 |
35 | // Método para obtener un usuario por su ID.
36 | async findById(id: string): Promise {
37 | return this.users.find((user) => user.id === id);
38 | }
39 |
40 | // Método para crear un nuevo usuario.
41 | async create(user: User): Promise {
42 | this.users.push(user);
43 | }
44 |
45 | // Método para actualizar un usuario existente.
46 | async update(id: string, user: User): Promise {
47 | const index = this.users.findIndex((u) => u.id === id);
48 | this.users[index] = user;
49 | }
50 |
51 | // Método para eliminar un usuario por su ID.
52 | async delete(id: string): Promise {
53 | this.users = this.users.filter((user) => user.id !== id);
54 | }
55 | }
56 |
57 | // user.controller.ts
58 | import {
59 | Controller,
60 | Get,
61 | Param,
62 | Post,
63 | Body,
64 | Put,
65 | Delete,
66 | } from '@nestjs/common';
67 | // import { UserService, User } from './user.service';
68 |
69 | // Controlador que maneja las rutas de la API para los usuarios.
70 | @Controller('users')
71 | class UserController {
72 | constructor(private readonly userService: UserService) {}
73 |
74 | // Ruta para obtener todos los usuarios.
75 | @Get()
76 | async getAllUsers(): Promise {
77 | return this.userService.findAll();
78 | }
79 |
80 | // Ruta para obtener un usuario específico por ID.
81 | @Get(':id')
82 | async getUser(@Param('id') id: string): Promise {
83 | return this.userService.findById(id);
84 | }
85 |
86 | // Ruta para crear un nuevo usuario.
87 | @Post()
88 | async createUser(@Body() user: User): Promise {
89 | return this.userService.create(user);
90 | }
91 |
92 | // Ruta para actualizar un usuario existente.
93 | @Put(':id')
94 | async updateUser(@Param('id') id: string, @Body() user: User): Promise {
95 | return this.userService.update(id, user);
96 | }
97 |
98 | // Ruta para eliminar un usuario por ID.
99 | @Delete(':id')
100 | async deleteUser(@Param('id') id: string): Promise {
101 | return this.userService.delete(id);
102 | }
103 | }
104 |
105 | // app.module.ts
106 | import { Module } from '@nestjs/common';
107 |
108 | // Módulo principal de la aplicación que registra el controlador y el servicio de usuarios.
109 | @Module({
110 | controllers: [UserController],
111 | providers: [UserService],
112 | })
113 | export class AppModule {}
114 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { PokemonModule } from './pokemon.module';
5 |
6 | @Module({
7 | imports: [PokemonModule],
8 | controllers: [AppController],
9 | providers: [AppService],
10 | })
11 | export class AppModule {}
12 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello Bel!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | await app.listen(3000);
7 | }
8 |
9 | bootstrap();
10 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/pokemon.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { PokemonService } from './pokemon.service';
3 | import { firstValueFrom } from 'rxjs';
4 | import { Param, Res } from '@nestjs/common';
5 | import { HttpException, HttpStatus } from '@nestjs/common';
6 |
7 | @Controller()
8 | export class PokemonController {
9 | pokemon: any[];
10 |
11 | constructor(private readonly pokemonService: PokemonService) {
12 | this.pokemon = [];
13 | }
14 |
15 | @Get('/pokemon/:name')
16 | async getPokemon(@Param('name') pokemon, @Res() response): Promise {
17 | try {
18 | const { data } = await firstValueFrom(
19 | await this.pokemonService.getPokemonByName(pokemon),
20 | );
21 | response.send(data.name);
22 | } catch (e) {
23 | throw new HttpException(
24 | 'Error al obtener el Pokémon',
25 | HttpStatus.INTERNAL_SERVER_ERROR,
26 | );
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/pokemon.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { PokemonController } from './pokemon.controller';
3 | import { PokemonService } from './pokemon.service';
4 | import { HttpModule } from '@nestjs/axios';
5 |
6 | @Module({
7 | imports: [HttpModule],
8 | controllers: [PokemonController],
9 | providers: [PokemonService],
10 | })
11 | export class PokemonModule {}
12 |
--------------------------------------------------------------------------------
/clase09-nestapi/src/pokemon.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { HttpService } from '@nestjs/axios';
3 |
4 | @Injectable()
5 | export class PokemonService {
6 | constructor(private readonly httpService: HttpService) {}
7 |
8 | async getPokemonByName(name: string) {
9 | return this.httpService.get(`https://pokeapi.co/api/v2/pokemon/${name}`);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/clase09-nestapi/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/clase09-nestapi/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/clase09-nestapi/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/clase09-nestapi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "ES2021",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------