diff --git a/package-lock.json b/package-lock.json index 8280138..3676a6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "express-rate-limit": "^7.5.0", "install": "^0.13.0", "npm": "^11.1.0", - "pug": "^3.0.3" + "pug": "^3.0.3", + "swagger-ui-express": "^5.0.1" }, "devDependencies": { "jest": "^29.7.0", @@ -2205,6 +2206,21 @@ "node": ">= 10.0.0" } }, + "node_modules/express-jsdoc-swagger/node_modules/swagger-ui-express": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", + "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=4.11.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/express-rate-limit": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", @@ -7210,12 +7226,12 @@ } }, "node_modules/swagger-ui-express": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", - "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", "license": "MIT", "dependencies": { - "swagger-ui-dist": ">=4.11.0" + "swagger-ui-dist": ">=5.0.0" }, "engines": { "node": ">= v0.10.32" diff --git a/package.json b/package.json index db4d7a7..a82898b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "express-rate-limit": "^7.5.0", "install": "^0.13.0", "npm": "^11.1.0", - "pug": "^3.0.3" + "pug": "^3.0.3", + "swagger-ui-express": "^5.0.1" }, "devDependencies": { "jest": "^29.7.0", diff --git a/server.js b/server.js index 137dd90..186421e 100644 --- a/server.js +++ b/server.js @@ -12,6 +12,7 @@ const { handleAxiosError } = require("./utils/axios"); const ValidationFunctions = require('./validationFunctions'); const { urlUtils } = require("./utils/urlUtils"); const expressJSDocSwagger = require('express-jsdoc-swagger'); +const swaggerUi = require('swagger-ui-express') const fetchAiGeneratedContent = require('./runGeminiPrompt'); // Constants and Error Messages @@ -26,7 +27,7 @@ const SIZE_LIMIT_ERROR = 'Input exceeds maximum size of 10MB'; * each IP can make up to 1000 requests per `windowsMs` (1 minute) */ const limiter = rateLimit({ - windowMs: 1 * 60 * 1000, // 1 minute + windowMs: 1 * 60 * 1000, limit: 1000, standardHeaders: true, legacyHeaders: false, @@ -55,9 +56,9 @@ const options = { // URL where SwaggerUI will be rendered swaggerUIPath: '/api-docs', // Expose OpenAPI UI - exposeSwaggerUI: true, + exposeSwaggerUI: false, // Expose Open API JSON Docs documentation in `apiDocsPath` path. - exposeApiDocs: false, + exposeApiDocs: true, // Open API JSON Docs endpoint. apiDocsPath: '/v3/api-docs', // Set non-required fields as nullable by default @@ -65,13 +66,25 @@ const options = { // You can customize your UI options. // you can extend swagger-ui-express config. You can checkout an example of this // in the `example/configuration/swaggerOptions.js` - swaggerUiOptions: {}, + swaggerUiOptions: { + filter: true + }, // multiple option in case you want more that one instance multiple: true, }; + expressJSDocSwagger(app)(options); +app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(undefined, + { + swaggerOptions: { + url: '/v3/api-docs', + filter: true, + }, + ...options.swaggerUiOptions + } +)); app.use(limiter) @@ -144,7 +157,7 @@ app.use((err, req, res, next) => { * Contains request * @typedef {object} ContainsRequest * @property {string} inputString.required - Input string - * @property {string} stringContained.required - String contained + * @property {string} stringContained.required - String contained * @property {boolean} caseSensitive.required - Case sensitivity */ @@ -197,6 +210,7 @@ app.use((err, req, res, next) => { * @param {GeminiValidationRequest} request.body.required * @return {GeminiResponse} 200 - Success response * @return {BadRequestResponse} 400 - Bad request response + * @tags IsEmailAddress * @example request - test * { * "inputString": "test@gmail.com", @@ -409,7 +423,7 @@ app.post('/api/trim', (req, res) => { * @example request - test * { * "inputString": " Hello World! ", - * "containsString": "World", + * "stringContained": "World", * "caseSensitive": true * } * @example response - 200 - example payload @@ -423,8 +437,8 @@ app.post('/api/trim', (req, res) => { */ app.post('/api/contains', (req, res) => { const inputString = req.body.inputString; - const stringContained = req.body.stringContained - const caseSensitive = req.body.caseSensitive + const stringContained = req.body.stringContained; + const caseSensitive = req.body.caseSensitive; if (!inputString) { return res.status(400).json({ error: requiredParameterResponse }); @@ -434,13 +448,11 @@ app.post('/api/contains', (req, res) => { return res.status(400).json({ error: 'stringContained is a required parameter' }) } - // only throw an error if caseSensitive is not passed, which means it's undefiend. - // The ! operation won't work because when a boolean is passed, it will flip it, instead of checking if the value exists if (caseSensitive === undefined) { return res.status(400).json({ error: 'caseSensitive is a required parameter' }) } - const result = ValidationFunctions.contains(inputString, stringContained, caseSensitive) + const result = ValidationFunctions.contains(inputString, stringContained, caseSensitive); res.json({ result }); }); @@ -1132,4 +1144,4 @@ app.post('/api/isLatLong', (req, res) => { res.json({ result }); }); -module.exports = app; \ No newline at end of file +module.exports = app;