From ea8a8152a9134b82d17385c1b4eddc15084400ef Mon Sep 17 00:00:00 2001 From: Edward Park Date: Wed, 7 Oct 2020 10:15:41 -0700 Subject: [PATCH 1/8] add: swagger ui + jsdoc dependencies --- package.json | 2 + yarn.lock | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 73f608e..99c8917 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "mongoose-delete": "^0.5.2", "pg": "^8.3.3", "reflect-metadata": "^0.1.13", + "swagger-jsdoc": "^4.2.0", + "swagger-ui-express": "^4.1.4", "typeorm": "^0.2.25" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index fec4488..28ef25b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,37 @@ # yarn lockfile v1 +"@apidevtools/json-schema-ref-parser@^9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" + integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== + dependencies: + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + js-yaml "^3.13.1" + +"@apidevtools/openapi-schemas@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.0.4.tgz#bae1cef77ebb2b3705c7cc6911281da5153c1ab3" + integrity sha512-ob5c4UiaMYkb24pNhvfSABShAwpREvUGCkqjiz/BX9gKZ32y/S22M+ALIHftTAuv9KsFVSpVdIDzi9ZzFh5TCA== + +"@apidevtools/swagger-methods@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== + +"@apidevtools/swagger-parser@10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.2.tgz#f4145afb7c3a3bafe0376f003b5c3bdeae17a952" + integrity sha512-JFxcEyp8RlNHgBCE98nwuTkZT6eNFPc1aosWV6wPcQph72TSEEu1k3baJD4/x1qznU+JiDdz8F5pTwabZh+Dhg== + dependencies: + "@apidevtools/json-schema-ref-parser" "^9.0.6" + "@apidevtools/openapi-schemas" "^2.0.4" + "@apidevtools/swagger-methods" "^3.0.2" + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + z-schema "^4.2.3" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" @@ -365,6 +396,11 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + "@opencensus/core@^0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@opencensus/core/-/core-0.0.8.tgz#df01f200c2d2fbfe14dae129a1a86fb87286db92" @@ -1259,6 +1295,11 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1485,6 +1526,16 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +commander@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc" + integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA== + +commander@^2.7.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1775,7 +1826,7 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -doctrine@^3.0.0: +doctrine@3.0.0, doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== @@ -2528,7 +2579,7 @@ glob-parent@^5.0.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.1.6, glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3498,6 +3549,14 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -3733,6 +3792,11 @@ lodash.isboolean@^3.0.3: resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" @@ -5791,6 +5855,36 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" +swagger-jsdoc@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-4.2.0.tgz#f891d1f750e5bf6e8e9ede5e0a31bca566636180" + integrity sha512-QuEMMDddyiMQi/g5jlwtjc902xJe28n1Q9zbgqX0hBjcNybKPmrJykMElvlGtZ9CL0xk08OXNOZQUCEsk9kY0g== + dependencies: + commander "6.1.0" + doctrine "3.0.0" + glob "7.1.6" + js-yaml "3.14.0" + swagger-parser "10.0.2" + +swagger-parser@10.0.2: + version "10.0.2" + resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-10.0.2.tgz#d7f18faa09c9c145e938977c9bd6c3435998b667" + integrity sha512-9jHkHM+QXyLGFLk1DkXBwV+4HyNm0Za3b8/zk/+mjr8jgOSiqm3FOTHBSDsBjtn9scdL+8eWcHdupp2NLM8tDw== + dependencies: + "@apidevtools/swagger-parser" "10.0.2" + +swagger-ui-dist@^3.18.1: + version "3.35.0" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.35.0.tgz#af68c2164aba18847d951e6bee19f5b1e3aca98f" + integrity sha512-VdjOd7Lpj3LU6V/SG9BHZHTJ5cTk+uoyHBrGAeEP70SYf7GflLYqw7USUNxoraEx72vIA1wqogMv4GiRqMr8lA== + +swagger-ui-express@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz#8b814ad998b850a1cf90e71808d6d0a8a8daf742" + integrity sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g== + dependencies: + swagger-ui-dist "^3.18.1" + symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -6209,6 +6303,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validator@^12.0.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-12.2.0.tgz#660d47e96267033fd070096c3b1a6f2db4380a0a" + integrity sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -6516,3 +6615,14 @@ yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +z-schema@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-4.2.3.tgz#85f7eea7e6d4fe59a483462a98f511bd78fe9882" + integrity sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A== + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + validator "^12.0.0" + optionalDependencies: + commander "^2.7.1" From 054097531c6c7d273edf27d0e0ce73e016c1842b Mon Sep 17 00:00:00 2001 From: Edward Park Date: Wed, 7 Oct 2020 10:15:49 -0700 Subject: [PATCH 2/8] fix: docker-compose to include pg init --- docker-compose.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index dc7a283..529f979 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,20 @@ -version: '3' +version: "3" services: mongo: image: mongo:4 ports: - 27017:27017 + pg: + image: postgres:latest + ports: + - 9876:9876 + environment: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: test + PGPORT: 9876 + api: image: node:12-alpine command: yarn start From 72907c21fc0d59d8f70777b741d9df8203576dbd Mon Sep 17 00:00:00 2001 From: Edward Park Date: Wed, 7 Oct 2020 10:15:58 -0700 Subject: [PATCH 3/8] update: tsconfig to allow json resolution --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 29b44cc..e451d10 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -43,6 +43,7 @@ "baseUrl": "app", /* 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. */ + "resolveJsonModule": true, // "typeRoots": [], /* 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. */ From 364aade539c7185f8d8272cd8e40917485b93f44 Mon Sep 17 00:00:00 2001 From: Edward Park Date: Wed, 7 Oct 2020 10:16:04 -0700 Subject: [PATCH 4/8] add: swagger endpoint + init --- app/app.ts | 19 +++++++++++++++++++ app/routes/user.ts | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/app/app.ts b/app/app.ts index f16655b..11f50df 100644 --- a/app/app.ts +++ b/app/app.ts @@ -1,18 +1,37 @@ import express from 'express' import cors from 'cors' +const SwaggerJSDoc = require('swagger-jsdoc') +const SwaggerUI = require('swagger-ui-express') + import authentication from 'middlewares/authentication' import logErrors from 'middlewares/logErrors' import errorHandler from 'middlewares/errorHandler' import routes from 'routes' +import { version } from '../package.json' const port = process.env.PORT || 8080 const app: express.Application = express() +const swaggerSpec = SwaggerJSDoc({ + definition: { + info: { + title: 'Node TS Boilerplate', + description: 'A Node + Typescript boilerplate project', + version: version, + servers: [`http://localhost:${port}`], + }, + }, + + /* Can also configure wildcards within dirs (eg /routes/*.ts) */ + apis: ['/build/**/*.js'], +}) + app.use(cors()) app.use(express.json()) app.use(authentication) +app.use('/documentation', SwaggerUI.serve, SwaggerUI.setup(swaggerSpec)) app.get('/', function(req, res) { res.send({ title: 'Welcome to server', diff --git a/app/routes/user.ts b/app/routes/user.ts index aac2c03..8f6db10 100644 --- a/app/routes/user.ts +++ b/app/routes/user.ts @@ -5,6 +5,24 @@ import { authentication } from 'roleResolvers' const router = Router() +/** + * @swagger + * + * /api/users: + * post: + * description: Creates a user + * produces: + * - application/json + * parameters: + * - name: user + * description: User object + * in: body + * required: true + * type: string + * responses: + * 200: + * description: users + */ router.post('/', userServices.create) router.get('/', auth([authentication]), userServices.find) router.get('/:id', userServices.userMe, userServices.findById) From 5774ffa4dc8c0d56a853be1a77e731151f7a9911 Mon Sep 17 00:00:00 2001 From: Edward Park Date: Fri, 9 Oct 2020 15:54:05 -0700 Subject: [PATCH 5/8] fix swagger watch path --- app/app.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/app.ts b/app/app.ts index 11f50df..cf8af99 100644 --- a/app/app.ts +++ b/app/app.ts @@ -22,9 +22,7 @@ const swaggerSpec = SwaggerJSDoc({ servers: [`http://localhost:${port}`], }, }, - - /* Can also configure wildcards within dirs (eg /routes/*.ts) */ - apis: ['/build/**/*.js'], + apis: ['**/*.ts'], }) app.use(cors()) From 356959ba240f6f111166c558c72c8fbd351e8cbd Mon Sep 17 00:00:00 2001 From: Edward Park Date: Fri, 9 Oct 2020 15:54:12 -0700 Subject: [PATCH 6/8] add: post user route example --- app/routes/user.ts | 51 +++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/app/routes/user.ts b/app/routes/user.ts index 8f6db10..e39a66b 100644 --- a/app/routes/user.ts +++ b/app/routes/user.ts @@ -6,28 +6,47 @@ import { authentication } from 'roleResolvers' const router = Router() /** - * @swagger - * - * /api/users: - * post: - * description: Creates a user - * produces: - * - application/json - * parameters: - * - name: user - * description: User object - * in: body - * required: true - * type: string - * responses: - * 200: - * description: users + * Generate your Swagger spec by documenting your routes: + * https://swagger.io/specification/ + * https://jsdoc.app/ + * https://github.com/Surnet/swagger-jsdoc/blob/master/docs/GETTING-STARTED.md */ + +/** + * @swagger + * /api/users: + * post: + * description: Creates a user + * produces: + * - application/json + * parameters: + * - name: body + * description: new user attributes + * in: body + * required: true + * schema: + * type: object + * properties: + * email: + * type: string + * username: + * type: string + * password: + * type: string + * responses: + * 200: + * description: Created user + * */ router.post('/', userServices.create) + router.get('/', auth([authentication]), userServices.find) + router.get('/:id', userServices.userMe, userServices.findById) + router.patch('/:id', userServices.userMe, userServices.updateById) + // router.delete('/:id', userServices.deleteById) + router.post('/login', userServices.login) export default router From 3e63f9e88dae46395da970b01fd05454a95cc7ff Mon Sep 17 00:00:00 2001 From: Edward Park Date: Fri, 9 Oct 2020 16:00:37 -0700 Subject: [PATCH 7/8] enable explorer --- app/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.ts b/app/app.ts index cf8af99..c687249 100644 --- a/app/app.ts +++ b/app/app.ts @@ -29,7 +29,7 @@ app.use(cors()) app.use(express.json()) app.use(authentication) -app.use('/documentation', SwaggerUI.serve, SwaggerUI.setup(swaggerSpec)) +app.use('/documentation', SwaggerUI.serve, SwaggerUI.setup(swaggerSpec, { explorer: true })) app.get('/', function(req, res) { res.send({ title: 'Welcome to server', From 3e17a788644acfa2cec4a42ed912da092c28581a Mon Sep 17 00:00:00 2001 From: Edward Park Date: Fri, 9 Oct 2020 16:00:43 -0700 Subject: [PATCH 8/8] add: example jsdoc for swagger spec --- app/routes/user.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/routes/user.ts b/app/routes/user.ts index e39a66b..6a1cb8c 100644 --- a/app/routes/user.ts +++ b/app/routes/user.ts @@ -19,6 +19,8 @@ const router = Router() * description: Creates a user * produces: * - application/json + * tags: + * - User Routes * parameters: * - name: body * description: new user attributes