├── www └── api │ ├── .prettierignore │ ├── src │ ├── models │ │ ├── index.ts │ │ ├── README.md │ │ └── product.model.ts │ ├── datasources │ │ ├── index.ts │ │ ├── README.md │ │ └── mysql.datasource.ts │ ├── repositories │ │ ├── index.ts │ │ ├── README.md │ │ └── product.repository.ts │ ├── __tests__ │ │ ├── README.md │ │ └── acceptance │ │ │ ├── ping.controller.acceptance.ts │ │ │ ├── test-helper.ts │ │ │ └── home-page.acceptance.ts │ ├── controllers │ │ ├── index.ts │ │ ├── README.md │ │ ├── ping.controller.ts │ │ └── product.controller.ts │ ├── sequence.ts │ ├── migrate.ts │ ├── openapi-spec.ts │ ├── index.ts │ └── application.ts │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .mocharc.json │ ├── .yo-rc.json │ ├── .dockerignore │ ├── .prettierrc │ ├── tsconfig.json │ ├── Dockerfile │ ├── .vscode │ ├── tasks.json │ ├── settings.json │ └── launch.json │ ├── .gitignore │ ├── DEVELOPING.md │ ├── README.md │ ├── public │ └── index.html │ └── package.json ├── docker ├── loopback │ ├── ssh.sh │ ├── docker.env │ ├── build.sh │ ├── Dockerfile │ ├── start.sh │ └── pm2 │ │ ├── pm2-development.json │ │ └── pm2-production.json ├── mysql │ ├── ssh.sh │ ├── Dockerfile │ └── build.sh ├── dev-build.sh ├── dev-up.sh └── dev-init.sh ├── README.md ├── docker-compose.yml ├── .gitignore ├── LICENSE └── docs ├── docker.md └── api.md /www/api/.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | *.json 3 | -------------------------------------------------------------------------------- /www/api/src/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './product.model'; 2 | -------------------------------------------------------------------------------- /www/api/src/datasources/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mysql.datasource'; 2 | -------------------------------------------------------------------------------- /www/api/src/repositories/index.ts: -------------------------------------------------------------------------------- 1 | export * from './product.repository'; 2 | -------------------------------------------------------------------------------- /www/api/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | coverage/ 4 | .eslintrc.js 5 | -------------------------------------------------------------------------------- /www/api/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@loopback/eslint-config', 3 | }; 4 | -------------------------------------------------------------------------------- /www/api/src/__tests__/README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | Please place your tests in this folder. 4 | -------------------------------------------------------------------------------- /docker/loopback/ssh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bash -c "clear && docker exec -it cursoaws_api bash" 4 | -------------------------------------------------------------------------------- /docker/mysql/ssh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bash -c "clear && docker exec -it cursoaws_mysql bash" 4 | -------------------------------------------------------------------------------- /www/api/src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ping.controller'; 2 | export * from './product.controller'; 3 | -------------------------------------------------------------------------------- /www/api/src/models/README.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | This directory contains code for models provided by this app. 4 | -------------------------------------------------------------------------------- /www/api/.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "exit": true, 3 | "recursive": true, 4 | "require": "source-map-support/register" 5 | } 6 | -------------------------------------------------------------------------------- /www/api/.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "@loopback/cli": { 3 | "packageManager": "npm", 4 | "version": "2.20.2" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /www/api/src/datasources/README.md: -------------------------------------------------------------------------------- 1 | # Datasources 2 | 3 | This directory contains config for datasources used by this app. 4 | -------------------------------------------------------------------------------- /www/api/src/repositories/README.md: -------------------------------------------------------------------------------- 1 | # Repositories 2 | 3 | This directory contains code for repositories provided by this app. 4 | -------------------------------------------------------------------------------- /www/api/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | /dist 4 | # Cache used by TypeScript's incremental build 5 | *.tsbuildinfo 6 | -------------------------------------------------------------------------------- /docker/dev-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Databases 4 | ./docker/mysql/build.sh 5 | 6 | # APIs 7 | ./docker/loopback/build.sh 8 | -------------------------------------------------------------------------------- /www/api/src/sequence.ts: -------------------------------------------------------------------------------- 1 | import {MiddlewareSequence} from '@loopback/rest'; 2 | 3 | export class MySequence extends MiddlewareSequence {} 4 | -------------------------------------------------------------------------------- /www/api/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": false, 3 | "singleQuote": true, 4 | "printWidth": 80, 5 | "trailingComma": "all", 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /docker/dev-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Start up Docker for Dev Environment 4 | docker-compose up 5 | 6 | # Start up Docker for Dev Environment in Daemon MODE 7 | #docker-compose up -d 8 | -------------------------------------------------------------------------------- /docker/mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | # our base image 2 | FROM mysql:5.7.28 3 | 4 | # specify the port number the container should expose 5 | EXPOSE 3306 6 | 7 | USER root 8 | RUN apt-get update -y 9 | RUN apt-get install -y apt-utils 10 | -------------------------------------------------------------------------------- /docker/loopback/docker.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | INSTANCE=development 3 | 4 | HOST=0.0.0.0 5 | PORT=3001 6 | 7 | MYSQL_HOST=mysql.dev.docker 8 | MYSQL_PORT=3306 9 | MYSQL_USER=root 10 | MYSQL_PASSWORD=root 11 | MYSQL_DATABASE=dev_cursoaws 12 | -------------------------------------------------------------------------------- /www/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "@loopback/build/config/tsconfig.common.json", 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /docker/loopback/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Remove Old Image 4 | docker rm -f cursoaws_api 5 | 6 | # No Cache Build 7 | docker build --no-cache -t cursoaws_api -f docker/loopback/Dockerfile . 8 | 9 | # Cache Build 10 | #docker build -t cursoaws_api -f docker/loopback/Dockerfile . 11 | -------------------------------------------------------------------------------- /docker/mysql/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Remove Old Image 4 | docker rm -f cursoaws_mysql 5 | 6 | # No Cache Build 7 | docker build --no-cache -t cursoaws_mysql -f docker/mysql/Dockerfile . 8 | 9 | # Cache Build 10 | #docker build -t cursoaws_mysql -f docker/mysql/Dockerfile . 11 | -------------------------------------------------------------------------------- /docker/dev-init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Install NPM dependencies 4 | echo "Installing API dependencies..." 5 | cd www/api/ 6 | npm i 7 | 8 | # Build Docker images 9 | echo "Building Docker Images..." 10 | cd ../../ 11 | ./docker/dev-build.sh 12 | 13 | echo "Starting up Docker Containers..." 14 | ./docker/dev-up.sh 15 | -------------------------------------------------------------------------------- /www/api/src/controllers/README.md: -------------------------------------------------------------------------------- 1 | # Controllers 2 | 3 | This directory contains source files for the controllers exported by this app. 4 | 5 | To add a new empty controller, type in `lb4 controller []` from the 6 | command-line of your application's root directory. 7 | 8 | For more information, please visit 9 | [Controller generator](http://loopback.io/doc/en/lb4/Controller-generator.html). 10 | -------------------------------------------------------------------------------- /docker/loopback/Dockerfile: -------------------------------------------------------------------------------- 1 | # our base image 2 | FROM node:14 3 | 4 | # specify the port number the container should expose 5 | EXPOSE 3001 6 | 7 | # User user as root 8 | USER root 9 | 10 | # Create App 11 | RUN mkdir /app 12 | 13 | # Update Linux Packages 14 | RUN apt-get update && apt-get upgrade -y 15 | RUN apt-get install mysql-client -y 16 | 17 | # Run update and Strongloop install 18 | RUN npm install -g npm 19 | RUN npm install -g pm2 20 | RUN pm2 install pm2-logrotate 21 | -------------------------------------------------------------------------------- /www/api/src/repositories/product.repository.ts: -------------------------------------------------------------------------------- 1 | import {inject} from '@loopback/core'; 2 | import {DefaultCrudRepository} from '@loopback/repository'; 3 | import {MysqlDataSource} from '../datasources'; 4 | import {Product, ProductRelations} from '../models'; 5 | 6 | export class ProductRepository extends DefaultCrudRepository< 7 | Product, 8 | typeof Product.prototype.id, 9 | ProductRelations 10 | > { 11 | constructor( 12 | @inject('datasources.mysql') dataSource: MysqlDataSource, 13 | ) { 14 | super(Product, dataSource); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curso AWS Prático 2 | 3 | Este repositório é o resultado da aula 5 do curso de AWS na Prática do canal [Um Inventor Qualquer](https://www.youtube.com/c/UmInventorQualquer) 4 | no YouTube. 5 | 6 | Para aprender como executar esse ambiente em seu computador, acesse a documentação do [Docker](docs/docker.md). 7 | 8 | ## Documentação 9 | - [Docker](docs/docker.md) 10 | - [API](docs/api.md) 11 | 12 | ## Criando uma API em 90 segundos 13 | Assista nosso vídeo no YouTube para ver passo a passo como utilizar esse repositório. 14 | 15 | [Criando uma API em 90 segundos](https://youtu.be/bU4M9tZhsTs) 16 | -------------------------------------------------------------------------------- /www/api/src/__tests__/acceptance/ping.controller.acceptance.ts: -------------------------------------------------------------------------------- 1 | import {Client, expect} from '@loopback/testlab'; 2 | import {ApiApplication} from '../..'; 3 | import {setupApplication} from './test-helper'; 4 | 5 | describe('PingController', () => { 6 | let app: ApiApplication; 7 | let client: Client; 8 | 9 | before('setupApplication', async () => { 10 | ({app, client} = await setupApplication()); 11 | }); 12 | 13 | after(async () => { 14 | await app.stop(); 15 | }); 16 | 17 | it('invokes GET /ping', async () => { 18 | const res = await client.get('/ping?msg=world').expect(200); 19 | expect(res.body).to.containEql({greeting: 'Hello from LoopBack'}); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /www/api/src/migrate.ts: -------------------------------------------------------------------------------- 1 | import {ApiApplication} from './application'; 2 | 3 | export async function migrate(args: string[]) { 4 | const existingSchema = args.includes('--rebuild') ? 'drop' : 'alter'; 5 | console.log('Migrating schemas (%s existing schema)', existingSchema); 6 | 7 | const app = new ApiApplication(); 8 | await app.boot(); 9 | await app.migrateSchema({existingSchema}); 10 | 11 | // Connectors usually keep a pool of opened connections, 12 | // this keeps the process running even after all work is done. 13 | // We need to exit explicitly. 14 | process.exit(0); 15 | } 16 | 17 | migrate(process.argv).catch(err => { 18 | console.error('Cannot migrate database schema', err); 19 | process.exit(1); 20 | }); 21 | -------------------------------------------------------------------------------- /docker/loopback/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 'Checking up MySQL...' 4 | until mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -h $MYSQL_HOST -e ";" ; do 5 | echo 'Waiting MySQL...' 6 | sleep 5 7 | done 8 | 9 | DIR="/app/www/api/dist" 10 | if [[ ! -e $DIR ]]; then 11 | cd /app/www/api/ && npm run rebuild 12 | fi 13 | 14 | echo "Migrating DB..." 15 | cd /app/www/api/dist/ && node migrate.js 16 | 17 | echo 'Starting up API...' 18 | if [ "$NODE_ENV" == "development" ] 19 | then 20 | echo "Development MODE" 21 | pm2 start /app/docker/loopback/pm2/pm2-development.json 22 | else 23 | echo "Production MODE" 24 | pm2 start /app/docker/loopback/pm2/pm2-production.json 25 | fi 26 | 27 | # Keep Container Running 28 | tail -f /dev/null 29 | -------------------------------------------------------------------------------- /www/api/src/openapi-spec.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationConfig} from '@loopback/core'; 2 | import {ApiApplication} from './application'; 3 | 4 | /** 5 | * Export the OpenAPI spec from the application 6 | */ 7 | async function exportOpenApiSpec(): Promise { 8 | const config: ApplicationConfig = { 9 | rest: { 10 | port: +(process.env.PORT ?? 3000), 11 | host: process.env.HOST ?? 'localhost', 12 | }, 13 | }; 14 | const outFile = process.argv[2] ?? ''; 15 | const app = new ApiApplication(config); 16 | await app.boot(); 17 | await app.exportOpenApiSpec(outFile); 18 | } 19 | 20 | exportOpenApiSpec().catch(err => { 21 | console.error('Fail to export OpenAPI spec from the application.', err); 22 | process.exit(1); 23 | }); 24 | -------------------------------------------------------------------------------- /www/api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Check out https://hub.docker.com/_/node to select a new base image 2 | FROM node:10-slim 3 | 4 | # Set to a non-root built-in user `node` 5 | USER node 6 | 7 | # Create app directory (with user `node`) 8 | RUN mkdir -p /home/node/app 9 | 10 | WORKDIR /home/node/app 11 | 12 | # Install app dependencies 13 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 14 | # where available (npm@5+) 15 | COPY --chown=node package*.json ./ 16 | 17 | RUN npm install 18 | 19 | # Bundle app source code 20 | COPY --chown=node . . 21 | 22 | RUN npm run build 23 | 24 | # Bind to all network interfaces so that it can be mapped to the host OS 25 | ENV HOST=0.0.0.0 PORT=3000 26 | 27 | EXPOSE ${PORT} 28 | CMD [ "node", "." ] 29 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | 4 | api.dev.docker: 5 | container_name: "cursoaws_api" 6 | image: cursoaws_api 7 | user: root 8 | working_dir: /app/www/ 9 | environment: 10 | - NODE_ENV=development 11 | volumes: 12 | - ./:/app/ 13 | expose: 14 | - 3001 15 | ports: 16 | - 3001:3001 17 | env_file: 18 | - docker/loopback/docker.env 19 | command: "/./app/docker/loopback/start.sh" 20 | 21 | mysql.dev.docker: 22 | container_name: "cursoaws_mysql" 23 | image: cursoaws_mysql 24 | user: root 25 | environment: 26 | MYSQL_ROOT_PASSWORD: root 27 | MYSQL_DATABASE: dev_cursoaws 28 | volumes: 29 | - ./:/app/ 30 | expose: 31 | - 3306 32 | ports: 33 | - 3306:3306 34 | 35 | 36 | -------------------------------------------------------------------------------- /www/api/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Watch and Compile Project", 8 | "type": "shell", 9 | "command": "npm", 10 | "args": ["--silent", "run", "build:watch"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "problemMatcher": "$tsc-watch" 16 | }, 17 | { 18 | "label": "Build, Test and Lint", 19 | "type": "shell", 20 | "command": "npm", 21 | "args": ["--silent", "run", "test:dev"], 22 | "group": { 23 | "kind": "test", 24 | "isDefault": true 25 | }, 26 | "problemMatcher": ["$tsc", "$eslint-compact", "$eslint-stylish"] 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /www/api/src/__tests__/acceptance/test-helper.ts: -------------------------------------------------------------------------------- 1 | import {ApiApplication} from '../..'; 2 | import { 3 | createRestAppClient, 4 | givenHttpServerConfig, 5 | Client, 6 | } from '@loopback/testlab'; 7 | 8 | export async function setupApplication(): Promise { 9 | const restConfig = givenHttpServerConfig({ 10 | // Customize the server configuration here. 11 | // Empty values (undefined, '') will be ignored by the helper. 12 | // 13 | // host: process.env.HOST, 14 | // port: +process.env.PORT, 15 | }); 16 | 17 | const app = new ApiApplication({ 18 | rest: restConfig, 19 | }); 20 | 21 | await app.boot(); 22 | await app.start(); 23 | 24 | const client = createRestAppClient(app); 25 | 26 | return {app, client}; 27 | } 28 | 29 | export interface AppWithClient { 30 | app: ApiApplication; 31 | client: Client; 32 | } 33 | -------------------------------------------------------------------------------- /www/api/src/__tests__/acceptance/home-page.acceptance.ts: -------------------------------------------------------------------------------- 1 | import {Client} from '@loopback/testlab'; 2 | import {ApiApplication} from '../..'; 3 | import {setupApplication} from './test-helper'; 4 | 5 | describe('HomePage', () => { 6 | let app: ApiApplication; 7 | let client: Client; 8 | 9 | before('setupApplication', async () => { 10 | ({app, client} = await setupApplication()); 11 | }); 12 | 13 | after(async () => { 14 | await app.stop(); 15 | }); 16 | 17 | it('exposes a default home page', async () => { 18 | await client 19 | .get('/') 20 | .expect(200) 21 | .expect('Content-Type', /text\/html/); 22 | }); 23 | 24 | it('exposes self-hosted explorer', async () => { 25 | await client 26 | .get('/explorer/') 27 | .expect(200) 28 | .expect('Content-Type', /text\/html/) 29 | .expect(/LoopBack API Explorer/); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /www/api/src/models/product.model.ts: -------------------------------------------------------------------------------- 1 | import {Entity, model, property} from '@loopback/repository'; 2 | 3 | @model() 4 | export class Product extends Entity { 5 | @property({ 6 | type: 'number', 7 | id: true, 8 | generated: true, 9 | }) 10 | id?: number; 11 | 12 | @property({ 13 | type: 'string', 14 | required: true, 15 | }) 16 | name: string; 17 | 18 | @property({ 19 | type: 'string', 20 | required: true, 21 | }) 22 | category: string; 23 | 24 | @property({ 25 | type: 'number', 26 | default: 0, 27 | }) 28 | cost?: number; 29 | 30 | @property({ 31 | type: 'number', 32 | required: true, 33 | }) 34 | price: number; 35 | 36 | 37 | constructor(data?: Partial<Product>) { 38 | super(data); 39 | } 40 | } 41 | 42 | export interface ProductRelations { 43 | // describe navigational properties here 44 | } 45 | 46 | export type ProductWithRelations = Product & ProductRelations; 47 | -------------------------------------------------------------------------------- /www/api/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [80], 3 | "editor.tabCompletion": "on", 4 | "editor.tabSize": 2, 5 | "editor.trimAutoWhitespace": true, 6 | "editor.formatOnSave": true, 7 | "editor.codeActionsOnSave": { 8 | "source.organizeImports": true, 9 | "source.fixAll.eslint": true 10 | }, 11 | 12 | "files.exclude": { 13 | "**/.DS_Store": true, 14 | "**/.git": true, 15 | "**/.hg": true, 16 | "**/.svn": true, 17 | "**/CVS": true, 18 | "dist": true, 19 | }, 20 | "files.insertFinalNewline": true, 21 | "files.trimTrailingWhitespace": true, 22 | 23 | "typescript.tsdk": "./node_modules/typescript/lib", 24 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, 25 | "typescript.preferences.quoteStyle": "single", 26 | "eslint.run": "onSave", 27 | "eslint.nodePath": "./node_modules", 28 | "eslint.validate": [ 29 | "javascript", 30 | "typescript" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /docker/loopback/pm2/pm2-development.json: -------------------------------------------------------------------------------- 1 | { 2 | "apps": [ 3 | { 4 | "name" : "api", 5 | "script" : "dist/index.js", 6 | "instances" : 1, 7 | "exec_mode" : "cluster", 8 | "watch" : false, 9 | "merge_logs" : true, 10 | "cwd" : "/app/www/api/", 11 | "env_production" : { 12 | "NODE_ENV": process.env.NODE_ENV, 13 | "INSTANCE": process.env.INSTANCE, 14 | 15 | "HOST": process.env.HOST, 16 | "PORT": process.env.PORT, 17 | 18 | "MYSQL_HOST": process.env.MYSQL_HOST, 19 | "MYSQL_PORT": process.env.MYSQL_PORT, 20 | "MYSQL_USER": process.env.MYSQL_USER, 21 | "MYSQL_PASSWORD": process.env.MYSQL_PASSWORD, 22 | "MYSQL_DATABASE": process.env.MYSQL_DATABASE 23 | } 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /docker/loopback/pm2/pm2-production.json: -------------------------------------------------------------------------------- 1 | { 2 | "apps": [ 3 | { 4 | "name" : "api", 5 | "script" : "dist/index.js", 6 | "instances" : 2, 7 | "exec_mode" : "cluster", 8 | "watch" : false, 9 | "merge_logs" : true, 10 | "cwd" : "/app/www/api/", 11 | "env_production" : { 12 | "NODE_ENV": process.env.NODE_ENV, 13 | "INSTANCE": process.env.INSTANCE, 14 | 15 | "HOST": process.env.HOST, 16 | "PORT": process.env.PORT, 17 | 18 | "MYSQL_HOST": process.env.MYSQL_HOST, 19 | "MYSQL_PORT": process.env.MYSQL_PORT, 20 | "MYSQL_USER": process.env.MYSQL_USER, 21 | "MYSQL_PASSWORD": process.env.MYSQL_PASSWORD, 22 | "MYSQL_DATABASE": process.env.MYSQL_DATABASE 23 | } 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Compiled binary addons (https://nodejs.org/api/addons.html) 19 | build/Release 20 | 21 | # Dependency directories 22 | node_modules/ 23 | jspm_packages/ 24 | 25 | # TypeScript cache 26 | *.tsbuildinfo 27 | 28 | # Optional npm cache directory 29 | .npm 30 | 31 | # Optional eslint cache 32 | .eslintcache 33 | 34 | # Output of 'npm pack' 35 | *.tgz 36 | 37 | # Yarn Integrity file 38 | .yarn-integrity 39 | 40 | # dotenv environment variables file 41 | .env 42 | .env.test 43 | 44 | # parcel-bundler cache (https://parceljs.org/) 45 | .cache 46 | 47 | # Nuxt.js build / generate output 48 | .nuxt 49 | dist/ 50 | 51 | # Jetbrains IDE 52 | .idea 53 | 54 | .DS_Store 55 | -------------------------------------------------------------------------------- /www/api/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "node", 5 | "request": "launch", 6 | "name": "Launch Program", 7 | "skipFiles": [ 8 | "<node_internals>/**" 9 | ], 10 | "program": "${workspaceFolder}/dist/index.js", 11 | }, 12 | { 13 | "type": "node", 14 | "request": "launch", 15 | "name": "Run Mocha tests", 16 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 17 | "runtimeArgs": [ 18 | "-r", 19 | "${workspaceRoot}/node_modules/source-map-support/register" 20 | ], 21 | "cwd": "${workspaceRoot}", 22 | "autoAttachChildProcesses": true, 23 | "args": [ 24 | "--config", 25 | "${workspaceRoot}/.mocharc.json", 26 | "${workspaceRoot}/dist/__tests__/**/*.js", 27 | "-t", 28 | "0" 29 | ] 30 | }, 31 | { 32 | "type": "node", 33 | "request": "attach", 34 | "name": "Attach to Process", 35 | "port": 5858 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /www/api/src/datasources/mysql.datasource.ts: -------------------------------------------------------------------------------- 1 | import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core'; 2 | import {juggler} from '@loopback/repository'; 3 | 4 | const config = { 5 | name: 'mysql', 6 | connector: 'mysql', 7 | url: '', 8 | host: process.env.MYSQL_HOST, 9 | port: process.env.MYSQL_PORT, 10 | user: process.env.MYSQL_USER, 11 | password: process.env.MYSQL_PASSWORD, 12 | database: process.env.MYSQL_DATABASE 13 | }; 14 | 15 | // Observe application's life cycle to disconnect the datasource when 16 | // application is stopped. This allows the application to be shut down 17 | // gracefully. The `stop()` method is inherited from `juggler.DataSource`. 18 | // Learn more at https://loopback.io/doc/en/lb4/Life-cycle.html 19 | @lifeCycleObserver('datasource') 20 | export class MysqlDataSource extends juggler.DataSource 21 | implements LifeCycleObserver { 22 | static dataSourceName = 'mysql'; 23 | static readonly defaultConfig = config; 24 | 25 | constructor( 26 | @inject('datasources.config.mysql', {optional: true}) 27 | dsConfig: object = config, 28 | ) { 29 | super(dsConfig); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Um Inventor Qualquer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 2 | 3 | ## Docker 4 | Baixe e instale o Docker em https://www.docker.com/ 5 | 6 | ### Primeira execução 7 | Se esta é a primeira vez que você está executando seu ambiente, utilize o seguinte comando para compilar e inicializar 8 | seus containers. 9 | ``` 10 | ./docker/dev-init.sh 11 | ``` 12 | 13 | ### Compilando as Imagens 14 | Abra o terminal e de dentro da pasta deste repositório execute: 15 | 16 | Linux / MacOS: 17 | ``` 18 | ./docker/dev-build.sh 19 | ``` 20 | 21 | Windows: 22 | ``` 23 | docker rm -f cursoaws_api 24 | docker build -t cursoaws_api -f docker/loopback/Dockerfile . 25 | docker rm -f cursoaws_mysql 26 | docker build -t cursoaws_mysql -f docker/mysql/Dockerfile . 27 | ``` 28 | 29 | ### Iniciando os containers 30 | Abra o terminal e de dentro da pasta deste repositório execute: 31 | 32 | Linux / MacOS: 33 | ``` 34 | ./docker/dev-up.sh 35 | ``` 36 | 37 | Windows: 38 | ``` 39 | docker-compose --profile dev up 40 | ``` 41 | 42 | ### Acessando o container do Loopback via SSH 43 | Abra o terminal e de dentro da pasta deste repositório execute: 44 | 45 | Linux / MacOS: 46 | ``` 47 | ./docker/loopback/ssh.sh 48 | ``` 49 | 50 | Windows: 51 | ``` 52 | bash -c "clear && docker exec -it cursoaws_api bash" 53 | ``` 54 | -------------------------------------------------------------------------------- /www/api/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # Transpiled JavaScript files from Typescript 61 | /dist 62 | 63 | # Cache used by TypeScript's incremental build 64 | *.tsbuildinfo 65 | -------------------------------------------------------------------------------- /www/api/src/index.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationConfig, ApiApplication} from './application'; 2 | 3 | export * from './application'; 4 | 5 | export async function main(options: ApplicationConfig = {}) { 6 | const app = new ApiApplication(options); 7 | await app.boot(); 8 | await app.start(); 9 | 10 | const url = app.restServer.url; 11 | console.log(`Server is running at ${url}`); 12 | console.log(`Try ${url}/ping`); 13 | 14 | return app; 15 | } 16 | 17 | if (require.main === module) { 18 | // Run the application 19 | const config = { 20 | rest: { 21 | port: +(process.env.PORT ?? 3000), 22 | host: process.env.HOST, 23 | // The `gracePeriodForClose` provides a graceful close for http/https 24 | // servers with keep-alive clients. The default value is `Infinity` 25 | // (don't force-close). If you want to immediately destroy all sockets 26 | // upon stop, set its value to `0`. 27 | // See https://www.npmjs.com/package/stoppable 28 | gracePeriodForClose: 5000, // 5 seconds 29 | openApiSpec: { 30 | // useful when used with OpenAPI-to-GraphQL to locate your application 31 | setServersFromRequest: true, 32 | }, 33 | }, 34 | }; 35 | main(config).catch(err => { 36 | console.error('Cannot start the application.', err); 37 | process.exit(1); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /www/api/src/application.ts: -------------------------------------------------------------------------------- 1 | import {BootMixin} from '@loopback/boot'; 2 | import {ApplicationConfig} from '@loopback/core'; 3 | import { 4 | RestExplorerBindings, 5 | RestExplorerComponent, 6 | } from '@loopback/rest-explorer'; 7 | import {RepositoryMixin} from '@loopback/repository'; 8 | import {RestApplication} from '@loopback/rest'; 9 | import {ServiceMixin} from '@loopback/service-proxy'; 10 | import path from 'path'; 11 | import {MySequence} from './sequence'; 12 | 13 | export {ApplicationConfig}; 14 | 15 | export class ApiApplication extends BootMixin( 16 | ServiceMixin(RepositoryMixin(RestApplication)), 17 | ) { 18 | constructor(options: ApplicationConfig = {}) { 19 | super(options); 20 | 21 | // Set up the custom sequence 22 | this.sequence(MySequence); 23 | 24 | // Set up default home page 25 | this.static('/', path.join(__dirname, '../public')); 26 | 27 | // Customize @loopback/rest-explorer configuration here 28 | this.configure(RestExplorerBindings.COMPONENT).to({ 29 | path: '/explorer', 30 | }); 31 | this.component(RestExplorerComponent); 32 | 33 | this.projectRoot = __dirname; 34 | // Customize @loopback/boot Booter Conventions here 35 | this.bootOptions = { 36 | controllers: { 37 | // Customize ControllerBooter Conventions here 38 | dirs: ['controllers'], 39 | extensions: ['.controller.js'], 40 | nested: true, 41 | }, 42 | }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /www/api/src/controllers/ping.controller.ts: -------------------------------------------------------------------------------- 1 | import {inject} from '@loopback/core'; 2 | import { 3 | Request, 4 | RestBindings, 5 | get, 6 | response, 7 | ResponseObject, 8 | } from '@loopback/rest'; 9 | 10 | /** 11 | * OpenAPI response for ping() 12 | */ 13 | const PING_RESPONSE: ResponseObject = { 14 | description: 'Ping Response', 15 | content: { 16 | 'application/json': { 17 | schema: { 18 | type: 'object', 19 | title: 'PingResponse', 20 | properties: { 21 | greeting: {type: 'string'}, 22 | date: {type: 'string'}, 23 | url: {type: 'string'}, 24 | headers: { 25 | type: 'object', 26 | properties: { 27 | 'Content-Type': {type: 'string'}, 28 | }, 29 | additionalProperties: true, 30 | }, 31 | }, 32 | }, 33 | }, 34 | }, 35 | }; 36 | 37 | /** 38 | * A simple controller to bounce back http requests 39 | */ 40 | export class PingController { 41 | constructor(@inject(RestBindings.Http.REQUEST) private req: Request) {} 42 | 43 | // Map to `GET /ping` 44 | @get('/ping') 45 | @response(200, PING_RESPONSE) 46 | ping(): object { 47 | // Reply with a greeting, the current time, the url, and request headers 48 | return { 49 | greeting: 'Hello from LoopBack', 50 | date: new Date(), 51 | url: this.req.url, 52 | headers: Object.assign({}, this.req.headers), 53 | }; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /www/api/DEVELOPING.md: -------------------------------------------------------------------------------- 1 | # Developer's Guide 2 | 3 | We use Visual Studio Code for developing LoopBack and recommend the same to our 4 | users. 5 | 6 | ## VSCode setup 7 | 8 | Install the following extensions: 9 | 10 | - [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) 11 | - [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) 12 | 13 | ## Development workflow 14 | 15 | ### Visual Studio Code 16 | 17 | 1. Start the build task (Cmd+Shift+B) to run TypeScript compiler in the 18 | background, watching and recompiling files as you change them. Compilation 19 | errors will be shown in the VSCode's "PROBLEMS" window. 20 | 21 | 2. Execute "Run Rest Task" from the Command Palette (Cmd+Shift+P) to re-run the 22 | test suite and lint the code for both programming and style errors. Linting 23 | errors will be shown in VSCode's "PROBLEMS" window. Failed tests are printed 24 | to terminal output only. 25 | 26 | ### Other editors/IDEs 27 | 28 | 1. Open a new terminal window/tab and start the continuous build process via 29 | `npm run build:watch`. It will run TypeScript compiler in watch mode, 30 | recompiling files as you change them. Any compilation errors will be printed 31 | to the terminal. 32 | 33 | 2. In your main terminal window/tab, run `npm run test:dev` to re-run the test 34 | suite and lint the code for both programming and style errors. You should run 35 | this command manually whenever you have new changes to test. Test failures 36 | and linter errors will be printed to the terminal. 37 | -------------------------------------------------------------------------------- /www/api/README.md: -------------------------------------------------------------------------------- 1 | # api 2 | 3 | This application is generated using [LoopBack 4 CLI](https://loopback.io/doc/en/lb4/Command-line-interface.html) with the 4 | [initial project layout](https://loopback.io/doc/en/lb4/Loopback-application-layout.html). 5 | 6 | ## Install dependencies 7 | 8 | By default, dependencies were installed when this application was generated. 9 | Whenever dependencies in `package.json` are changed, run the following command: 10 | 11 | ```sh 12 | npm install 13 | ``` 14 | 15 | To only install resolved dependencies in `package-lock.json`: 16 | 17 | ```sh 18 | npm ci 19 | ``` 20 | 21 | ## Run the application 22 | 23 | ```sh 24 | npm start 25 | ``` 26 | 27 | You can also run `node .` to skip the build step. 28 | 29 | Open http://127.0.0.1:3000 in your browser. 30 | 31 | ## Rebuild the project 32 | 33 | To incrementally build the project: 34 | 35 | ```sh 36 | npm run build 37 | ``` 38 | 39 | To force a full build by cleaning up cached artifacts: 40 | 41 | ```sh 42 | npm run rebuild 43 | ``` 44 | 45 | ## Fix code style and formatting issues 46 | 47 | ```sh 48 | npm run lint 49 | ``` 50 | 51 | To automatically fix such issues: 52 | 53 | ```sh 54 | npm run lint:fix 55 | ``` 56 | 57 | ## Other useful commands 58 | 59 | - `npm run migrate`: Migrate database schemas for models 60 | - `npm run openapi-spec`: Generate OpenAPI spec into a file 61 | - `npm run docker:build`: Build a Docker image for this application 62 | - `npm run docker:run`: Run this application inside a Docker container 63 | 64 | ## Tests 65 | 66 | ```sh 67 | npm test 68 | ``` 69 | 70 | ## What's next 71 | 72 | Please check out [LoopBack 4 documentation](https://loopback.io/doc/en/lb4/) to 73 | understand how you can continue to add features to this application. 74 | 75 | [![LoopBack](https://github.com/strongloop/loopback-next/raw/master/docs/site/imgs/branding/Powered-by-LoopBack-Badge-(blue)-@2x.png)](http://loopback.io/) 76 | -------------------------------------------------------------------------------- /www/api/public/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html lang="en"> 3 | 4 | <head> 5 | <title>API Test 6 | 7 | 8 | 9 | 10 | 11 | 12 | 70 | 71 | 72 | 73 |
74 |

