From 8c4f67b1063208e3e50173e9b92276c61da9ace1 Mon Sep 17 00:00:00 2001 From: Timo John Date: Fri, 26 Jun 2020 14:34:02 +0200 Subject: [PATCH] Implemented basic Swagger. Reachable by ./api/v1/doc --- backend/index.js | 45 +++++++ backend/package-lock.json | 247 ++++++++++++++++++++++++++++-------- backend/package.json | 4 +- backend/routes/climate.js | 34 ++++- backend/routes/countries.js | 37 ++++++ backend/routes/place.js | 52 ++++++++ backend/routes/regions.js | 67 ++++++++++ backend/routes/search.js | 54 ++++++++ backend/routes/update.js | 90 ++++++++++++- 9 files changed, 567 insertions(+), 63 deletions(-) diff --git a/backend/index.js b/backend/index.js index 4d48828..cc6b12c 100644 --- a/backend/index.js +++ b/backend/index.js @@ -20,6 +20,50 @@ const update = require("./routes/update"); const app = express(); +const swaggerJsdoc = require('swagger-jsdoc'); +const swaggerUi = require('swagger-ui-express'); + +const swaggerUIOptions = { + explorer: true +}; + +// Swagger set up +const swaggerJSOptions = { + swaggerDefinition: { + openapi: "3.0.0", + info: { + title: "Time to document that Express API you built", + version: "1.0.0", + description: + "A test project to understand how easy it is to document and Express API", + license: { + name: "Licensing Pending", + url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" + }, + contact: { + name: "travOpti", + url: "https://travopti.de/home", + email: "feedback@travopti.de" + } + }, + servers: [ + { + url: "https://travopti.de/api/v1" + } + ] + }, + apis: [ + "./Routes/search.js", + "./Routes/regions.js", + "./Routes/place.js", + "./Routes/countries.js", + "./Routes/climate.js", "./Models/handleClimateUpdate.js", "./Models/handleClimateUpdateV2.js", + "./Routes/update.js" + ] +}; + +const specs = swaggerJsdoc(swaggerJSOptions); + (async () => { try { const dbConn = await dbConnection(); @@ -29,6 +73,7 @@ const app = express(); app.use(express.static(path.join(__dirname, "../../dist"))); app.use(bodyParser.json()); app.use(cors()); + app.use('/api/v1/doc', swaggerUi.serve, swaggerUi.setup(specs, swaggerUIOptions)); // Express routes app.use(search(dbConn)); diff --git a/backend/package-lock.json b/backend/package-lock.json index 812b9c6..792f773 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4,6 +4,45 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz", + "integrity": "sha512-n4YBtwQhdpLto1BaUCyAeflizmIbaloGShsPyRtFf5qdFJxfssj+GgLavczgKJFa3Bq+3St2CKcpRJdjtB4EBw==", + "requires": { + "@jsdevtools/ono": "^7.1.0", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "@apidevtools/openapi-schemas": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.0.3.tgz", + "integrity": "sha512-QoPaxGXfgqgGpK1p21FJ400z56hV681a8DOcZt3J5z0WIHgFeaIZ4+6bX5ATqmOoCpRCsH4ITEwKaOyFMz7wOA==" + }, + "@apidevtools/swagger-methods": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.1.tgz", + "integrity": "sha512-1Vlm18XYW6Yg7uHunroXeunWz5FShPFAdxBbPy8H6niB2Elz9QQsCoYHMbcc11EL1pTxaIr9HXz2An/mHXlX1Q==" + }, + "@apidevtools/swagger-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-9.0.1.tgz", + "integrity": "sha512-Irqybg4dQrcHhZcxJc/UM4vO7Ksoj1Id5e+K94XUOzllqX1n47HEA50EKiXTCQbykxuJ4cYGIivjx/MRSTC5OA==", + "requires": { + "@apidevtools/json-schema-ref-parser": "^8.0.0", + "@apidevtools/openapi-schemas": "^2.0.2", + "@apidevtools/swagger-methods": "^3.0.0", + "@jsdevtools/ono": "^7.1.0", + "call-me-maybe": "^1.0.1", + "openapi-types": "^1.3.5", + "z-schema": "^4.2.2" + } + }, + "@jsdevtools/ono": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.2.tgz", + "integrity": "sha512-qS/a24RA5FEoiJS9wiv6Pwg2c/kiUo3IVUQcfeM9JvsR6pM8Yx+yl/6xWYLckZCT5jpLNhslgjiA8p/XcGyMRQ==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -50,29 +89,6 @@ "negotiator": "0.6.2" } }, - "agent-base": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", - "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -126,6 +142,14 @@ "picomatch": "^2.0.4" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -142,8 +166,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "basic-auth": { "version": "2.0.1", @@ -196,7 +219,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -248,6 +270,11 @@ } } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -342,11 +369,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "commander": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.0.0.tgz", + "integrity": "sha512-JrDGPAKjMGSP1G0DUoaceEJ3DZgAfr/q6X7FVk4+U5KxUSKviYGM2k6zWkfyyBHy5rAtzgYJFa1ro2O9PtoxwQ==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "configstore": { "version": "5.0.1", @@ -444,6 +475,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, "dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", @@ -505,6 +544,11 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -598,6 +642,11 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, "fsevents": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", @@ -622,6 +671,19 @@ "pump": "^3.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -700,30 +762,6 @@ "resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz", "integrity": "sha1-5NNH/omEpi9GfUBg31J/GFH2mXs=" }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -750,6 +788,15 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -856,6 +903,15 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -885,6 +941,16 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -988,7 +1054,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1169,11 +1234,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } }, + "openapi-types": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-1.3.5.tgz", + "integrity": "sha512-11oi4zYorsgvg5yBarZplAqbpev5HkuVNPlZaPTknPDzAynq+lnJdXAmruGWP0s+dNYZS7bjM+xrTpJw7184Fg==" + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -1214,6 +1283,11 @@ "util": "^0.10.3" } }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1452,6 +1526,11 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "sqlstring": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", @@ -1526,6 +1605,39 @@ "has-flag": "^3.0.0" } }, + "swagger-jsdoc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-4.0.0.tgz", + "integrity": "sha512-wHrmRvE/OQa3d387YIrRNPvsPwxkJc0tAYeCVa359gUIKPjC4ReduFhqq/+4erLUS79kY1T5Fv0hE0SV/PgBig==", + "requires": { + "commander": "5.0.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "js-yaml": "3.13.1", + "swagger-parser": "9.0.1" + } + }, + "swagger-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-9.0.1.tgz", + "integrity": "sha512-oxOHUaeNetO9ChhTJm2fD+48DbGbLD09ZEOwPOWEqcW8J6zmjWxutXtSuOiXsoRgDWvORYlImbwM21Pn+EiuvQ==", + "requires": { + "@apidevtools/swagger-parser": "9.0.1" + } + }, + "swagger-ui-dist": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.27.0.tgz", + "integrity": "sha512-dlbH4L8+UslXVeYvCulicmJP2cnHLoabQGfeav5lx74fM+tMQW53M8iqpH5wbBqBbFkZwza+IIWoPrenqO/F2g==" + }, + "swagger-ui-express": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz", + "integrity": "sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g==", + "requires": { + "swagger-ui-dist": "^3.18.1" + } + }, "term-size": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", @@ -1651,6 +1763,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "validator": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz", + "integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -1668,8 +1785,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", @@ -1693,6 +1809,25 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "z-schema": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.3.tgz", + "integrity": "sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==", + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^12.0.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "optional": true + } + } } } } diff --git a/backend/package.json b/backend/package.json index 5ae1253..af8739e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,7 +21,9 @@ "morgan": "^1.10.0", "mysql2": "^2.1.0", "path": "^0.12.7", - "sqlstring": "^2.3.2" + "sqlstring": "^2.3.2", + "swagger-jsdoc": "^4.0.0", + "swagger-ui-express": "^4.1.4" }, "devDependencies": { "nodemon": "^2.0.4" diff --git a/backend/routes/climate.js b/backend/routes/climate.js index 672a588..5a42463 100644 --- a/backend/routes/climate.js +++ b/backend/routes/climate.js @@ -1,16 +1,46 @@ +/** + * @swagger + * tags: + * name: Climate + * description: Climate data acquiration + */ + const router = require("express").Router() // Models const handleClimateUpdate = require("../models/handleClimateUpdate.js") const handleClimateUpdateV2 = require("../models/handleClimateUpdateV2.js") + module.exports = dbConn => { - router.put("/api/v1/climate/update", async (req, res) => { + /** + * @swagger + * path: + * /climate/update: + * patch: + * summary: Pull monthly data from meteostat API V1 + * tags: [Climate] + * responses: + * "200": + * description: Update information is logged in backend + */ + router.patch("/api/v1/climate/update", async (req, res) => { const update = await handleClimateUpdate(dbConn) res.json(update) }); - router.put("/api/v1/climate/update/v2", async (req, res) => { + /** + * @swagger + * path: + * /climate/update/v2: + * patch: + * summary: Pull daily data from meteostat API V2 + * tags: [Climate] + * responses: + * "200": + * description: Update information is logged in backend + */ + router.patch("/api/v1/climate/update/v2", async (req, res) => { const update = await handleClimateUpdateV2(dbConn) res.json(update) }); diff --git a/backend/routes/countries.js b/backend/routes/countries.js index 23407db..04b05ec 100644 --- a/backend/routes/countries.js +++ b/backend/routes/countries.js @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: Countries + * description: Access country data + */ + const router = require("express").Router(); // Models @@ -8,10 +15,40 @@ const getCountryById = require("../models/getCountryById.js"); const sqlSanitzer = require("../util/sqlstring_sanitizer.js") module.exports = dbConn => { + /** + * @swagger + * path: + * /countries: + * get: + * summary: Get all countries + * tags: [Countries] + * responses: + * "200": + * description: Returns all countries and aviable data + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/countries", async (req, res) => { res.json(await getCountries(dbConn)); }); + /** + * @swagger + * path: + * /countries/:id: + * get: + * summary: Get a specific country by ID + * tags: [Countries] + * responses: + * "200": + * description: Returns the selected country and aviable data + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/countries/:id", async (req, res) => { const id = sqlSanitzer(req.params.id); res.json(await getCountryById(dbConn, id)) diff --git a/backend/routes/place.js b/backend/routes/place.js index 80bd9b2..b3f7e55 100644 --- a/backend/routes/place.js +++ b/backend/routes/place.js @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: Places + * description: Access to the Google Place API + */ + const router = require("express").Router() // Models @@ -9,11 +16,41 @@ const getPlacePhoto = require("../models/getPlacePhoto.js") const sqlSanitzer = require("../util/sqlstring_sanitizer.js") module.exports = dbConn => { + /** + * @swagger + * path: + * /place: + * get: + * summary: Get a specific place + * tags: [Places] + * responses: + * "200": + * description: Returns a place from the google places API. + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/place", async (req, res) => { const place = await getPlace(req.query.q) res.json(place) }); + /** + * @swagger + * path: + * /place/nearby: + * get: + * summary: Get nearby places + * tags: [Places] + * responses: + * "200": + * description: Returns nearby places from the google places API. + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/place/nearby", async (req, res) => { const lat = req.query.lat const lng = req.query.lng @@ -21,6 +58,21 @@ module.exports = dbConn => { res.json(place) }); + /** + * @swagger + * path: + * /place/photo: + * get: + * summary: Get a photo for a place + * tags: [Places] + * responses: + * "200": + * description: Returns the matching photo for a photo_reference. + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/place/photo", async (req, res) => { const photoref = req.query.photoref const photo = await getPlacePhoto(photoref) diff --git a/backend/routes/regions.js b/backend/routes/regions.js index 9ede6e5..501855b 100644 --- a/backend/routes/regions.js +++ b/backend/routes/regions.js @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: Regions + * description: Access region data + */ + const router = require("express").Router(); // Models @@ -12,6 +19,21 @@ const _ = require('lodash') const sqlSanitzer = require("../util/sqlstring_sanitizer.js") module.exports = dbConn => { + /** + * @swagger + * path: + * /regions: + * get: + * summary: Get all regions + * tags: [Regions] + * responses: + * "200": + * description: Returns all regions and aviable data + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/regions", async (req, res) => { const data = await getRegions(dbConn) if (req.query.randomize) { @@ -22,6 +44,21 @@ module.exports = dbConn => { } }); + /** + * @swagger + * path: + * /regions/:id: + * get: + * summary: Get a specific region + * tags: [Regions] + * responses: + * "200": + * description: Returns the specific region and aviable data + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/regions/:id", async (req, res) => { console.log(typeof req.params.id) const id = sqlSanitzer(req.params.id); @@ -29,6 +66,21 @@ module.exports = dbConn => { res.json(await getRegionById(dbConn, id)) }); + /** + * @swagger + * path: + * /regions/:id/image: + * get: + * summary: Get all country + * tags: [Regions] + * responses: + * "200": + * description: Returns the image for a specific region + * content: + * application/json: + * schema: + * $ref: '' + */ router.get('/api/v1/regions/:id/image', (req, res) => { if (fs.existsSync(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`))) { res.sendFile(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`)) @@ -37,6 +89,21 @@ module.exports = dbConn => { } }) + /** + * @swagger + * path: + * /regions/:id/nearby: + * get: + * summary: Get nearby places for a specific region + * tags: [Regions] + * responses: + * "200": + * description: Returns nearby places for a specific region + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/regions/:id/nearby", async (req,res) => { const id = sqlSanitzer(req.params.id); res.json(await getRegionNearbyById(dbConn,id)) diff --git a/backend/routes/search.js b/backend/routes/search.js index 43c390e..2a67fde 100644 --- a/backend/routes/search.js +++ b/backend/routes/search.js @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: Search + * description: Access the information for the search + */ + const router = require("express").Router(); // Models @@ -12,8 +19,55 @@ const oldToNewQuerySyntax = require("../util/oldToNewQuerySyntax.js") const { getUniqueTags } = require("../models/getTags.js"); module.exports = dbConn => { + /** + * @swagger + * path: + * /search: + * get: + * summary: Get Searchresults + * tags: [Search] + * responses: + * "200": + * description: Returns the region information and scores for the searchresults + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/search", searchHandler(dbConn)); + + /** + * @swagger + * path: + * /search/presets: + * get: + * summary: Get the presets for the search parameters + * tags: [Search] + * responses: + * "200": + * description: Returns all presets for the search parameters + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/search/presets", presetHandler(dbConn)); + + /** + * @swagger + * path: + * /search/tags: + * get: + * summary: Get the existing searchtags + * tags: [Search] + * responses: + * "200": + * description: Returns all existing searchtags + * content: + * application/json: + * schema: + * $ref: '' + */ router.get("/api/v1/search/tags", tagsHandler(dbConn)); return router; diff --git a/backend/routes/update.js b/backend/routes/update.js index 4ef9eae..fd0f523 100644 --- a/backend/routes/update.js +++ b/backend/routes/update.js @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: Update + * description: Endpoint for updating region specific data + */ + const router = require("express").Router(); // Models @@ -10,23 +17,98 @@ const handleUpdateRegionNearbyImgUrlById = require("../models/handleUpdateRegion const sqlSanitzer = require("../util/sqlstring_sanitizer.js") module.exports = dbConn => { + /** + * @swagger + * path: + * /update/regions/all/nearby: + * patch: + * summary: Updates all nearby data for all regions + * tags: [Update] + * responses: + * "200": + * description: Updates all nearby data for all regions + * content: + * application/json: + * schema: + * $ref: '' + */ router.patch("/api/v1/update/regions/all/nearby", async (req, res) => { res.json(await handleUpdateRegionNearby(dbConn)) }); + /** + * @swagger + * path: + * /update/regions/all/lonlat: + * patch: + * summary: Updates all coordinate data for all regions + * tags: [Update] + * responses: + * "200": + * description: Updates all coordinate data for all regions + * content: + * application/json: + * schema: + * $ref: '' + */ router.patch("/api/v1/update/regions/all/lonlat", async (req,res) => { res.json(await handleRegionLonLat(dbConn)) }); + /** + * @swagger + * path: + * /update/regions/all/nearby/imgurl: + * patch: + * summary: Updates the nearby imgurls for all regions + * tags: [Update] + * responses: + * "200": + * description: Updates the nearby imgurls for all regions + * content: + * application/json: + * schema: + * $ref: '' + */ + router.patch("/api/v1/update/regions/all/nearby/imgurl", async (req, res) => { + res.json(await handleUpdateRegionNearbyImgUrl(dbConn)) + }); + + /** + * @swagger + * path: + * /update/regions/:id/nearby: + * patch: + * summary: Updates the nearby data for a specific region + * tags: [Update] + * responses: + * "200": + * description: Updates the nearby data for a specific region + * content: + * application/json: + * schema: + * $ref: '' + */ router.patch("/api/v1/update/regions/:id/nearby", async (req, res) => { const id = sqlSanitzer(req.params.id); res.json(await handleUpdateRegionNearbyById(dbConn, id)) }); - router.patch("/api/v1/update/regions/all/nearby/imgurl", async (req, res) => { - res.json(await handleUpdateRegionNearbyImgUrl(dbConn)) - }); - + /** + * @swagger + * path: + * /update/regions/:id/nearby/imgurl: + * patch: + * summary: Updates the nearby imgurls for a specific region + * tags: [Update] + * responses: + * "200": + * description: Updates the nearby imgurls for a specific region + * content: + * application/json: + * schema: + * $ref: '' + */ router.patch("/api/v1/update/regions/:id/nearby/imgurl", async (req, res) => { const id = sqlSanitzer(req.params.id); res.json(await handleUpdateRegionNearbyImgUrlById(dbConn, id))