diff --git a/extra/swagger.js b/extra/swagger.js new file mode 100644 index 00000000..3ee3f7f6 --- /dev/null +++ b/extra/swagger.js @@ -0,0 +1,25 @@ +/* npm run swagger-autogen */ + +const swaggerAutogen = require("swagger-autogen")(); + +const doc = { + info: { + title: "Uptime Kuma API", + description: "Autogen by swagger-autogen", + }, + host: "localhost:3001", + schemes: [ "http" ], +}; + +// The working directory is root +const outputFile = "./swagger.json"; + +const endpointsFiles = [ + "./server/routers/api-router.js", +]; + +/* NOTE: if you use the express Router, you must pass in the + 'endpointsFiles' only the root file where the route starts, + such as index.js, app.js, routes.js, ... */ + +swaggerAutogen(outputFile, endpointsFiles, doc); diff --git a/package-lock.json b/package-lock.json index b2452a4e..12ca8157 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "uptime-kuma", - "version": "1.17.0", + "version": "1.17.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "1.17.0", + "version": "1.17.1", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-svg-core": "~1.2.36", @@ -60,6 +60,7 @@ "socket.io": "~4.4.1", "socket.io-client": "~4.4.1", "socks-proxy-agent": "^6.1.1", + "swagger-ui-express": "^4.4.0", "tar": "^6.1.11", "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", @@ -103,6 +104,7 @@ "sass": "~1.42.1", "stylelint": "~14.7.1", "stylelint-config-standard": "~25.0.0", + "swagger-autogen": "^2.21.3", "typescript": "~4.4.4", "vite": "~2.9.9", "vite-plugin-compression": "^0.5.1", @@ -16911,6 +16913,37 @@ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", "dev": true }, + "node_modules/swagger-autogen": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.21.3.tgz", + "integrity": "sha512-i0m5SzEp6Y7J/kB89v11mQhbeCnDp3FA+wPTXeA5PvGFHGt9SvfBmYRaQMvTrKpW515eXoD1YJtWp5jOjKfdwg==", + "dev": true, + "dependencies": { + "acorn": "^7.4.1", + "deepmerge": "^4.2.2", + "glob": "^7.1.7", + "json5": "^2.2.1" + } + }, + "node_modules/swagger-ui-dist": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.12.0.tgz", + "integrity": "sha512-B0Iy2ueXtbByE6OOyHTi3lFQkpPi/L7kFOKFeKTr44za7dJIELa9kzaca6GkndCgpK1QTjArnoXG+aUy0XQp1w==" + }, + "node_modules/swagger-ui-express": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.4.0.tgz", + "integrity": "sha512-1CzRkHG386VQMVZK406jcpgnW2a9A5A/NiAjKhsFTQqUBWRF+uGbXTU/mA7WSV3mTzyOQDvjBdWP/c2qd5lqKw==", + "dependencies": { + "swagger-ui-dist": ">=4.11.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -31341,6 +31374,31 @@ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", "dev": true }, + "swagger-autogen": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.21.3.tgz", + "integrity": "sha512-i0m5SzEp6Y7J/kB89v11mQhbeCnDp3FA+wPTXeA5PvGFHGt9SvfBmYRaQMvTrKpW515eXoD1YJtWp5jOjKfdwg==", + "dev": true, + "requires": { + "acorn": "^7.4.1", + "deepmerge": "^4.2.2", + "glob": "^7.1.7", + "json5": "^2.2.1" + } + }, + "swagger-ui-dist": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.12.0.tgz", + "integrity": "sha512-B0Iy2ueXtbByE6OOyHTi3lFQkpPi/L7kFOKFeKTr44za7dJIELa9kzaca6GkndCgpK1QTjArnoXG+aUy0XQp1w==" + }, + "swagger-ui-express": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.4.0.tgz", + "integrity": "sha512-1CzRkHG386VQMVZK406jcpgnW2a9A5A/NiAjKhsFTQqUBWRF+uGbXTU/mA7WSV3mTzyOQDvjBdWP/c2qd5lqKw==", + "requires": { + "swagger-ui-dist": ">=4.11.0" + } + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 15bb2169..2c802c83 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,8 @@ "release-final": "node extra/update-version.js && npm run build-docker && node ./extra/press-any-key.js && npm run upload-artifacts && node ./extra/update-wiki-version.js", "release-beta": "node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts", "git-remove-tag": "git tag -d", - "build-dist-and-restart": "npm run build && npm run start-server-dev" + "build-dist-and-restart": "npm run build && npm run start-server-dev", + "swagger-autogen": "node ./extra/swagger.js" }, "dependencies": { "@fortawesome/fontawesome-svg-core": "~1.2.36", @@ -112,6 +113,7 @@ "socket.io": "~4.4.1", "socket.io-client": "~4.4.1", "socks-proxy-agent": "^6.1.1", + "swagger-ui-express": "^4.4.0", "tar": "^6.1.11", "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", @@ -155,6 +157,7 @@ "sass": "~1.42.1", "stylelint": "~14.7.1", "stylelint-config-standard": "~25.0.0", + "swagger-autogen": "^2.21.3", "typescript": "~4.4.4", "vite": "~2.9.9", "vite-plugin-compression": "^0.5.1", diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 605ba533..f7cd07c8 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -7,6 +7,8 @@ const { R } = require("redbean-node"); const { log } = require("../src/util"); const Database = require("./database"); const util = require("util"); +const swaggerUi = require("swagger-ui-express"); +const checkVersion = require("./check-version"); /** * `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue. @@ -50,6 +52,13 @@ class UptimeKumaServer { log.info("server", "Creating express and socket.io instance"); this.app = express(); + // TODO swaggerDocument.host should be match current base url! + const swaggerDocument = require("../swagger.json"); + swaggerDocument.info.version = checkVersion.version; + + // TODO it should be optional and configurable in the settings + this.app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + if (sslKey && sslCert) { log.info("server", "Server Type: HTTPS"); this.httpServer = https.createServer({ diff --git a/swagger.json b/swagger.json new file mode 100644 index 00000000..d2465b8e --- /dev/null +++ b/swagger.json @@ -0,0 +1,283 @@ +{ + "swagger": "2.0", + "info": { + "title": "Uptime Kuma API", + "description": "Autogen by swagger-autogen", + "version": "1.0.0" + }, + "host": "localhost:3001", + "basePath": "/", + "schemes": [ + "http" + ], + "paths": { + "/api/entry-page": { + "get": { + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/push/{pushToken}": { + "get": { + "description": "", + "parameters": [ + { + "name": "pushToken", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "msg", + "in": "query", + "type": "string" + }, + { + "name": "ping", + "in": "query", + "type": "string" + }, + { + "name": "status", + "in": "query", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "404": { + "description": "Not Found" + } + } + } + }, + "/api/badge/{id}/status": { + "get": { + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "label", + "in": "query", + "type": "string" + }, + { + "name": "upLabel", + "in": "query", + "type": "string" + }, + { + "name": "downLabel", + "in": "query", + "type": "string" + }, + { + "name": "upColor", + "in": "query", + "type": "string" + }, + { + "name": "downColor", + "in": "query", + "type": "string" + }, + { + "name": "style", + "in": "query", + "type": "string" + }, + { + "name": "value", + "in": "query", + "type": "string" + }, + { + "name": "Access-Control-Allow-Origin", + "in": "header", + "type": "string" + }, + { + "name": "Access-Control-Allow-Headers", + "in": "header", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/badge/{id}/uptime/{duration?}": { + "get": { + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "duration?", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "label", + "in": "query", + "type": "string" + }, + { + "name": "labelPrefix", + "in": "query", + "type": "string" + }, + { + "name": "labelSuffix", + "in": "query", + "type": "string" + }, + { + "name": "prefix", + "in": "query", + "type": "string" + }, + { + "name": "suffix", + "in": "query", + "type": "string" + }, + { + "name": "color", + "in": "query", + "type": "string" + }, + { + "name": "labelColor", + "in": "query", + "type": "string" + }, + { + "name": "style", + "in": "query", + "type": "string" + }, + { + "name": "value", + "in": "query", + "type": "string" + }, + { + "name": "Access-Control-Allow-Origin", + "in": "header", + "type": "string" + }, + { + "name": "Access-Control-Allow-Headers", + "in": "header", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/badge/{id}/ping/{duration?}": { + "get": { + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "duration?", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "label", + "in": "query", + "type": "string" + }, + { + "name": "labelPrefix", + "in": "query", + "type": "string" + }, + { + "name": "labelSuffix", + "in": "query", + "type": "string" + }, + { + "name": "prefix", + "in": "query", + "type": "string" + }, + { + "name": "suffix", + "in": "query", + "type": "string" + }, + { + "name": "color", + "in": "query", + "type": "string" + }, + { + "name": "labelColor", + "in": "query", + "type": "string" + }, + { + "name": "style", + "in": "query", + "type": "string" + }, + { + "name": "value", + "in": "query", + "type": "string" + }, + { + "name": "Access-Control-Allow-Origin", + "in": "header", + "type": "string" + }, + { + "name": "Access-Control-Allow-Headers", + "in": "header", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + } +} \ No newline at end of file