From 58a2fde8fb0c3ad264c2703e2ccf9073b791f69d Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 13 Aug 2025 03:12:59 -0300 Subject: [PATCH 1/4] feat: add filter by tag - swagger --- server.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/server.js b/server.js index 137dd90..f1d06bc 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} containsString.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", @@ -423,24 +437,22 @@ 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 containsString = req.body.containsString; // <-- cambia aquí + const caseSensitive = req.body.caseSensitive; if (!inputString) { return res.status(400).json({ error: requiredParameterResponse }); } - if (!stringContained) { - return res.status(400).json({ error: 'stringContained is a required parameter' }) + if (!containsString) { // <-- cambia aquí + return res.status(400).json({ error: 'containsString 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, containsString, caseSensitive); // <-- cambia aquí res.json({ result }); }); From 0f210bab4dd9143b0a04b5229d712c07fc94baa6 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 13 Aug 2025 03:13:14 -0300 Subject: [PATCH 2/4] add swagger-ui-express --- package-lock.json | 26 +++++++++++++++++++++----- package.json | 3 ++- 2 files changed, 23 insertions(+), 6 deletions(-) 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", From 8365926ba25cac5452d31491fa4ace66452b1b25 Mon Sep 17 00:00:00 2001 From: Facundo Hernando <91550030+Facu00H@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:21:29 -0300 Subject: [PATCH 3/4] Update server.js --- server.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server.js b/server.js index f1d06bc..c433f5a 100644 --- a/server.js +++ b/server.js @@ -157,7 +157,7 @@ app.use((err, req, res, next) => { * Contains request * @typedef {object} ContainsRequest * @property {string} inputString.required - Input string - * @property {string} containsString.required - String contained + * @property {string} stringContained.required - String contained * @property {boolean} caseSensitive.required - Case sensitivity */ @@ -423,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 @@ -437,22 +437,22 @@ app.post('/api/trim', (req, res) => { */ app.post('/api/contains', (req, res) => { const inputString = req.body.inputString; - const containsString = req.body.containsString; // <-- cambia aquí + const stringContained = req.body.stringContained; const caseSensitive = req.body.caseSensitive; if (!inputString) { return res.status(400).json({ error: requiredParameterResponse }); } - if (!containsString) { // <-- cambia aquí - return res.status(400).json({ error: 'containsString is a required parameter' }) + if (!stringContained) { + return res.status(400).json({ error: 'stringContained is a required parameter' }) } if (caseSensitive === undefined) { return res.status(400).json({ error: 'caseSensitive is a required parameter' }) } - const result = ValidationFunctions.contains(inputString, containsString, caseSensitive); // <-- cambia aquí + const result = ValidationFunctions.contains(inputString, stringContained, caseSensitive); // <-- cambia aquí res.json({ result }); }); @@ -1144,4 +1144,4 @@ app.post('/api/isLatLong', (req, res) => { res.json({ result }); }); -module.exports = app; \ No newline at end of file +module.exports = app; From 117990393277d0d0126f63e8528641219dee15f5 Mon Sep 17 00:00:00 2001 From: Facundo Hernando <91550030+Facu00H@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:22:26 -0300 Subject: [PATCH 4/4] Update server.js --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index c433f5a..186421e 100644 --- a/server.js +++ b/server.js @@ -452,7 +452,7 @@ app.post('/api/contains', (req, res) => { return res.status(400).json({ error: 'caseSensitive is a required parameter' }) } - const result = ValidationFunctions.contains(inputString, stringContained, caseSensitive); // <-- cambia aquí + const result = ValidationFunctions.contains(inputString, stringContained, caseSensitive); res.json({ result }); });