From 71b56db909e51c88c0d1a5eddec5eb0ba7bae322 Mon Sep 17 00:00:00 2001 From: Raj Nandan Sharma Date: Tue, 19 Nov 2024 11:11:58 +0530 Subject: [PATCH] docs: added api reference --- Dockerfile | 1 + docs/kener-apis.md | 18 + main.js | 33 ++ openapi.json | 971 +++++++++++++++++++++++++++++++ openapi.yaml | 708 ++++++++++++++++++++++ package-lock.json | 63 ++ package.json | 1 + src/routes/(docs)/+layout.svelte | 1 + 8 files changed, 1796 insertions(+) create mode 100644 openapi.json create mode 100644 openapi.yaml diff --git a/Dockerfile b/Dockerfile index ef4e950..0c1b88f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,6 +45,7 @@ COPY --chown=abc:abc static /app/static COPY --chown=abc:abc database /app/database COPY --chown=abc:abc build.js /app/build.js COPY --chown=abc:abc sitemap.js /app/sitemap.js +COPY --chown=abc:abc openapi.json /app/openapi.json COPY --chown=abc:abc src/lib/server /app/src/lib/server COPY --chown=abc:abc src/lib/helpers.js /app/src/lib/helpers.js diff --git a/docs/kener-apis.md b/docs/kener-apis.md index e19a31e..4b682a3 100644 --- a/docs/kener-apis.md +++ b/docs/kener-apis.md @@ -13,6 +13,24 @@ export API_TOKEN=some-token-set-by-you Additonally you can set IP whitelisting by setting another environment token called `API_IP` or `API_IP_REGEX`. If you set both `API_IP` and `API_IP_REGEX`, `API_IP` will be given preference. Read more [here](/docs/environment-vars#api_ip) +## Interactive API Reference + +

+ + + 🤖 + + + Click here to view the interactive API reference + + +

+ +You can download the openapi spec + +- [JSON](https://raw.githubusercontent.com/rajnandan1/kener/main/openapi.json) +- [YAML](https://raw.githubusercontent.com/rajnandan1/kener/main/openapi.yaml) + --- ## Update Status - API diff --git a/main.js b/main.js index 19dd89a..60d52c0 100644 --- a/main.js +++ b/main.js @@ -1,8 +1,10 @@ import { handler } from "./build/handler.js"; +import { apiReference } from "@scalar/express-api-reference"; import dotenv from "dotenv"; dotenv.config(); import express from "express"; import sitemap from "./sitemap.js"; +import fs from "fs-extra"; const PORT = process.env.PORT || 3000; const app = express(); @@ -16,10 +18,41 @@ app.use((req, res, next) => { app.get("/healthcheck", (req, res) => { res.end("ok"); }); + +try { + const openapiJSON = fs.readFileSync("./openapi.json", "utf-8"); + app.use( + "/api-reference", + apiReference({ + spec: { + content: openapiJSON + }, + theme: "alternate", + hideModels: true, + hideTestRequestButton: true, + darkMode: true, + metaData: { + title: "Kener API Reference", + description: "Kener free open source status page API Reference", + ogDescription: "Kener free open source status page API Reference", + ogTitle: "Kener API Reference", + ogImage: "https://kener.ing/newbg.png", + twitterCard: "summary_large_image", + twitterTitle: "Kener API Reference", + twitterDescription: "Kener free open source status page API Reference", + twitterImage: "https://kener.ing/newbg.png" + }, + favicon: "https://kener.ing/logo96.png" + }) + ); +} catch (e) { + console.warn("Error loading openapi.json, but that is okay."); +} app.get("/sitemap.xml", (req, res) => { res.setHeader("Content-Type", "application/xml"); res.end(sitemap); }); + app.use(handler); app.listen(PORT, () => { diff --git a/openapi.json b/openapi.json new file mode 100644 index 0000000..899f890 --- /dev/null +++ b/openapi.json @@ -0,0 +1,971 @@ +{ + "info": { + "title": "Kener API", + "version": "1.0.0", + "description": "# Kener Self-hosted node js status page\n![Kener](https://kener.ing/newbg.png \"kener\")\nAPI specification for Kener status page and incident management system. This API spec was created using [Frogment](https://www.frogment.app)\n", + "contact": { + "name": "Raj Nandan Sharma", + "email": "rajnandan1@gmail.com", + "url": "https://github.com/rajnandan1/kener/issues" + }, + "license": { + "name": "MIT", + "url": "https://opensource.org/licenses/MIT" + } + }, + "openapi": "3.0.0", + "servers": [ + { + "url": "https://your-kener-host.com", + "description": "Kener host URL" + } + ], + "tags": [ + { + "name": "Monitors", + "description": "APIs to interact with monitors" + }, + { + "name": "Incidents", + "description": "APIs to integrate incidents" + } + ], + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT", + "description": "enter your api key here" + } + }, + "schemas": { + "MonitorStatus": { + "type": "object", + "description": "Monitor Status", + "required": ["status", "latency", "tag"], + "properties": { + "status": { + "type": "string", + "example": "UP", + "enum": ["UP", "DOWN", "DEGRADED"] + }, + "latency": { + "type": "number", + "description": "In seconds", + "example": 100 + }, + "timestampInSeconds": { + "type": "integer", + "description": "UTC timestamp in seconds", + "example": 1731251760 + }, + "tag": { + "type": "string", + "example": "earth", + "description": "Tag of a monitor" + } + }, + "example": { + "status": "UP", + "timestampInSeconds": 1731251760, + "latency": 100, + "tag": "earth" + } + }, + "StatusResponse": { + "type": "object", + "description": "Status of a monitor given a tag", + "properties": { + "status": { + "type": "string", + "example": "UP", + "enum": ["UP", "DOWN", "DEGRADED"] + }, + "uptime": { + "type": "string", + "example": "100" + }, + "lastUpdatedAt": { + "type": "integer", + "example": 1731251760 + } + }, + "example": { + "status": "UP", + "lastUpdatedAt": 1731251760, + "uptime": "100" + } + }, + "Incident": { + "type": "object", + "description": "body of an incident", + "required": ["title", "tags"], + "properties": { + "startDatetime": { + "type": "integer", + "description": "UTC timestamp in seconds", + "example": 1731901920 + }, + "endDatetime": { + "type": "integer", + "description": "UTC timestamp in seconds", + "example": 1704123938 + }, + "title": { + "type": "string", + "example": "Outage in mumbai", + "description": "title of the incident" + }, + "body": { + "type": "string", + "example": "body of the incident", + "description": "body of the incident" + }, + "tags": { + "type": "array", + "items": { + "type": "string", + "example": "earth" + }, + "description": "comma separated tags of monitors", + "example": ["earth", "google"] + }, + "impact": { + "type": "string", + "example": "DOWN", + "description": "Impact of the incident", + "enum": ["DOWN", "DEGRADED"] + }, + "isMaintenance": { + "type": "boolean", + "description": "is this incident because of maintenance", + "example": false + }, + "isIdentified": { + "type": "boolean", + "description": "has the incident been indentified", + "example": true + }, + "isResolved": { + "type": "boolean", + "description": "has the incident been resovled", + "example": true + } + }, + "example": { + "startDatetime": 1731901920, + "endDatetime": 1704123938, + "title": "title of the incident", + "body": "body of the incident", + "tags": ["earth", "google"], + "impact": "DOWN", + "isMaintenance": false, + "isIdentified": true, + "isResolved": true + } + }, + "IncidentResponse": { + "description": "Incident response schema", + "allOf": [ + { + "$ref": "#/components/schemas/Incident" + }, + { + "type": "object", + "properties": { + "createdAt": { + "type": "integer", + "description": "UTC timestamp in seconds, incident created at", + "example": 1731901920 + }, + "closedAt": { + "type": "integer", + "nullable": true, + "description": "UTC timestamp in seconds, incident closed at", + "example": 1731901920 + }, + "incidentNumber": { + "type": "integer", + "description": "id of the incident", + "example": 4 + } + }, + "example": { + "createdAt": 1731901920, + "closedAt": 1731901920, + "incidentNumber": 4 + } + } + ] + }, + "Comment": { + "type": "object", + "description": "Comment of an incident", + "required": ["body"], + "properties": { + "body": { + "type": "string", + "example": "comment 1" + } + }, + "example": { + "body": "comment 2" + } + }, + "CommentResponse": { + "type": "object", + "description": "Comment Response", + "properties": { + "commentID": { + "type": "integer", + "description": "ID of the comment", + "example": 1873376745 + }, + "body": { + "type": "string", + "description": "body of the comment", + "example": "comment 3" + }, + "createdAt": { + "type": "integer", + "description": "timestamp when comment was created", + "example": 1704123938 + } + }, + "example": { + "commentID": 1873376745, + "body": "comment 4", + "createdAt": 1704123938 + } + }, + "IncidentStatus": { + "type": "object", + "description": "Status of the incident", + "properties": { + "isIdentified": { + "type": "boolean", + "description": "Has the incident been indetified", + "example": true + }, + "isResolved": { + "type": "boolean", + "description": "has the incident been resolved", + "example": true + }, + "endDatetime": { + "type": "integer", + "description": "Incident end time", + "example": 1731901920 + } + }, + "example": { + "isIdentified": true, + "isResolved": true, + "endDatetime": 1731901920 + } + } + }, + "responses": { + "Response401": { + "description": "Bad API keys response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Invalid token response", + "example": "invalid token" + } + } + }, + "example": { + "error": "invalid token" + } + } + } + }, + "Response400": { + "description": "bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "bad request while calling kener apis", + "example": "unknown tags" + } + } + }, + "example": { + "error": "unknown tags" + } + } + } + } + }, + "examples": { + "GetMonitorStatusExample200": { + "summary": "response of get status of a monitor", + "description": "Some Description", + "value": { + "status": "UP", + "uptime": "100", + "lastUpdatedAt": 1731901920 + } + }, + "DegradedRequestBody": { + "summary": "update to degraded", + "description": "Some Description", + "value": { + "status": "DEGRADED", + "timestampInSeconds": 1731251760, + "latency": 100, + "tag": "earth" + } + }, + "CreateIncidentResponse": { + "summary": "create incident response", + "description": "create incident response", + "value": { + "createdAt": 1731901920, + "closedAt": 1731901920, + "incidentNumber": 4, + "startDatetime": 1731901920, + "endDatetime": 1704123938, + "title": "title of the incident", + "body": "body of the incident", + "tags": ["earth", "google"], + "impact": "DOWN", + "isMaintenance": false, + "isIdentified": true, + "isResolved": true + } + }, + "CreateIncidentRequest": { + "summary": "create incident request body", + "description": "Some Description", + "value": { + "startDatetime": 1731901920, + "endDatetime": 1704123938, + "title": "title of the incident", + "body": "body of the incident", + "tags": ["earth", "google"], + "impact": "DOWN", + "isMaintenance": false, + "isIdentified": true, + "isResolved": true + } + }, + "SearchIncidentsResponse": { + "summary": "array of incidents", + "description": "Some Description", + "value": [ + { + "createdAt": 1731901920, + "closedAt": 1731901920, + "incidentNumber": 4, + "startDatetime": 1731901920, + "endDatetime": 1704123938, + "title": "title of the incident", + "body": "body of the incident", + "tags": ["earth", "google"], + "impact": "DOWN", + "isMaintenance": false, + "isIdentified": true, + "isResolved": true + }, + { + "createdAt": 1731901920, + "closedAt": 1731901920, + "incidentNumber": 4, + "startDatetime": 1731901920, + "endDatetime": 1704123938, + "title": "title of the incident", + "body": "body of the incident", + "tags": ["earth", "google"], + "impact": "DOWN", + "isMaintenance": false, + "isIdentified": true, + "isResolved": true + } + ] + }, + "CommentsResponse": { + "summary": "list of comments", + "description": "Some Description", + "value": [ + { + "commentID": 1873376745, + "body": "comment 4", + "createdAt": 1704123938 + }, + { + "commentID": 1873376745, + "body": "comment 4", + "createdAt": 1704123938 + } + ] + }, + "CommentRequestBody": { + "summary": "request body for a comment", + "description": "request body for a comment to add in an incident", + "value": { + "body": "This is a comment" + } + }, + "CreateCommentResponse": { + "summary": "create comment response body sample", + "description": "create comment response body sample", + "value": { + "commentID": 1873376745, + "body": "comment 4", + "createdAt": 1704123938 + } + } + } + }, + "paths": { + "/api/status": { + "post": { + "operationId": "updateMonitorStatus", + "summary": "Update status of a monitor", + "description": "Update status of an incident at a given timestamp", + "tags": ["Monitors"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "description": "request body to update an incident", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MonitorStatus" + }, + "examples": { + "degraded": { + "$ref": "#/components/examples/DegradedRequestBody" + } + } + } + } + }, + "responses": { + "200": { + "description": "Status updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "example": 200 + }, + "message": { + "type": "string", + "example": "success at 1731251760" + } + } + }, + "example": { + "status": 200, + "message": "success at 1731251760" + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + }, + "get": { + "operationId": "getMonitorStatus", + "summary": "Get status of a monitor", + "description": "get status of a monitor at timestamp", + "tags": ["Monitors"], + "security": [ + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "tag", + "in": "query", + "required": true, + "description": "monitor tag to get an incident", + "schema": { + "type": "string", + "example": "earth" + } + } + ], + "responses": { + "200": { + "description": "Monitor status retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StatusResponse" + }, + "examples": { + "successExample": { + "$ref": "#/components/examples/GetMonitorStatusExample200" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + } + }, + "/api/incident": { + "post": { + "operationId": "createIncident", + "summary": "Create a new incident", + "description": "API to create incidents", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "description": "request body to manually create an incident", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Incident" + }, + "examples": { + "sample": { + "$ref": "#/components/examples/CreateIncidentRequest" + } + } + } + } + }, + "responses": { + "200": { + "description": "Incident created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IncidentResponse" + }, + "examples": { + "success": { + "$ref": "#/components/examples/CreateIncidentResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + }, + "get": { + "operationId": "searchIncidents", + "summary": "Search for incidents", + "description": "API to get incidents", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "state", + "in": "query", + "description": "state of the incident. Can be open or close", + "schema": { + "type": "string", + "description": "state of the incident. Can be open or close", + "enum": ["open", "closed"], + "default": "open", + "example": "open" + } + }, + { + "name": "tags", + "in": "query", + "description": "Comma separated monitor tags", + "schema": { + "type": "string", + "description": "Comma separated monitor tags", + "example": "earth,google" + } + }, + { + "name": "page", + "in": "query", + "description": "page number", + "schema": { + "type": "integer", + "description": "page number", + "default": 1, + "minimum": 1, + "example": 1 + } + }, + { + "name": "per_page", + "in": "query", + "description": "how many per page", + "schema": { + "type": "integer", + "default": 10, + "description": "how many per page", + "maximum": 100, + "example": 10 + } + }, + { + "name": "created_after_utc", + "description": "start time", + "in": "query", + "schema": { + "type": "integer", + "description": "start time", + "example": 1731866475 + } + }, + { + "name": "created_before_utc", + "description": "end time", + "in": "query", + "schema": { + "type": "integer", + "description": "end time", + "example": 1731866475 + } + }, + { + "name": "title_like", + "description": "title of the incident", + "in": "query", + "schema": { + "type": "string", + "description": "title of the incident", + "example": "outage" + } + } + ], + "responses": { + "200": { + "description": "Search results retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IncidentResponse" + } + }, + "examples": { + "success": { + "$ref": "#/components/examples/SearchIncidentsResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + } + }, + "/api/incident/{incidentNumber}": { + "parameters": [ + { + "name": "incidentNumber", + "in": "path", + "required": true, + "description": "incident number as an integer to get incident by id", + "schema": { + "type": "integer", + "example": 4 + } + } + ], + "get": { + "operationId": "getIncident", + "summary": "Get an incident by number", + "description": "API to get an incident by incident number", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Incident retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IncidentResponse" + }, + "examples": { + "success": { + "$ref": "#/components/examples/CreateIncidentResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + }, + "patch": { + "operationId": "updateIncident", + "summary": "Update an incident", + "description": "API to update an incident by incident number", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "description": "search for an incident", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Incident" + }, + "examples": { + "sample": { + "$ref": "#/components/examples/CreateIncidentRequest" + } + } + } + } + }, + "responses": { + "200": { + "description": "Incident updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IncidentResponse" + }, + "examples": { + "success": { + "$ref": "#/components/examples/CreateIncidentResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + } + }, + "/api/incident/{incidentNumber}/comment": { + "parameters": [ + { + "name": "incidentNumber", + "in": "path", + "required": true, + "description": "incident number to fetch comment for", + "schema": { + "type": "integer", + "example": 4 + } + } + ], + "post": { + "operationId": "addIncidentComment", + "summary": "Add a comment to an incident", + "description": "API to create comment for an incident", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "description": "body to add a comment", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Comment" + }, + "examples": { + "sample": { + "$ref": "#/components/examples/CommentRequestBody" + } + } + } + } + }, + "responses": { + "200": { + "description": "Comment added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommentResponse" + }, + "examples": { + "sample": { + "$ref": "#/components/examples/CreateCommentResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + }, + "get": { + "operationId": "getIncidentComments", + "summary": "Get comments for an incident", + "description": "API to get comments for an incident", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Comments retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommentResponse" + } + }, + "examples": { + "success": { + "$ref": "#/components/examples/CommentsResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + } + }, + "/api/incident/{incidentNumber}/status": { + "parameters": [ + { + "name": "incidentNumber", + "in": "path", + "required": true, + "description": "incident number to fetch status for", + "schema": { + "type": "integer", + "example": 4 + } + } + ], + "post": { + "operationId": "updateIncidentStatus", + "summary": "Update the status of an incident", + "description": "API to update status of an incident", + "tags": ["Incidents"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "description": "request body to update status of an incident", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IncidentStatus" + }, + "example": { + "isIdentified": true, + "isResolved": true, + "endDatetime": 1731901920 + } + } + } + }, + "responses": { + "200": { + "description": "Incident status updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IncidentResponse" + }, + "examples": { + "success": { + "$ref": "#/components/examples/CreateIncidentResponse" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/Response400" + }, + "401": { + "$ref": "#/components/responses/Response401" + } + } + } + } + } +} diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..86f2f84 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,708 @@ +--- +info: + title: Kener API + version: 1.0.0 + description: | + # Kener Self-hosted node js status page + ![Kener](https://kener.ing/newbg.png "kener") + API specification for Kener status page and incident management system. This API spec was created using [Frogment](https://www.frogment.app) + contact: + name: Raj Nandan Sharma + email: rajnandan1@gmail.com + url: https://github.com/rajnandan1/kener/issues + license: + name: MIT + url: https://opensource.org/licenses/MIT +openapi: 3.0.0 +servers: +- url: https://your-kener-host.com + description: Kener host URL +tags: +- name: Monitors + description: APIs to interact with monitors +- name: Incidents + description: APIs to integrate incidents +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: enter your api key here + schemas: + MonitorStatus: + type: object + description: Monitor Status + required: + - status + - latency + - tag + properties: + status: + type: string + example: UP + enum: + - UP + - DOWN + - DEGRADED + latency: + type: number + description: In seconds + example: 100 + timestampInSeconds: + type: integer + description: UTC timestamp in seconds + example: 1731251760 + tag: + type: string + example: earth + description: Tag of a monitor + example: + status: UP + timestampInSeconds: 1731251760 + latency: 100 + tag: earth + StatusResponse: + type: object + description: Status of a monitor given a tag + properties: + status: + type: string + example: UP + enum: + - UP + - DOWN + - DEGRADED + uptime: + type: string + example: '100' + lastUpdatedAt: + type: integer + example: 1731251760 + example: + status: UP + lastUpdatedAt: 1731251760 + uptime: '100' + Incident: + type: object + description: body of an incident + required: + - title + - tags + properties: + startDatetime: + type: integer + description: UTC timestamp in seconds + example: 1731901920 + endDatetime: + type: integer + description: UTC timestamp in seconds + example: 1704123938 + title: + type: string + example: Outage in mumbai + description: title of the incident + body: + type: string + example: body of the incident + description: body of the incident + tags: + type: array + items: + type: string + example: earth + description: comma separated tags of monitors + example: + - earth + - google + impact: + type: string + example: DOWN + description: Impact of the incident + enum: + - DOWN + - DEGRADED + isMaintenance: + type: boolean + description: is this incident because of maintenance + example: false + isIdentified: + type: boolean + description: has the incident been indentified + example: true + isResolved: + type: boolean + description: has the incident been resovled + example: true + example: + startDatetime: 1731901920 + endDatetime: 1704123938 + title: title of the incident + body: body of the incident + tags: + - earth + - google + impact: DOWN + isMaintenance: false + isIdentified: true + isResolved: true + IncidentResponse: + description: Incident response schema + allOf: + - "$ref": "#/components/schemas/Incident" + - type: object + properties: + createdAt: + type: integer + description: UTC timestamp in seconds, incident created at + example: 1731901920 + closedAt: + type: integer + nullable: true + description: UTC timestamp in seconds, incident closed at + example: 1731901920 + incidentNumber: + type: integer + description: id of the incident + example: 4 + example: + createdAt: 1731901920 + closedAt: 1731901920 + incidentNumber: 4 + Comment: + type: object + description: Comment of an incident + required: + - body + properties: + body: + type: string + example: comment 1 + example: + body: comment 2 + CommentResponse: + type: object + description: Comment Response + properties: + commentID: + type: integer + description: ID of the comment + example: 1873376745 + body: + type: string + description: body of the comment + example: comment 3 + createdAt: + type: integer + description: timestamp when comment was created + example: 1704123938 + example: + commentID: 1873376745 + body: comment 4 + createdAt: 1704123938 + IncidentStatus: + type: object + description: Status of the incident + properties: + isIdentified: + type: boolean + description: Has the incident been indetified + example: true + isResolved: + type: boolean + description: has the incident been resolved + example: true + endDatetime: + type: integer + description: Incident end time + example: 1731901920 + example: + isIdentified: true + isResolved: true + endDatetime: 1731901920 + responses: + Response401: + description: Bad API keys response + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Invalid token response + example: invalid token + example: + error: invalid token + Response400: + description: bad request + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: bad request while calling kener apis + example: unknown tags + example: + error: unknown tags + examples: + GetMonitorStatusExample200: + summary: response of get status of a monitor + description: Some Description + value: + status: UP + uptime: '100' + lastUpdatedAt: 1731901920 + DegradedRequestBody: + summary: update to degraded + description: Some Description + value: + status: DEGRADED + timestampInSeconds: 1731251760 + latency: 100 + tag: earth + CreateIncidentResponse: + summary: create incident response + description: create incident response + value: + createdAt: 1731901920 + closedAt: 1731901920 + incidentNumber: 4 + startDatetime: 1731901920 + endDatetime: 1704123938 + title: title of the incident + body: body of the incident + tags: + - earth + - google + impact: DOWN + isMaintenance: false + isIdentified: true + isResolved: true + CreateIncidentRequest: + summary: create incident request body + description: Some Description + value: + startDatetime: 1731901920 + endDatetime: 1704123938 + title: title of the incident + body: body of the incident + tags: + - earth + - google + impact: DOWN + isMaintenance: false + isIdentified: true + isResolved: true + SearchIncidentsResponse: + summary: array of incidents + description: Some Description + value: + - createdAt: 1731901920 + closedAt: 1731901920 + incidentNumber: 4 + startDatetime: 1731901920 + endDatetime: 1704123938 + title: title of the incident + body: body of the incident + tags: + - earth + - google + impact: DOWN + isMaintenance: false + isIdentified: true + isResolved: true + - createdAt: 1731901920 + closedAt: 1731901920 + incidentNumber: 4 + startDatetime: 1731901920 + endDatetime: 1704123938 + title: title of the incident + body: body of the incident + tags: + - earth + - google + impact: DOWN + isMaintenance: false + isIdentified: true + isResolved: true + CommentsResponse: + summary: list of comments + description: Some Description + value: + - commentID: 1873376745 + body: comment 4 + createdAt: 1704123938 + - commentID: 1873376745 + body: comment 4 + createdAt: 1704123938 + CommentRequestBody: + summary: request body for a comment + description: request body for a comment to add in an incident + value: + body: This is a comment + CreateCommentResponse: + summary: create comment response body sample + description: create comment response body sample + value: + commentID: 1873376745 + body: comment 4 + createdAt: 1704123938 +paths: + "/api/status": + post: + operationId: updateMonitorStatus + summary: Update status of a monitor + description: Update status of an incident at a given timestamp + tags: + - Monitors + security: + - bearerAuth: [] + requestBody: + required: true + description: request body to update an incident + content: + application/json: + schema: + "$ref": "#/components/schemas/MonitorStatus" + examples: + degraded: + "$ref": "#/components/examples/DegradedRequestBody" + responses: + '200': + description: Status updated successfully + content: + application/json: + schema: + type: object + properties: + status: + type: integer + example: 200 + message: + type: string + example: success at 1731251760 + example: + status: 200 + message: success at 1731251760 + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + get: + operationId: getMonitorStatus + summary: Get status of a monitor + description: get status of a monitor at timestamp + tags: + - Monitors + security: + - bearerAuth: [] + parameters: + - name: tag + in: query + required: true + description: monitor tag to get an incident + schema: + type: string + example: earth + responses: + '200': + description: Monitor status retrieved successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/StatusResponse" + examples: + successExample: + "$ref": "#/components/examples/GetMonitorStatusExample200" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + "/api/incident": + post: + operationId: createIncident + summary: Create a new incident + description: API to create incidents + tags: + - Incidents + security: + - bearerAuth: [] + requestBody: + required: true + description: request body to manually create an incident + content: + application/json: + schema: + "$ref": "#/components/schemas/Incident" + examples: + sample: + "$ref": "#/components/examples/CreateIncidentRequest" + responses: + '200': + description: Incident created successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/IncidentResponse" + examples: + success: + "$ref": "#/components/examples/CreateIncidentResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + get: + operationId: searchIncidents + summary: Search for incidents + description: API to get incidents + tags: + - Incidents + security: + - bearerAuth: [] + parameters: + - name: state + in: query + description: state of the incident. Can be open or close + schema: + type: string + description: state of the incident. Can be open or close + enum: + - open + - closed + default: open + example: open + - name: tags + in: query + description: Comma separated monitor tags + schema: + type: string + description: Comma separated monitor tags + example: earth,google + - name: page + in: query + description: page number + schema: + type: integer + description: page number + default: 1 + minimum: 1 + example: 1 + - name: per_page + in: query + description: how many per page + schema: + type: integer + default: 10 + description: how many per page + maximum: 100 + example: 10 + - name: created_after_utc + description: start time + in: query + schema: + type: integer + description: start time + example: 1731866475 + - name: created_before_utc + description: end time + in: query + schema: + type: integer + description: end time + example: 1731866475 + - name: title_like + description: title of the incident + in: query + schema: + type: string + description: title of the incident + example: outage + responses: + '200': + description: Search results retrieved successfully + content: + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/IncidentResponse" + examples: + success: + "$ref": "#/components/examples/SearchIncidentsResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + "/api/incident/{incidentNumber}": + parameters: + - name: incidentNumber + in: path + required: true + description: incident number as an integer to get incident by id + schema: + type: integer + example: 4 + get: + operationId: getIncident + summary: Get an incident by number + description: API to get an incident by incident number + tags: + - Incidents + security: + - bearerAuth: [] + responses: + '200': + description: Incident retrieved successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/IncidentResponse" + examples: + success: + "$ref": "#/components/examples/CreateIncidentResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + patch: + operationId: updateIncident + summary: Update an incident + description: API to update an incident by incident number + tags: + - Incidents + security: + - bearerAuth: [] + requestBody: + required: true + description: search for an incident + content: + application/json: + schema: + "$ref": "#/components/schemas/Incident" + examples: + sample: + "$ref": "#/components/examples/CreateIncidentRequest" + responses: + '200': + description: Incident updated successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/IncidentResponse" + examples: + success: + "$ref": "#/components/examples/CreateIncidentResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + "/api/incident/{incidentNumber}/comment": + parameters: + - name: incidentNumber + in: path + required: true + description: incident number to fetch comment for + schema: + type: integer + example: 4 + post: + operationId: addIncidentComment + summary: Add a comment to an incident + description: API to create comment for an incident + tags: + - Incidents + security: + - bearerAuth: [] + requestBody: + required: true + description: body to add a comment + content: + application/json: + schema: + "$ref": "#/components/schemas/Comment" + examples: + sample: + "$ref": "#/components/examples/CommentRequestBody" + responses: + '200': + description: Comment added successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/CommentResponse" + examples: + sample: + "$ref": "#/components/examples/CreateCommentResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + get: + operationId: getIncidentComments + summary: Get comments for an incident + description: API to get comments for an incident + tags: + - Incidents + security: + - bearerAuth: [] + responses: + '200': + description: Comments retrieved successfully + content: + application/json: + schema: + type: array + items: + "$ref": "#/components/schemas/CommentResponse" + examples: + success: + "$ref": "#/components/examples/CommentsResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" + "/api/incident/{incidentNumber}/status": + parameters: + - name: incidentNumber + in: path + required: true + description: incident number to fetch status for + schema: + type: integer + example: 4 + post: + operationId: updateIncidentStatus + summary: Update the status of an incident + description: API to update status of an incident + tags: + - Incidents + security: + - bearerAuth: [] + requestBody: + required: true + description: request body to update status of an incident + content: + application/json: + schema: + "$ref": "#/components/schemas/IncidentStatus" + example: + isIdentified: true + isResolved: true + endDatetime: 1731901920 + responses: + '200': + description: Incident status updated successfully + content: + application/json: + schema: + "$ref": "#/components/schemas/IncidentResponse" + examples: + success: + "$ref": "#/components/examples/CreateIncidentResponse" + '400': + "$ref": "#/components/responses/Response400" + '401': + "$ref": "#/components/responses/Response401" diff --git a/package-lock.json b/package-lock.json index 7d3ff57..6e2086d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.16", "license": "MIT", "dependencies": { + "@scalar/express-api-reference": "^0.4.167", "analytics": "^0.8.14", "axios": "^1.6.2", "badge-maker": "^3.3.1", @@ -757,6 +758,40 @@ } } }, + "node_modules/@scalar/express-api-reference": { + "version": "0.4.167", + "resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.4.167.tgz", + "integrity": "sha512-pHbKZrU+fCCY7hjXrEoS3mEdHDyIBFSTEPHYk4h4luMUxzdDw+3oI6wNCT4bIUIMnG17lVTyvNSpEs8SRAcKjA==", + "license": "MIT", + "dependencies": { + "@scalar/types": "0.0.19" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@scalar/openapi-types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.1.5.tgz", + "integrity": "sha512-6geH9ehvQ/sG/xUyy3e0lyOw3BaY5s6nn22wHjEJhcobdmWyFER0O6m7AU0ZN4QTjle/gYvFJOjj552l/rsNSw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@scalar/types": { + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.0.19.tgz", + "integrity": "sha512-wOxtXd35BS0DaVhBopQUB8c8hfLQ+/PKEr99GbOZW+4DWCrEB8JfWJgvpJyxHU6by7LHNVY4fvpFQR7Ezh1IIw==", + "license": "MIT", + "dependencies": { + "@scalar/openapi-types": "0.1.5", + "@unhead/schema": "^1.9.5" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sveltejs/adapter-auto": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-2.1.1.tgz", @@ -922,6 +957,19 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, + "node_modules/@unhead/schema": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.11.tgz", + "integrity": "sha512-xSGsWHPBYcMV/ckQeImbrVu6ddeRnrdDCgXUKv3xIjGBY+ob/96V80lGX8FKWh8GwdFSwhblISObKlDAt5K9ZQ==", + "license": "MIT", + "dependencies": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2625,6 +2673,12 @@ "node": ">= 0.4" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -5674,6 +5728,15 @@ "engines": { "node": ">=12" } + }, + "node_modules/zhead": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz", + "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } } } } diff --git a/package.json b/package.json index ed1aba9..51a71e6 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ }, "type": "module", "dependencies": { + "@scalar/express-api-reference": "^0.4.167", "analytics": "^0.8.14", "axios": "^1.6.2", "badge-maker": "^3.3.1", diff --git a/src/routes/(docs)/+layout.svelte b/src/routes/(docs)/+layout.svelte index 9741759..70965c0 100644 --- a/src/routes/(docs)/+layout.svelte +++ b/src/routes/(docs)/+layout.svelte @@ -91,6 +91,7 @@ src="https://img.shields.io/github/stars/rajnandan1/kener?label=Star%20Repo&style=social" /> + API Reference