From 02726341645cf7f80d65d34299781e832c97ee0f Mon Sep 17 00:00:00 2001 From: Thiago Felipe Date: Wed, 25 Aug 2021 21:50:29 -0400 Subject: [PATCH] Inicializando o projeto --- semana20/lama/.eslintrc.json | 197 ++++++++++++++++++++ semana20/lama/.gitignore | 5 + semana20/lama/jest.config.js | 8 + semana20/lama/nodemon.json | 6 + semana20/lama/package.json | 41 ++++ semana20/lama/src/@types/commons.ts | 11 ++ semana20/lama/src/@types/index.ts | 7 + semana20/lama/src/business/index.ts | 0 semana20/lama/src/commons/id.ts | 6 + semana20/lama/src/commons/index.ts | 3 + semana20/lama/src/commons/password.ts | 12 ++ semana20/lama/src/commons/token.ts | 26 +++ semana20/lama/src/data/databaseSQL/index.ts | 0 semana20/lama/src/data/index.ts | 15 ++ semana20/lama/src/docs/swagger.yml | 100 ++++++++++ semana20/lama/src/env.ts | 31 +++ semana20/lama/src/errors/commons.ts | 45 +++++ semana20/lama/src/errors/error.ts | 48 +++++ semana20/lama/src/errors/index.ts | 3 + semana20/lama/src/errors/send.ts | 31 +++ semana20/lama/src/handlers/index.ts | 0 semana20/lama/src/handlers/middleware.ts | 25 +++ semana20/lama/src/index.ts | 24 +++ semana20/lama/src/queries.sql | 3 + semana20/lama/src/routes.ts | 7 + semana20/lama/src/validate/index.ts | 18 ++ semana20/lama/tsconfig.json | 74 ++++++++ 27 files changed, 746 insertions(+) create mode 100644 semana20/lama/.eslintrc.json create mode 100644 semana20/lama/.gitignore create mode 100644 semana20/lama/jest.config.js create mode 100644 semana20/lama/nodemon.json create mode 100644 semana20/lama/package.json create mode 100644 semana20/lama/src/@types/commons.ts create mode 100644 semana20/lama/src/@types/index.ts create mode 100644 semana20/lama/src/business/index.ts create mode 100644 semana20/lama/src/commons/id.ts create mode 100644 semana20/lama/src/commons/index.ts create mode 100644 semana20/lama/src/commons/password.ts create mode 100644 semana20/lama/src/commons/token.ts create mode 100644 semana20/lama/src/data/databaseSQL/index.ts create mode 100644 semana20/lama/src/data/index.ts create mode 100644 semana20/lama/src/docs/swagger.yml create mode 100644 semana20/lama/src/env.ts create mode 100644 semana20/lama/src/errors/commons.ts create mode 100644 semana20/lama/src/errors/error.ts create mode 100644 semana20/lama/src/errors/index.ts create mode 100644 semana20/lama/src/errors/send.ts create mode 100644 semana20/lama/src/handlers/index.ts create mode 100644 semana20/lama/src/handlers/middleware.ts create mode 100644 semana20/lama/src/index.ts create mode 100644 semana20/lama/src/queries.sql create mode 100644 semana20/lama/src/routes.ts create mode 100644 semana20/lama/src/validate/index.ts create mode 100644 semana20/lama/tsconfig.json diff --git a/semana20/lama/.eslintrc.json b/semana20/lama/.eslintrc.json new file mode 100644 index 0000000..12088a5 --- /dev/null +++ b/semana20/lama/.eslintrc.json @@ -0,0 +1,197 @@ +{ + "root": true, + "env": { + "browser": true, + "es2020": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "settings": { + "react": { + "version": "detect" + } + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 11, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "no-cond-assign": ["error", "always"], + "no-console": ["warn", {"allow": ["info", "warn", "error"]}], + "no-constant-condition": "error", + "no-debugger": "error", + "no-dupe-else-if": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty": "warn", + "no-empty-character-class": "error", + "no-extra-boolean-cast": "warn", + "no-extra-parens": "off", + "@typescript-eslint/no-extra-parens": ["warn", "all", { "ignoreJSX": "multi-line" }], + "no-extra-semi": "warn", + "no-func-assign": "warn", + "no-import-assign": "warn", + "no-inner-declarations": ["warn", "both"], + "no-invalid-regexp": "error", + "no-irregular-whitespace": ["warn", { + "skipRegExps": true, + "skipTemplates": true + }], + "no-loss-of-precision": "warn", + "no-misleading-character-class": "warn", + "no-obj-calls": "warn", + "no-prototype-builtins": "error", + "no-sparse-arrays": "error", + "no-template-curly-in-string": "warn", + "no-unexpected-multiline": "warn", + "no-unreachable": "error", + "no-unreachable-loop": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "use-isnan": "warn", + "valid-typeof": "error", + + "curly": ["warn", "multi", "consistent"], + "no-empty-function": "warn", + + "array-bracket-newline": ["warn", { "multiline": true }], + "array-bracket-spacing": ["warn", "always"], + "array-element-newline": ["warn", { "multiline": true, "minItems": 3 }], + "block-spacing": "warn", + "brace-style": ["warn", "1tbs", { "allowSingleLine": true }], + "capitalized-comments": "warn", + "camelcase": "off", + "comma-dangle": ["warn", "never"], + "comma-spacing": ["warn", { "before": false, "after": true }], + "comma-style": ["warn", "last"], + "computed-property-spacing": "warn", + "eol-last": ["warn", "always"], + "func-call-spacing": ["error", "never"], + "func-names": ["error", "always"], + "func-style": ["error", "declaration", { "allowArrowFunctions": true }], + "function-call-argument-newline": ["warn", "consistent"], + "function-paren-newline": ["warn", "multiline"], + "id-length": ["warn", { "min": 3, "exceptions": ["id", "_"] }], + "implicit-arrow-linebreak": ["warn", "beside"], + "indent": ["warn", 2, { + "SwitchCase": 1, + "VariableDeclarator": "first", + "MemberExpression": 1, + "FunctionDeclaration": {"parameters": "first"}, + "FunctionExpression": {"parameters": "first"}, + "CallExpression": {"arguments": "first"}, + "ArrayExpression": "first", + "ObjectExpression": "first", + "ImportDeclaration": "first", + "flatTernaryExpressions": false, + "offsetTernaryExpressions": true, + "ignoreComments": false + }], + "jsx-quotes": ["warn", "prefer-double"], + "key-spacing": ["warn", { + "beforeColon": false, + "afterColon": true, + "mode": "strict" , + "align": "value" + }], + "keyword-spacing": "warn", + "linebreak-style": ["warn", "unix"], + "lines-around-comment": ["warn", { + "beforeBlockComment": true, + "afterBlockComment": true, + "beforeLineComment": true, + "afterLineComment": false + }], + "lines-between-class-members": ["warn", "always"], + "max-depth": ["warn", 4], + "max-len": ["warn", { "code": 85 }], + "max-lines-per-function": ["warn", { + "max": 100, + "skipBlankLines": true, + "skipComments": true + }], + "max-nested-callbacks": ["warn", 3], + "max-params": ["warn", 6], + "max-statements-per-line": ["warn", { "max": 2 }], + "multiline-comment-style": ["warn", "bare-block"], + "multiline-ternary": ["warn", "always-multiline"], + "newline-per-chained-call": ["warn", { "ignoreChainWithDepth": 3 }], + "no-lonely-if": "warn", + "no-mixed-spaces-and-tabs": "warn", + "no-multi-assign": "warn", + "no-multiple-empty-lines": ["warn", { "max": 1 }], + "no-negated-condition": "warn", + "no-nested-ternary": "warn", + "no-new-object": "error", + "no-tabs": "warn", + "no-trailing-spaces": "warn", + "no-unneeded-ternary": "warn", + "no-whitespace-before-property": "warn", + "nonblock-statement-body-position": ["warn", "below"], + "object-curly-newline": ["warn", { + "ObjectExpression": { "multiline": true, "minProperties": 4 }, + "ObjectPattern": { "multiline": true, "minProperties": 4 }, + "ImportDeclaration": { "multiline": true, "minProperties": 4 }, + "ExportDeclaration": { "multiline": true, "minProperties": 4 } + }], + "object-curly-spacing": ["warn", "always"], + "object-property-newline": "warn", + "one-var": ["warn", { "initialized": "never" }], + "one-var-declaration-per-line": ["warn", "initializations"], + "operator-assignment": ["warn", "always"], + "operator-linebreak": ["warn", "before"], + "padded-blocks": ["warn", "never", { "allowSingleLineBlocks": true } ], + "prefer-exponentiation-operator": "warn", + "prefer-object-spread": "warn", + "quote-props": ["warn", "as-needed"], + "quotes": ["warn", "double"], + "semi": ["warn", "always"], + "semi-spacing": ["warn", {"before": false, "after": true}], + "semi-style": ["warn", "last"], + "space-before-blocks": "warn", + "space-before-function-paren": ["warn", {"anonymous": "always", "named": "never", "asyncArrow": "always"}], + "space-in-parens": ["warn", "never"], + "space-infix-ops": "warn", + "space-unary-ops": [ "warn", {"words": true, "nonwords": false}], + "spaced-comment": ["warn", "never"], + "switch-colon-spacing": "warn", + "template-tag-spacing": "warn", + "wrap-regex": "warn", + + "arrow-body-style": ["warn", "as-needed"], + "arrow-parens": ["warn", "always"], + "arrow-spacing": "warn", + "constructor-super": "error", + "generator-star-spacing": ["warn", "before"], + "no-class-assign": "error", + "no-confusing-arrow": "warn", + "no-const-assign": "error", + "no-duplicate-imports": ["error", { "includeExports": true }], + "no-new-symbol": "error", + "no-useless-computed-key": "warn", + "no-useless-constructor": "error", + "no-useless-rename": "warn", + "no-var": "warn", + "prefer-arrow-callback": "warn", + "prefer-const": "warn", + "prefer-numeric-literals": "warn", + "prefer-rest-params": "error", + "prefer-spread": "warn", + "prefer-template": "warn", + "require-yield": "error", + "rest-spread-spacing": ["warn", "never"], + "symbol-description": "error", + "template-curly-spacing": "warn", + "yield-star-spacing": ["warn", "before"], + + "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }] + } +} diff --git a/semana20/lama/.gitignore b/semana20/lama/.gitignore new file mode 100644 index 0000000..853f700 --- /dev/null +++ b/semana20/lama/.gitignore @@ -0,0 +1,5 @@ +node_module +build +.env +package-lock.json +yarn.lock diff --git a/semana20/lama/jest.config.js b/semana20/lama/jest.config.js new file mode 100644 index 0000000..ae7f8c0 --- /dev/null +++ b/semana20/lama/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + roots: ["/tests"], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], +}; diff --git a/semana20/lama/nodemon.json b/semana20/lama/nodemon.json new file mode 100644 index 0000000..6a88ea1 --- /dev/null +++ b/semana20/lama/nodemon.json @@ -0,0 +1,6 @@ +{ + "verbose": true, + "ignore": ["build", "node_modules"], + "ext": "ts,yml", + "watch": ["src"] +} diff --git a/semana20/lama/package.json b/semana20/lama/package.json new file mode 100644 index 0000000..fa03698 --- /dev/null +++ b/semana20/lama/package.json @@ -0,0 +1,41 @@ +{ + "name": "aula58", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "tsc && node build/index.js", + "lint": "eslint --fix ./src", + "test": "jest", + "dev": "nodemon src/index.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "bcryptjs": "^2.4.3", + "cors": "^2.8.5", + "dotenv": "^10.0.0", + "express": "^4.17.1", + "jest": "^27.0.6", + "jsonwebtoken": "^8.5.1", + "knex": "^0.95.7", + "mysql": "^2.18.1", + "swagger-ui-express": "^4.1.6", + "ts-jest": "^27.0.5", + "typescript": "^4.3.5", + "uuid": "^8.3.2", + "yaml": "^1.10.2", + "yup": "^0.32.9" + }, + "devDependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/cors": "^2.8.12", + "@types/express": "^4.17.13", + "@types/jsonwebtoken": "^8.5.4", + "@types/node": "^16.6.1", + "@types/swagger-ui-express": "^4.1.3", + "@types/uuid": "^8.3.1", + "@typescript-eslint/eslint-plugin": "^4.29.2" + } +} diff --git a/semana20/lama/src/@types/commons.ts b/semana20/lama/src/@types/commons.ts new file mode 100644 index 0000000..14f87cd --- /dev/null +++ b/semana20/lama/src/@types/commons.ts @@ -0,0 +1,11 @@ +export type ID = string; + +export type Token = string; + +export interface ApplicationErrorInterface { + initialError: any; //eslint-disable-line + name: string; + message: string; + httpStatus: number; + getMessage: () => string; +} diff --git a/semana20/lama/src/@types/index.ts b/semana20/lama/src/@types/index.ts new file mode 100644 index 0000000..ff0cdaf --- /dev/null +++ b/semana20/lama/src/@types/index.ts @@ -0,0 +1,7 @@ +export * from "./commons"; + +//Veja https://knexjs.org/#typescript-support +declare module "knex/types/tables" { + interface Tables { + } +} diff --git a/semana20/lama/src/business/index.ts b/semana20/lama/src/business/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/semana20/lama/src/commons/id.ts b/semana20/lama/src/commons/id.ts new file mode 100644 index 0000000..ac5e0e9 --- /dev/null +++ b/semana20/lama/src/commons/id.ts @@ -0,0 +1,6 @@ +import { v1 as uuidV1 } from "uuid"; +import { ID } from "../@types"; + +export function generateId(): ID { + return uuidV1(); +} diff --git a/semana20/lama/src/commons/index.ts b/semana20/lama/src/commons/index.ts new file mode 100644 index 0000000..b04816c --- /dev/null +++ b/semana20/lama/src/commons/index.ts @@ -0,0 +1,3 @@ +export * from "./token"; +export * from "./password"; +export * from "./id"; diff --git a/semana20/lama/src/commons/password.ts b/semana20/lama/src/commons/password.ts new file mode 100644 index 0000000..98b224f --- /dev/null +++ b/semana20/lama/src/commons/password.ts @@ -0,0 +1,12 @@ +import * as bcrypt from "bcryptjs"; + +export async function encryptPassword(password: string): Promise { + const rounds = Number(process.env.CRYPTO_ROUNDS); + const salt = await bcrypt.genSalt(rounds); + return await bcrypt.hash(password, salt); +} + +export async function comparePassword(plainPassword: string, hashPassword: string) +: Promise { + return await bcrypt.compare(plainPassword, hashPassword); +} diff --git a/semana20/lama/src/commons/token.ts b/semana20/lama/src/commons/token.ts new file mode 100644 index 0000000..8e998b1 --- /dev/null +++ b/semana20/lama/src/commons/token.ts @@ -0,0 +1,26 @@ +import * as jwt from "jsonwebtoken"; +import { Token } from "../@types"; + +export function generateToken(payload: unknown): Token { + return jwt.sign( + payload as Buffer, + process.env.TOKEN_SECRET_KEY as string, + { expiresIn: process.env.TOKEN_DURATION } + ); +} + +/* +Export function generateUserToken(userTokenData: UserTokenData): Token { + return generateToken(userTokenData); +} + +export async function getUserToken(token: Token): Promise { + try { + const result = jwt.verify(token, process.env.TOKEN_SECRET_KEY as string); + await validate(UserTokenDataSchema, result); + return result as UserTokenData; + } catch (error) { + throw applicationError(errorName.InvalidToken, error); + } +} +*/ diff --git a/semana20/lama/src/data/databaseSQL/index.ts b/semana20/lama/src/data/databaseSQL/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/semana20/lama/src/data/index.ts b/semana20/lama/src/data/index.ts new file mode 100644 index 0000000..4174232 --- /dev/null +++ b/semana20/lama/src/data/index.ts @@ -0,0 +1,15 @@ +import knex from "knex"; + +export * from "./databaseSQL"; + +export const databaseConnection = knex({ + client: process.env.DATABASE_TYPE, + connection: { + host: process.env.DATABASE_HOST, + port: Number(process.env.DATABASE_PORT), + database: process.env.DATABASE_SCHEMA, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + multipleStatements: true + } +}); diff --git a/semana20/lama/src/docs/swagger.yml b/semana20/lama/src/docs/swagger.yml new file mode 100644 index 0000000..071bab8 --- /dev/null +++ b/semana20/lama/src/docs/swagger.yml @@ -0,0 +1,100 @@ +openapi: 3.0.0 +info: + title: LaBook + description: Descrição de como o backend da rede social LaBook funciona + version: 0.0.1 + +servers: + - url: http://localhost:3000 + description: URL padrão para desenvolvimento + +tags: + - name: tag + description: + +security: + - TokenAuth: [] + +paths: + /: + post: + summary: + description: + tags: + - tag + requestBody: + required: true + content: + application/json: + schema: + example: + responses: + '200': + description: + content: + application/json: + schema: + example: + '400': + description: + content: + application/json: + schema: + $ref: '#/components/schemas/ValidateError' + example: + error: + name: Validate + message: A validation error has occurred + errors: [] + '401': + $ref: '#/components/responses/InvalidToken' + '500': + $ref: '#/components/responses/Unexpected' + +components: + schemas: + Error: + type: object + properties: + error: + type: object + properties: + name: + type: string + message: + type: string + ValidateError: + type: object + properties: + error: + type: object + properties: + name: + type: string + message: + type: string + securitySchemes: + TokenAuth: + type: http + scheme: bearer + responses: + Unexpected: + description: Mensagem de erro que informa que ocorreu um erro inesperado no servidor + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: + name: Unexpect + message: An unexpected error has occurred + InvalidToken: + description: Mensagem de erro que informa que foi enviado um token invalido para a aplicação + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: + name: InvalidToken + message: Invalid authorization token diff --git a/semana20/lama/src/env.ts b/semana20/lama/src/env.ts new file mode 100644 index 0000000..95d68e3 --- /dev/null +++ b/semana20/lama/src/env.ts @@ -0,0 +1,31 @@ +import dotenv from "dotenv"; + +function validateEnvironment() { + const requiredsEnvironmentVariable = [ + "NODE_PORT", + "TOKEN_SECRET_KEY", + "TOKEN_DURATION", + "CRYPTO_ROUNDS", + "DATABASE_TYPE", + "DATABASE_HOST", + "DATABASE_PORT", + "DATABASE_SCHEMA", + "DATABASE_USER", + "DATABASE_PASSWORD", + "DOCS_PATH" + ]; + + const missingVariables = []; + + for (const varible of requiredsEnvironmentVariable) + if (!process.env[varible]) + missingVariables.push(varible); + + if (missingVariables.length) + //eslint-disable-next-line max-len + throw new Error(`The following envioroment varibles are requireds:\n\t${missingVariables.join("\n\t")}`); +} + +dotenv.config(); + +validateEnvironment(); diff --git a/semana20/lama/src/errors/commons.ts b/semana20/lama/src/errors/commons.ts new file mode 100644 index 0000000..155a39e --- /dev/null +++ b/semana20/lama/src/errors/commons.ts @@ -0,0 +1,45 @@ +import { ApplicationErrorInterface } from "../@types"; +import { ErrorName, errorNames, errors } from "./error"; + +export class ApplicationError implements ApplicationErrorInterface { + name: string; + + message: string; + + httpStatus: number; + + initialError: any; //eslint-disable-line + + constructor( + name: string, + message: string, + httpStatus?: number, + initialError?: any //eslint-disable-line + ) { + this.name = name; + this.message = message; + this.httpStatus = httpStatus || 500; + this.initialError = initialError || "No initial error"; + } + + getMessage(): string { + return `${this.name}: ${this.message}`; + } +} + +export function applicationError(errorName: string, initialError?: unknown) +: ApplicationError { + if (initialError instanceof ApplicationError) + initialError = initialError.initialError; + + const error = errorNames.includes(errorName) + ? errors[errorName as ErrorName] + : errors.Unexpected; + + return new ApplicationError( + error.name, + error.message, + error.httpStatus, + initialError + ); +} diff --git a/semana20/lama/src/errors/error.ts b/semana20/lama/src/errors/error.ts new file mode 100644 index 0000000..3668905 --- /dev/null +++ b/semana20/lama/src/errors/error.ts @@ -0,0 +1,48 @@ +export const errorName = { + Unexpected: "Unexpect", + Validate: "Validate", + InvalidPassword: "InvalidPassword", + PostNotFound: "PostNotFound", + InvalidToken: "InvalidToken" +}; + +export type ErrorName = keyof typeof errorName; + +export const errorNames = Object.keys(errorName); + +type Error = { + [key in ErrorName]: { + name: string, + message: string, + httpStatus: number + } +} + +export const errors: Error = { + Unexpected: { + name: errorName.Unexpected, + message: "An unexpected error has occurred", + httpStatus: 500 + }, + Validate: { + name: errorName.Validate, + message: "A validation error has occurred", + httpStatus: 400 + }, + InvalidPassword: { + name: errorName.InvalidPassword, + message: "Invalid password", + httpStatus: 401 + }, + PostNotFound: { + name: errorName.PostNotFound, + message: "Post not found", + httpStatus: 404 + }, + InvalidToken: { + name: errorName.InvalidToken, + message: "Invalid authorization token", + httpStatus: 401 + } +}; + diff --git a/semana20/lama/src/errors/index.ts b/semana20/lama/src/errors/index.ts new file mode 100644 index 0000000..e09a495 --- /dev/null +++ b/semana20/lama/src/errors/index.ts @@ -0,0 +1,3 @@ +export * from "./commons"; +export * from "./error"; +export * from "./send"; diff --git a/semana20/lama/src/errors/send.ts b/semana20/lama/src/errors/send.ts new file mode 100644 index 0000000..98c2ef9 --- /dev/null +++ b/semana20/lama/src/errors/send.ts @@ -0,0 +1,31 @@ +import { Response } from "express"; +import { applicationError } from "./commons"; +import { errorName } from "./error"; + +//eslint-disable-next-line +export function sendError(response: Response, error: any, httpStatus?: number) +: void { + const finalError = applicationError(error.name, error); + if (finalError.name === errorName.Unexpected) + console.error(error); + + if (finalError.name === errorName.Validate + && Array.isArray(finalError.initialError.errors)) { + response.status(httpStatus || finalError.httpStatus).send({ + error: { + name: finalError.name, + message: finalError.message, + errors: finalError.initialError.errors + } + }); + return; + } + + response.status(httpStatus || finalError.httpStatus).send({ + error: { + name: finalError.name, + message: finalError.message + } + }); +} + diff --git a/semana20/lama/src/handlers/index.ts b/semana20/lama/src/handlers/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/semana20/lama/src/handlers/middleware.ts b/semana20/lama/src/handlers/middleware.ts new file mode 100644 index 0000000..0942230 --- /dev/null +++ b/semana20/lama/src/handlers/middleware.ts @@ -0,0 +1,25 @@ +import { NextFunction, Request, Response } from "express"; +import { applicationError, errorName, sendError } from "../errors"; + +export async function isLogin( + request: Request, + response: Response, + next: NextFunction +): Promise { + try { + const { authorization = "" } = request.headers; + + const tokenSplit = authorization.split(" "); + if (tokenSplit.length !== 2 || tokenSplit[0] !== "Bearer") + throw applicationError(errorName.InvalidToken); + + const token = { id: "0000" }; //Await getUserToken(tokenSplit[1]); + + response.locals.userID = token.id; + + next(); + } catch (error) { + sendError(response, error); + } +} + diff --git a/semana20/lama/src/index.ts b/semana20/lama/src/index.ts new file mode 100644 index 0000000..9284f16 --- /dev/null +++ b/semana20/lama/src/index.ts @@ -0,0 +1,24 @@ +import "./env"; +import express from "express"; +import cors from "cors"; +import swaggerUi from "swagger-ui-express"; +import files from "fs"; +import yaml from "yaml"; + +const docs = yaml.parse(files.readFileSync(process.env.DOCS_PATH as string, "utf8")); + +const serverPort = process.env.PORT || process.env.NODE_PORT || 3003; + +export const server = express(); +server.use(express.json()); +server.use(cors()); +server.use("/docs", swaggerUi.serve, swaggerUi.setup(docs)); + +const serverListener = server.listen(serverPort, () => { + if (serverListener) + console.info(`Server is running in http://localhost:${serverPort}`); + else + console.error("Failure upon starting server."); +}); + +import "./routes"; diff --git a/semana20/lama/src/queries.sql b/semana20/lama/src/queries.sql new file mode 100644 index 0000000..81d9afe --- /dev/null +++ b/semana20/lama/src/queries.sql @@ -0,0 +1,3 @@ + +SHOW TABLES; + diff --git a/semana20/lama/src/routes.ts b/semana20/lama/src/routes.ts new file mode 100644 index 0000000..1257b5e --- /dev/null +++ b/semana20/lama/src/routes.ts @@ -0,0 +1,7 @@ +import { Request, Response } from "express"; +import { server } from "."; + +//Routes for test +server.get("/ping", (_request: Request, response: Response): void => { + response.send("pong"); +}); diff --git a/semana20/lama/src/validate/index.ts b/semana20/lama/src/validate/index.ts new file mode 100644 index 0000000..8d94eff --- /dev/null +++ b/semana20/lama/src/validate/index.ts @@ -0,0 +1,18 @@ +import { AnySchema } from "yup"; +import { applicationError, errorName } from "../errors"; + +export * from "./user"; +export * from "./post"; +export * from "./comment"; + +export async function validate(schema: AnySchema, data: unknown): Promise { + try { + await schema.validate(data, { abortEarly: false }); + } catch (error) { + if (error.name === "ValidationError") + throw applicationError(errorName.Validate, error); + + throw applicationError(errorName.Unexpected, error); + } +} + diff --git a/semana20/lama/tsconfig.json b/semana20/lama/tsconfig.json new file mode 100644 index 0000000..3befd18 --- /dev/null +++ b/semana20/lama/tsconfig.json @@ -0,0 +1,74 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./build", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ + // "nPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + "typeRoots": ["./src/@types"], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + "resolveJsonModule": true + }, + "exclude": ["tests"] +}