[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [Sean-Bradley]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: seanwasere\nopen_collective: # Replace with a single Open Collective username\nko_fi: sean_bradley\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nnpm-debug.log\ndist/"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "image: docker:latest\nservices:\n  - docker:dind\n\nstages:\n  - test\n  - deploy\n\nstep-develop:\n  stage: test\n  before_script:\n    - export DYNAMIC_ENV_VAR=DEVELOP\n  only:\n    - develop\n  tags:\n    - develop\n  script:\n    - echo running tests in $DYNAMIC_ENV_VAR\n\nstep-uat:\n  stage: deploy\n  before_script:\n    - export DYNAMIC_ENV_VAR=UAT\n  only:\n    - uat\n  tags:\n    - uat\n  script:\n    - echo setting up env $DYNAMIC_ENV_VAR\n    - sudo apt-get install -y python-pip\n    - sudo pip install docker-compose\n    - sudo docker image prune -f\n    - sudo docker-compose -f docker-compose.yml build --no-cache\n    - sudo docker-compose -f docker-compose.yml up -d\n\nstep-deploy-staging:\n  stage: deploy\n  before_script:\n    - export DYNAMIC_ENV_VAR=STAGING\n  only:\n    - staging\n  tags:\n    - staging\n  script:\n    - echo setting up env $DYNAMIC_ENV_VAR\n    - sudo apt-get install -y python-pip\n    - sudo pip install docker-compose\n    - sudo docker image prune -f\n    - sudo docker-compose -f docker-compose.yml build --no-cache\n    - sudo docker-compose -f docker-compose.yml up -d\n\nstep-deploy-production:\n  stage: deploy\n  before_script:\n    - export DYNAMIC_ENV_VAR=PRODUCTION\n  only:\n    - production\n  tags:\n    - production\n  script:\n    - echo setting up env $DYNAMIC_ENV_VAR\n    - sudo apt-get install -y python-pip\n    - sudo pip install docker-compose\n    - sudo docker image prune -f\n    - sudo docker-compose -f docker-compose.yml build --no-cache\n    - sudo docker-compose -f docker-compose.yml up -d\n  when: manual\n\n\n\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM node:alpine\n\nLABEL github=https://github.com/Sean-Bradley\n\nCOPY src /nodejs/src\nCOPY package.json /nodejs/package.json\nCOPY tsconfig.json /nodejs/tsconfig.json\n\nWORKDIR /nodejs\n\nRUN npm install\n\nEXPOSE 3000:3000\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 seanwasere youtube\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "app.json",
    "content": "{\n    \"name\": \"seans-typescript-nodejs-crud-rest-api-boilerplate\",\n    \"description\": \"A barebones TypeScript Node.js CRUD REST API\",\n    \"repository\": \"https://github.com/Sean-Bradley/Seans-TypeScript-NodeJS-CRUD-REST-API-Boilerplate\",\n    \"logo\": \"https://github.com/Sean-Bradley/Seans-TypeScript-NodeJS-CRUD-REST-API-Boilerplate/blob/master/cosmo1.png\",\n    \"keywords\": [\"node\", \"typescript\", \"crud\", \"seanwasere\"]\n  }"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '2'\nservices:\n  nginx:\n    build: \n      context: nginx\n      dockerfile: Dockerfile\n    ports:\n      - \"80:80\"\n    command: nginx -g \"daemon off\";\n    depends_on:\n      - nodejs\n      \n  nodejs:\n    build:\n      context: .      \n      dockerfile: Dockerfile\n    image: service-cats:1.01\n    expose:\n      - \"3000\"\n    command: npm start\n\n"
  },
  {
    "path": "nginx/Dockerfile",
    "content": "FROM nginx\nLABEL github=https://github.com/Sean-Bradley\nCOPY /nginx.conf\t/etc/nginx/nginx.conf\n#COPY /server.crt\t/etc/nginx/server.crt\n#COPY /server.key\t/etc/nginx/server.key\nCOPY /static\t    /static\n"
  },
  {
    "path": "nginx/nginx.conf",
    "content": "user www-data;\nworker_processes 1;\npid /run/nginx.pid;\nevents {\n    worker_connections 768;\n}\nhttp {\n    sendfile off;\n    tcp_nopush on;\n    tcp_nodelay on;\n    keepalive_timeout 65;\n    types_hash_max_size 2048;\n    include /etc/nginx/mime.types;\n    default_type application/octet-stream;\n    #access_log /var/log/nginx/access.log;\n    error_log /var/log/nginx/error.log;\n    gzip on;\n    gzip_disable \"msie6\";\n    server {\n        listen 80;\n        server_name localhost;\n#ssl_certificate      server.crt;\n#ssl_certificate_key  server.key;\n        location / {\n            root /static;\n            index index.html;\n        }\n        location /api/ {\n            proxy_pass_header Server;\n            proxy_set_header Host $http_host;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-Scheme $scheme;\n            proxy_set_header X-Real-IP\t$remote_addr;\n            proxy_set_header X-Forwarded-For\t$proxy_add_x_forwarded_for;\n            proxy_redirect off;\n            proxy_connect_timeout 20;\n            proxy_read_timeout 20;\n            proxy_pass http://nodejs:3000/;\n        }\n    }\n}\n"
  },
  {
    "path": "nginx/static/index.html",
    "content": "put the static html generated from you favourite front end framework here."
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"seans-typescript-nodejs-crud-rest-api-boilerplate\",\n  \"version\": \"1.0.1\",\n  \"description\": \"\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"start\": \"tsc && node dist/server.js\",\n    \"build\": \"tsc\",\n    \"dev\": \"concurrently --kill-others \\\"tsc -w\\\" \\\"nodemon dist/server.js\\\"\"\n  },\n  \"keywords\": [\n    \"typescript\",\n    \"nodejs\",\n    \"crud\",\n    \"rest\",\n    \"swagger\"\n  ],\n  \"author\": \"Sean Bradley\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@types/express\": \"^4.17.11\",\n    \"@types/node\": \"^13.13.40\",\n    \"body-parser\": \"^1.20.2\",\n    \"cors\": \"^2.8.5\",\n    \"express\": \"^4.18.2\",\n    \"swagger-ui-express\": \"^5.0.0\",\n    \"typescript\": \"^5.2.2\",\n    \"uuid\": \"^9.0.1\"\n  },\n  \"devDependencies\": {\n    \"concurrently\": \"^8.2.2\",\n    \"nodemon\": \"^3.0.1\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "## Seans-TypeScript-NodeJS-CRUD-REST-API-Boilerplate\n\n> To help support this TypeScript boilerplate, please take a moment to look at my official **Design Patterns in TypeScript** book and **TypeScript Courses**. <br/>  \n>  <img src=\"docs/threejs-course-image-w100.png\" style=\"margin-bottom:-4px\"> [Three.js and TypeScript](https://www.udemy.com/course/threejs-tutorials/?referralCode=4C7E1DE91C3E42F69D0F)\n>\n> <img src=\"docs/tssock-course-w100.png\" style=\"margin-bottom:-4px\"> [Socket.IO and TypeScript](https://www.udemy.com/course/typescript-socketio/?referralCode=2F6E227AC7EB9D147327)\n>\n> <img src=\"docs/threejs_typescript_116.jpg\"> Three.js and TypeScript : [ASIN B094716FD6](https://www.amazon.com/dp/B09GYTKRCH)\n>\n> <img src=\"docs/dp_typescript_116.jpg\"> Design Patterns in TypeScript : Paperback [ASIN B0948BCH24](https://www.amazon.com/dp/B0948BCH24), eBook : [ASIN B094716FD6](https://www.amazon.com/dp/B094716FD6)\n\n### MIT License\n\nRemember, No guarantees, or even fit for a particular purpose.\n\nIf you have a suggestion, or you want to contribute some code, you can make a pull request.\n\nYour contributions will be visible since this project is public.\n\n### Setup\n\n```bash\nnpm install\n```\n\n### Development with nodemon and tsc --watch\n\n```bash\nnpm run dev\n```\n\nThen visit `http://localhost:3000/cats`\n\n### Run without nodemon and tsc --watch\n\n```bash\nnpm start\n```\n\nThen visit `http://localhost:3000/cats`\n\n## Swagger\n\nVisit `http://localhost:3000/swagger` to view the OPENAPI document in Swagger-UI\n![Swagger-UI](docs/swagger.png)\n\n### Video tutorial on setting up Swagger in an existing NodeJS TypeScript API\n\n[![Add Swagger-UI Documentation To Existing NodeJS TypeScript API](https://img.youtube.com/vi/qemG0CWOx1I/0.jpg)](https://youtu.be/qemG0CWOx1I)\n\n## Continuous Integration and Deployment\n\nI've also added gitlab-ci.yml and dockerised with Docker-Compose. See video tutorial on how all this works.\n[![CI/CD a NodeJS API with Docker-Compose and GitLab](https://img.youtube.com/vi/Qlj6NiOy5jM/0.jpg)](https://youtu.be/Qlj6NiOy5jM)\n\n## Usage\n\n### List all records\n\n![Example Get all records](docs/get-example.png)\n\n### Post (Create) Record\n\n![Example Post (Create) new record](docs/post-example.png)\n\n### Get by Id\n\n![Example Get by ID](docs/get-id-example.png)\n\n### Put (Update) Record\n\n![Example Put (Update)](docs/put-example.png)\n\n### Delete Record\n\n![Example Delete](docs/delete-example.png)\n\n# TypeScript Courses\n\nIf you got this far, you probably like TypeScript just like I do,\nI have created two TypeScript courses specializing in the [Three.js](https://www.udemy.com/course/threejs-tutorials/?referralCode=4C7E1DE91C3E42F69D0F) and [Socket.IO](https://www.udemy.com/course/typescript-socketio/?referralCode=2F6E227AC7EB9D147327)\nlibraries that you may find useful.\n\n## Threejs and TypeScript Course\n\n[![TypeScript Threejs Introduction](docs/threejs-course-image.png)](https://youtu.be/BcF3yuVqfwo)\n\n## Socket.io and TypeScript Course\n\n[![TypeScript SocketIO Introduction](docs/tssock-course.png)](https://youtu.be/3uLSNctzkkw)\n\n# Programming Books\n\nTo help support my projects, please check out my books.\n\n## Three.js and TypeScript\n\n<img style=\"float:left; min-width:150px;\" src=\"./docs/threejs-typescript-250.jpg\">\n\n&nbsp;<a href=\"https://www.amazon.com/dp/B09GYTKRCH\"><img src=\"/docs/flag_us.gif\">&nbsp; https://www.amazon.com/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.co.uk/dp/B09GYTKRCH\"><img src=\"/docs/flag_uk.gif\">&nbsp; https://www.amazon.co.uk/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.in/dp/B09GYTKRCH\"><img src=\"/docs/flag_in.gif\">&nbsp; https://www.amazon.in/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.de/dp/B09GYTKRCH\"><img src=\"/docs/flag_de.gif\">&nbsp; https://www.amazon.de/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.fr/dp/B09GYTKRCH\"><img src=\"/docs/flag_fr.gif\">&nbsp; https://www.amazon.fr/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.es/dp/B09GYTKRCH\"><img src=\"/docs/flag_es.gif\">&nbsp; https://www.amazon.es/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.it/dp/B09GYTKRCH\"><img src=\"/docs/flag_it.gif\">&nbsp; https://www.amazon.it/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.nl/dp/B09GYTKRCH\"><img src=\"/docs/flag_nl.gif\">&nbsp; https://www.amazon.nl/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.co.jp/dp/B09GYTKRCH\"><img src=\"/docs/flag_jp.gif\">&nbsp; https://www.amazon.co.jp/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.ca/dp/B09GYTKRCH\"><img src=\"/docs/flag_ca.gif\">&nbsp; https://www.amazon.ca/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.com.br/dp/B09GYTKRCH\"><img src=\"/docs/flag_br.gif\">&nbsp; https://www.amazon.com.br/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.com.mx/dp/B09GYTKRCH\"><img src=\"/docs/flag_mx.gif\">&nbsp; https://www.amazon.com.mx/dp/B09GYTKRCH</a><br/>\n&nbsp;<a href=\"https://www.amazon.com.au/dp/B09GYTKRCH\"><img src=\"/docs/flag_au.gif\">&nbsp; https://www.amazon.com.au/dp/B09GYTKRCH</a>\n\n(ASIN : B09GZM9KGJ / B09GYTKRCH)\n\n**Design Patterns in TypeScript**.\n\n<img style=\"float:left; min-width:150px;\" src=\"/docs/dp_typescript_250.jpg\">\n\n&nbsp;<a href=\"https://www.amazon.com/dp/B0948BCH24\"><img src=\"/docs/flag_us.gif\">&nbsp; https://www.amazon.com/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.co.uk/dp/B0948BCH24\"><img src=\"/docs/flag_uk.gif\">&nbsp; https://www.amazon.co.uk/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.in/dp/B094716FD6\"><img src=\"/docs/flag_in.gif\">&nbsp; https://www.amazon.in/dp/B094716FD6</a><br/>\n&nbsp;<a href=\"https://www.amazon.de/dp/B0948BCH24\"><img src=\"/docs/flag_de.gif\">&nbsp; https://www.amazon.de/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.fr/dp/B0948BCH24\"><img src=\"/docs/flag_fr.gif\">&nbsp; https://www.amazon.fr/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.es/dp/B0948BCH24\"><img src=\"/docs/flag_es.gif\">&nbsp; https://www.amazon.es/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.it/dp/B0948BCH24\"><img src=\"/docs/flag_it.gif\">&nbsp; https://www.amazon.it/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.co.jp/dp/B0948BCH24\"><img src=\"/docs/flag_jp.gif\">&nbsp; https://www.amazon.co.jp/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.ca/dp/B0948BCH24\"><img src=\"/docs/flag_ca.gif\">&nbsp; https://www.amazon.ca/dp/B0948BCH24</a><br/>\n&nbsp;<a href=\"https://www.amazon.com.au/dp/B094716FD6\"><img src=\"/docs/flag_au.gif\">&nbsp; https://www.amazon.com.au/dp/B094716FD6</a>\n\n(ASIN : B0948BCH24 / B094716FD6)\n\n---\n\nThanks\n\nSean\n"
  },
  {
    "path": "src/app.ts",
    "content": "import express from 'express'\nimport Router from './router'\nimport swaggerUi from 'swagger-ui-express'\nimport * as swaggerDocument from './swagger.json'\nimport * as bodyParser from 'body-parser'\n\nclass App {\n  private httpServer: any\n\n  constructor() {\n    this.httpServer = express()\n\n    this.httpServer.use(bodyParser.urlencoded({ extended: true }));\n    this.httpServer.use(bodyParser.json());\n    \n    new Router(this.httpServer);\n\n    this.httpServer.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerDocument));     \n  }\n\n  public Start = (port: number) => {\n    return new Promise((resolve, reject) => {\n\n      this.httpServer.listen(\n        port,\n        () => {\n          resolve(port)\n        })\n        .on('error', (err: object) => reject(err));\n    })\n  }\n}\n\nexport default App;\n"
  },
  {
    "path": "src/models/Bird.ts",
    "content": "type Bird = {\n    genus: String;\n    name: String;\n    isHungry: Boolean;\n    lastFedDate: Date;\n}\nexport default Bird\n\n"
  },
  {
    "path": "src/models/Cat.ts",
    "content": "type Cat = {\n    genus: String;\n    name: String;\n    isHungry: Boolean;\n    lastFedDate: Date;\n}\nexport default Cat\n\n"
  },
  {
    "path": "src/models/Dog.ts",
    "content": "type Dog = {\n    genus: String;\n    name: String;\n    isHungry: Boolean;\n    lastFedDate: Date;\n}\nexport default Dog\n\n"
  },
  {
    "path": "src/router.ts",
    "content": "import * as express from 'express'\nimport Cat from './models/Cat'\nimport { v4 as uuid } from 'uuid';\nimport cors from 'cors'\n\nclass Router {\n\n    constructor(server: express.Express) {\n        const router = express.Router()\n\n        const cats = new Map<string, Cat>();\n        cats[uuid()] = { genus: \"feline\", name: \"Cosmo\", isHungry: true, lastFedDate: new Date() }\n        cats[uuid()] = { genus: \"feline\", name: \"Emmy\", isHungry: true, lastFedDate: new Date() }\n\n        router.get('/', (req: express.Request, res: express.Response) => {\n            res.json({\n                message: `Nothing to see here, [url]/cats instead.`\n            })\n        })\n\n        //get all cats\n        router.get('/cats', cors(), (req: express.Request, res: express.Response) => {\n            res.json({\n                cats\n            })\n        })\n\n        //create new cat\n        router.post('/cats', cors(), (req: express.Request, res: express.Response) => {\n            try {\n                let cat: Cat = {} as Cat;\n                Object.assign(cat, req.body)\n                const newUUID = uuid();\n                cats[newUUID] = cat;\n                res.json({\n                    uuid: newUUID\n                })\n            } catch (e) {\n                res.status(400).send(JSON.stringify({ \"error\": \"problem with posted data\" }));\n            }\n        })\n\n        //get cat by id\n        router.get('/cats/:id', cors(), (req: express.Request, res: express.Response) => {\n            if (!!cats[req.params.id]) {\n                res.json({\n                    cat: cats[req.params.id]\n                })\n            } else {\n                res.status(404).send(JSON.stringify({ \"error\": \"no such cat\" }));\n            }\n        })\n\n        //update cat\n        router.put('/cats/:id', cors(), (req: express.Request, res: express.Response) => {\n            try {\n                if (!!cats[req.params.id]) {\n                    let cat: Cat = {} as Cat;\n                    Object.assign(cat, req.body)\n                    cats[req.params.id] = cat;\n                    res.json({\n                        cat: cats[req.params.id]\n                    })\n                } else {\n                    res.status(404).send(JSON.stringify({ \"error\": \"no such cat\" }));\n                }\n            } catch (e) {\n                res.status(400).send(JSON.stringify({ \"error\": \"problem with posted data\" }));\n            }\n        })\n\n        //delete cat\n        router.delete('/cats/:id', cors(), (req: express.Request, res: express.Response) => {\n            if (!!cats[req.params.id]) {\n                delete cats[req.params.id]\n                res.json({\n                    uuid: req.params.id\n                })\n            } else {\n                res.status(404).send(JSON.stringify({ \"error\": \"no such cat\" }));\n            }\n        });\n\n        router.options('*', cors());\n\n        server.use('/', router)\n    }\n}\n\nexport default Router;"
  },
  {
    "path": "src/server.ts",
    "content": "import app from './app'\n\nconst port = parseInt(process.env.PORT || '3000')\n\nconst server = new app().Start(port)\n  .then(port => console.log(`Server running on port ${port}`))\n  .catch(error => {\n    console.log(error)\n    process.exit(1);\n  });\n\nexport default server;"
  },
  {
    "path": "src/swagger.json",
    "content": "{\n    \"openapi\": \"3.0.0\",\n    \"info\": {\n        \"version\": \"1.0.0\",\n        \"title\": \"Seans-TypeScript-NodeJS-CRUD-REST-API-Boilerplate\",\n        \"description\": \"A minimal and easy to follow example of what you need to create a CRUD style API in NodeJs using TypeScript\",\n        \"license\": {\n            \"name\": \"MIT\",\n            \"url\": \"https://opensource.org/licenses/MIT\"\n        }\n    },\n    \"servers\": [\n        {\n            \"url\": \"/\",\n            \"description\": \"Local Dev, or from Heroku\"\n        },\n        {\n            \"url\": \"/api/\",\n            \"description\": \"With docker-compose and nginx proxy\"\n        }\n    ],\n    \"tags\": [\n        {\n            \"name\": \"Cats\",\n            \"description\": \"API for cats in the system\"\n        }\n    ],\n    \"consumes\": [\n        \"application/json\"\n    ],\n    \"produces\": [\n        \"application/json\"\n    ],\n    \"paths\": {\n        \"/cats\": {\n            \"get\": {\n                \"tags\": [\n                    \"Cats\"\n                ],\n                \"summary\": \"Get all cats in system\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/Cats\"\n                        }\n                    }\n                }\n            },\n            \"post\": {\n                \"tags\": [\n                    \"Cats\"\n                ],\n                \"summary\": \"Create a new cat in system\",\n                \"requestBody\": {\n                    \"description\": \"Cat Object\",\n                    \"required\": true,\n                    \"content\": {\n                        \"application/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#/definitions/Cat\"\n                            }\n                        }\n                    }\n                },\n                \"produces\": [\n                    \"application/json\"\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/id\"\n                        }\n                    },\n                    \"400\": {\n                        \"description\": \"Failed. Bad post data.\"\n                    }\n                }\n            }\n        },\n        \"/cats/{id}\": {\n            \"parameters\": [\n                {\n                    \"name\": \"id\",\n                    \"in\": \"path\",\n                    \"required\": true,\n                    \"description\": \"ID of the cat that we want to match\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"get\": {\n                \"tags\": [\n                    \"Cats\"\n                ],\n                \"summary\": \"Get cat with given ID\",\n                \"parameters\": [\n                    {\n                        \"in\": \"path\",\n                        \"name\": \"id\",\n                        \"required\": true,\n                        \"description\": \"Cat with id\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/id\"\n                        }\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/Cat\"\n                        }\n                    },\n                    \"404\": {\n                        \"description\": \"Failed. Cat not found.\"\n                    }\n                }\n            },\n            \"put\": {\n                \"summary\": \"Update cat with given ID\",\n                \"tags\": [\n                    \"Cats\"\n                ],\n                \"requestBody\": {\n                    \"description\": \"Cat Object\",\n                    \"required\": true,\n                    \"content\": {\n                        \"application/json\": {\n                            \"schema\": {\n                                \"$ref\": \"#/definitions/Cat\"\n                            }\n                        }\n                    }\n                },\n                \"parameters\": [\n                    {\n                        \"in\": \"path\",\n                        \"name\": \"id\",\n                        \"required\": true,\n                        \"description\": \"Cat with new values of properties\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/id\"\n                        }\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/Cat\"\n                        }\n                    },\n                    \"400\": {\n                        \"description\": \"Failed. Bad post data.\"\n                    },\n                    \"404\": {\n                        \"description\": \"Failed. Cat not found.\"\n                    }\n                }\n            },\n            \"delete\": {\n                \"summary\": \"Delete cat with given ID\",\n                \"tags\": [\n                    \"Cats\"\n                ],\n                \"parameters\": [\n                    {\n                        \"in\": \"path\",\n                        \"name\": \"id\",\n                        \"required\": true,\n                        \"description\": \"Delete Cat with id\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/id\"\n                        }\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"OK\",\n                        \"schema\": {\n                            \"$ref\": \"#/definitions/id\"\n                        }\n                    },\n                    \"404\": {\n                        \"description\": \"Failed. Cat not found.\"\n                    }\n                }\n            }\n        }\n    },\n    \"definitions\": {\n        \"id\": {\n            \"properties\": {\n                \"uuid\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"Cat\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"genus\": {\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"type\": \"string\"\n                },\n                \"isHungry\": {\n                    \"type\": \"boolean\"\n                },\n                \"lastFedDate\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"Cats\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"cats\": {\n                    \"type\": \"object\",\n                    \"additionalProperties\": {\n                        \"$ref\": \"#/definitions/Cat\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2017\",\n    \"module\": \"commonjs\",\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"outDir\": \"dist\",\n    //\"sourceMap\": true\n  },\n  \"files\": [\n    \"./node_modules/@types/node/index.d.ts\"\n  ],\n  \"include\": [\n    \"src/**/*.ts\"\n  ],\n  \"exclude\": [\n    \"node_modules\"\n  ]\n}"
  }
]