api

75 |

Version 1.0.0

76 | 77 |

OpenAPI spec: /openapi.json

78 |

API Explorer: /explorer

79 |
80 | 81 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /www/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api", 3 | "version": "0.0.1", 4 | "description": "API Test", 5 | "keywords": [ 6 | "loopback-application", 7 | "loopback" 8 | ], 9 | "main": "dist/index.js", 10 | "types": "dist/index.d.ts", 11 | "engines": { 12 | "node": ">=10.16" 13 | }, 14 | "scripts": { 15 | "build": "lb-tsc", 16 | "build:watch": "lb-tsc --watch", 17 | "lint": "npm run eslint && npm run prettier:check", 18 | "lint:fix": "npm run eslint:fix && npm run prettier:fix", 19 | "prettier:cli": "lb-prettier \"**/*.ts\" \"**/*.js\"", 20 | "prettier:check": "npm run prettier:cli -- -l", 21 | "prettier:fix": "npm run prettier:cli -- --write", 22 | "eslint": "lb-eslint --report-unused-disable-directives .", 23 | "eslint:fix": "npm run eslint -- --fix", 24 | "pretest": "npm run rebuild", 25 | "test": "lb-mocha --allow-console-logs \"dist/__tests__\"", 26 | "posttest": "npm run lint", 27 | "test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js && npm run posttest", 28 | "docker:build": "docker build -t api .", 29 | "docker:run": "docker run -p 3000:3000 -d api", 30 | "premigrate": "npm run build", 31 | "migrate": "node ./dist/migrate", 32 | "preopenapi-spec": "npm run build", 33 | "openapi-spec": "node ./dist/openapi-spec", 34 | "prestart": "npm run rebuild", 35 | "start": "node -r source-map-support/register .", 36 | "clean": "lb-clean dist *.tsbuildinfo .eslintcache", 37 | "rebuild": "npm run clean && npm run build" 38 | }, 39 | "repository": { 40 | "type": "git", 41 | "url": "" 42 | }, 43 | "author": "Wesley Milan", 44 | "license": "", 45 | "files": [ 46 | "README.md", 47 | "dist", 48 | "src", 49 | "!*/__tests__" 50 | ], 51 | "dependencies": { 52 | "@loopback/boot": "^3.3.1", 53 | "@loopback/core": "^2.15.1", 54 | "@loopback/repository": "^3.5.1", 55 | "@loopback/rest": "^9.2.1", 56 | "@loopback/rest-explorer": "^3.2.1", 57 | "@loopback/service-proxy": "^3.1.1", 58 | "loopback-connector-mysql": "^5.4.4", 59 | "tslib": "^2.0.0" 60 | }, 61 | "devDependencies": { 62 | "@loopback/build": "^6.3.1", 63 | "@loopback/eslint-config": "^10.1.1", 64 | "@loopback/testlab": "^3.3.1", 65 | "@types/node": "^10.17.56", 66 | "eslint": "^7.23.0", 67 | "source-map-support": "^0.5.19", 68 | "typescript": "~4.2.3" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | ## Criação da API 2 | A API já está criada na pasta `www/api`. As seguintes instruções são uma demonstração prática de como ela foi criada 3 | utilizando o assistente de geração de aplicações do Loopback, você pode encontrar mais informações em 4 | https://loopback.io/doc/en/lb4/Getting-started.html . 5 | 6 | #### Criando o APP: 7 | 8 | ``` 9 | # sudo npm i -g @loopback/cli 10 | # lb4 app 11 | ? Project name: api 12 | ? Project description: Test API for AWS class 13 | ? Project root directory: api 14 | ? Application class name: ApiApplication 15 | ? Select features to enable in the project Enable eslint, Enable prettier, Enable mocha, Enable loopbackBuild, Enable vscode, Enable docker, Enable repositories, Enable s 16 | ervices 17 | ? Yarn is available. Do you prefer to use it by default? No 18 | # cd api 19 | # npm i 20 | ``` 21 | 22 | #### Criando Datasource 23 | ``` 24 | # lb4 datasource 25 | ? Datasource name: mysql 26 | ? Select the connector for mysql: MySQL (supported by StrongLoop) 27 | ? Connection String url to override other settings (eg: mysql://user:pass@host/db): 28 | ? host: mysql.docker 29 | ? port: 3306 30 | ? user: root 31 | ? password: root 32 | ? database: dev_cursoaws 33 | ``` 34 | 35 | #### Criando o Model Produtos 36 | ``` 37 | # lb4 model 38 | ? Model class name: Product 39 | ? Please select the model base class Entity (A persisted model with an ID) 40 | ? Allow additional (free-form) properties? No 41 | Model Product will be created in src/models/product.model.ts 42 | 43 | Let's add a property to Product 44 | Enter an empty property name when done 45 | 46 | ? Enter the property name: id 47 | ? Property type: number 48 | ? Is id the ID property? Yes 49 | ? Is id generated automatically? Yes 50 | 51 | Let's add another property to Product 52 | Enter an empty property name when done 53 | 54 | ? Enter the property name: name 55 | ? Property type: string 56 | ? Is it required?: Yes 57 | 58 | Let's add another property to Product 59 | Enter an empty property name when done 60 | 61 | ? Enter the property name: category 62 | ? Property type: string 63 | ? Is it required?: Yes 64 | 65 | Let's add another property to Product 66 | Enter an empty property name when done 67 | 68 | ? Enter the property name: cost 69 | ? Property type: number 70 | ? Is it required?: No 71 | ? Default value [leave blank for none]: 0 72 | 73 | Let's add another property to Product 74 | Enter an empty property name when done 75 | 76 | ? Enter the property name: price 77 | ? Property type: number 78 | ? Is it required?: Yes 79 | 80 | Let's add another property to Product 81 | Enter an empty property name when done 82 | 83 | ? Enter the property name: 84 | create src/models/product.model.ts 85 | update src/models/index.ts 86 | ``` 87 | 88 | #### Criando o Repositório 89 | ``` 90 | # lb4 repository 91 | ? Please select the datasource MysqlDatasource 92 | ? Select the model(s) you want to generate a repository for Product 93 | ? Please select the repository base class DefaultCrudRepository (Juggler bridge) 94 | create src/repositories/product.repository.ts 95 | update src/repositories/index.ts 96 | 97 | Repository ProductRepository was/were created in src/repositories 98 | ``` 99 | 100 | #### Criando o Controller 101 | ``` 102 | # lb4 controller 103 | ? Controller class name: Product 104 | Controller Product will be created in src/controllers/product.controller.ts 105 | 106 | ? What kind of controller would you like to generate? REST Controller with CRUD functions 107 | ? What is the name of the model to use with this CRUD repository? Product 108 | ? What is the name of your CRUD repository? ProductRepository 109 | ? What is the name of ID property? id 110 | ? What is the type of your ID? string 111 | ? Is the id omitted when creating a new instance? Yes 112 | ? What is the base HTTP path name of the CRUD operations? /products 113 | create src/controllers/product.controller.ts 114 | update src/controllers/index.ts 115 | 116 | Controller Product was/were created in src/controllers 117 | ``` 118 | 119 | #### Migrando models para DB 120 | ``` 121 | npm run build 122 | npm run migrate 123 | ``` 124 | 125 | #### Rodando a API 126 | ``` 127 | npm start 128 | ``` 129 | 130 | -------------------------------------------------------------------------------- /www/api/src/controllers/product.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Count, 3 | CountSchema, 4 | Filter, 5 | FilterExcludingWhere, 6 | repository, 7 | Where, 8 | } from '@loopback/repository'; 9 | import { 10 | post, 11 | param, 12 | get, 13 | getModelSchemaRef, 14 | patch, 15 | put, 16 | del, 17 | requestBody, 18 | response, 19 | } from '@loopback/rest'; 20 | import {Product} from '../models'; 21 | import {ProductRepository} from '../repositories'; 22 | 23 | export class ProductController { 24 | constructor( 25 | @repository(ProductRepository) 26 | public productRepository : ProductRepository, 27 | ) {} 28 | 29 | @post('/products') 30 | @response(200, { 31 | description: 'Product model instance', 32 | content: {'application/json': {schema: getModelSchemaRef(Product)}}, 33 | }) 34 | async create( 35 | @requestBody({ 36 | content: { 37 | 'application/json': { 38 | schema: getModelSchemaRef(Product, { 39 | title: 'NewProduct', 40 | exclude: ['id'], 41 | }), 42 | }, 43 | }, 44 | }) 45 | product: Omit, 46 | ): Promise { 47 | return this.productRepository.create(product); 48 | } 49 | 50 | @get('/products/count') 51 | @response(200, { 52 | description: 'Product model count', 53 | content: {'application/json': {schema: CountSchema}}, 54 | }) 55 | async count( 56 | @param.where(Product) where?: Where, 57 | ): Promise { 58 | return this.productRepository.count(where); 59 | } 60 | 61 | @get('/products') 62 | @response(200, { 63 | description: 'Array of Product model instances', 64 | content: { 65 | 'application/json': { 66 | schema: { 67 | type: 'array', 68 | items: getModelSchemaRef(Product, {includeRelations: true}), 69 | }, 70 | }, 71 | }, 72 | }) 73 | async find( 74 | @param.filter(Product) filter?: Filter, 75 | ): Promise { 76 | return this.productRepository.find(filter); 77 | } 78 | 79 | @patch('/products') 80 | @response(200, { 81 | description: 'Product PATCH success count', 82 | content: {'application/json': {schema: CountSchema}}, 83 | }) 84 | async updateAll( 85 | @requestBody({ 86 | content: { 87 | 'application/json': { 88 | schema: getModelSchemaRef(Product, {partial: true}), 89 | }, 90 | }, 91 | }) 92 | product: Product, 93 | @param.where(Product) where?: Where, 94 | ): Promise { 95 | return this.productRepository.updateAll(product, where); 96 | } 97 | 98 | @get('/products/{id}') 99 | @response(200, { 100 | description: 'Product model instance', 101 | content: { 102 | 'application/json': { 103 | schema: getModelSchemaRef(Product, {includeRelations: true}), 104 | }, 105 | }, 106 | }) 107 | async findById( 108 | @param.path.number('id') id: number, 109 | @param.filter(Product, {exclude: 'where'}) filter?: FilterExcludingWhere 110 | ): Promise { 111 | return this.productRepository.findById(id, filter); 112 | } 113 | 114 | @patch('/products/{id}') 115 | @response(204, { 116 | description: 'Product PATCH success', 117 | }) 118 | async updateById( 119 | @param.path.number('id') id: number, 120 | @requestBody({ 121 | content: { 122 | 'application/json': { 123 | schema: getModelSchemaRef(Product, {partial: true}), 124 | }, 125 | }, 126 | }) 127 | product: Product, 128 | ): Promise { 129 | await this.productRepository.updateById(id, product); 130 | } 131 | 132 | @put('/products/{id}') 133 | @response(204, { 134 | description: 'Product PUT success', 135 | }) 136 | async replaceById( 137 | @param.path.number('id') id: number, 138 | @requestBody() product: Product, 139 | ): Promise { 140 | await this.productRepository.replaceById(id, product); 141 | } 142 | 143 | @del('/products/{id}') 144 | @response(204, { 145 | description: 'Product DELETE success', 146 | }) 147 | async deleteById(@param.path.number('id') id: number): Promise { 148 | await this.productRepository.deleteById(id); 149 | } 150 | } 151 | --------------------------------------------------------------------------------