diff options
author | Pouria Ezzati <ezzati.upt@gmail.com> | 2020-02-15 21:02:10 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-15 21:02:10 +0300 |
commit | 2c261ad4afd04d5c8e718decfec921027cb8e0a9 (patch) | |
tree | 82a0ccc51071426d31393b7146e8eff6aac26876 /docs | |
parent | b5f210b68d2f3e28047fb2fecfbdb394b5bd3a47 (diff) |
API doc generation! (#280)
Co-authored-by: trgwii <trgwii@hotmail.com>
Diffstat (limited to 'docs')
-rw-r--r-- | docs/api/api.ts | 529 | ||||
-rw-r--r-- | docs/api/generate.ts | 48 |
2 files changed, 577 insertions, 0 deletions
diff --git a/docs/api/api.ts b/docs/api/api.ts new file mode 100644 index 0000000..bffe068 --- /dev/null +++ b/docs/api/api.ts @@ -0,0 +1,529 @@ +import * as p from '../../package.json'; + +export default { + openapi: '3.0.0', + info: { + title: "Kutt.it", + description: "API referrence for [http://kutt.it](http://kutt.it).\n", + version: p.version + }, + servers: [{ + url: "https://kutt.it/api/v2" + }], + tags: [{ + name: "health" + }, { + name: "links" + }, { + name: "domains" + }, { + name: "users" + }], + paths: { + '/health': { + get: { + tags: ["health"], + summary: "API health", + responses: { + 200: { + description: "Health", + content: { + 'text/html': { + example: "OK" + } + } + } + } + } + }, + '/links': { + get: { + tags: ["links"], + description: "Get list of links", + parameters: [{ + name: "limit", + in: "query", + description: "Limit", + required: false, + style: "form", + explode: true, + schema: { + type: "number", + example: 10 + } + }, { + name: "skip", + in: "query", + description: "Skip", + required: false, + style: "form", + explode: true, + schema: { + type: "number", + example: 0 + } + }, { + name: "all", + in: "query", + description: "All links (ADMIN only)", + required: false, + style: "form", + explode: true, + schema: { + type: "boolean", + example: false + } + }], + responses: { + 200: { + description: "List of links", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/inline_response_200" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + }, + post: { + tags: ["links"], + description: "Create a short link", + requestBody: { + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/body" + } + } + } + }, + responses: { + 200: { + description: "Craeted link", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/Link" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + }, + '/links/{id}': { + delete: { + tags: ["links"], + description: "Delete a link", + parameters: [{ + name: "id", + in: "path", + required: true, + style: "simple", + explode: false, + schema: { + type: "string", + format: "uuid" + } + }], + responses: { + 200: { + description: "Deleted link successfully", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/inline_response_200_1" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + }, + '/links/{id}/stats': { + get: { + tags: ["links"], + description: "Get link stats", + parameters: [{ + name: "id", + in: "path", + required: true, + style: "simple", + explode: false, + schema: { + type: "string", + format: "uuid" + } + }], + responses: { + 200: { + description: "Link stats", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/Stats" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + }, + '/domains': { + post: { + tags: ["domains"], + description: "Create a domain", + requestBody: { + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/body_1" + } + } + } + }, + responses: { + 200: { + description: "Created domain", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/Domain" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + }, + '/domains/{id}': { + delete: { + tags: ["domains"], + description: "Delete a domain", + parameters: [{ + name: "id", + in: "path", + required: true, + style: "simple", + explode: false, + schema: { + type: "string", + format: "uuid" + } + }], + responses: { + 200: { + description: "Deleted domain successfully", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/inline_response_200_1" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + }, + '/users': { + get: { + tags: ["users"], + description: "Get user info", + responses: { + 200: { + description: "User info", + content: { + 'application/json': { + schema: { + $ref: "#/components/schemas/User" + } + } + } + } + }, + security: [{ + APIKeyAuth: [] + }] + } + } + }, + components: { + schemas: { + Link: { + type: "object", + properties: { + address: { + type: "string" + }, + banned: { + type: "boolean", + default: false + }, + created_at: { + type: "string", + format: "date-time" + }, + id: { + type: "string", + format: "uuid" + }, + link: { + type: "string" + }, + password: { + type: "boolean", + default: false + }, + target: { + type: "string" + }, + updated_at: { + type: "string", + format: "date-time" + }, + visit_count: { + type: "number" + } + } + }, + Domain: { + type: "object", + properties: { + address: { + type: "string" + }, + banned: { + type: "boolean", + default: false + }, + created_at: { + type: "string", + format: "date-time" + }, + id: { + type: "string", + format: "uuid" + }, + homepage: { + type: "string" + }, + updated_at: { + type: "string", + format: "date-time" + } + } + }, + User: { + type: "object", + properties: { + apikey: { + type: "string" + }, + email: { + type: "string" + }, + domains: { + type: "array", + items: { + $ref: "#/components/schemas/Domain" + } + } + } + }, + StatsItem: { + type: "object", + properties: { + stats: { + $ref: "#/components/schemas/StatsItem_stats" + }, + views: { + type: "array", + items: { + type: "number" + } + } + } + }, + Stats: { + type: "object", + properties: { + allTime: { + $ref: "#/components/schemas/StatsItem" + }, + lastDay: { + $ref: "#/components/schemas/StatsItem" + }, + lastMonth: { + $ref: "#/components/schemas/StatsItem" + }, + lastWeek: { + $ref: "#/components/schemas/StatsItem" + }, + updatedAt: { + type: "string" + }, + address: { + type: "string" + }, + banned: { + type: "boolean", + default: false + }, + created_at: { + type: "string", + format: "date-time" + }, + id: { + type: "string", + format: "uuid" + }, + link: { + type: "string" + }, + password: { + type: "boolean", + default: false + }, + target: { + type: "string" + }, + updated_at: { + type: "string", + format: "date-time" + }, + visit_count: { + type: "number" + } + } + }, + inline_response_200: { + properties: { + limit: { + type: "number", + default: 10 + }, + skip: { + type: "number", + default: 0 + }, + total: { + type: "number", + default: 0 + }, + data: { + type: "array", + items: { + $ref: "#/components/schemas/Link" + } + } + } + }, + body: { + required: ["target"], + properties: { + target: { + type: "string" + }, + password: { + type: "string" + }, + customurl: { + type: "string" + }, + reuse: { + type: "boolean", + default: false + }, + domain: { + type: "string" + } + } + }, + inline_response_200_1: { + properties: { + message: { + type: "string" + } + } + }, + body_1: { + required: ["address"], + properties: { + address: { + type: "string" + }, + homepage: { + type: "string" + } + } + }, + StatsItem_stats_browser: { + type: "object", + properties: { + name: { + type: "string" + }, + value: { + type: "number" + } + } + }, + StatsItem_stats: { + type: "object", + properties: { + browser: { + type: "array", + items: { + $ref: "#/components/schemas/StatsItem_stats_browser" + } + }, + os: { + type: "array", + items: { + $ref: "#/components/schemas/StatsItem_stats_browser" + } + }, + country: { + type: "array", + items: { + $ref: "#/components/schemas/StatsItem_stats_browser" + } + }, + referrer: { + type: "array", + items: { + $ref: "#/components/schemas/StatsItem_stats_browser" + } + } + } + } + }, + securitySchemes: { + APIKeyAuth: { + type: "apiKey", + name: "X-API-KEY", + in: "header" + } + } + } +}; diff --git a/docs/api/generate.ts b/docs/api/generate.ts new file mode 100644 index 0000000..7c4b2f5 --- /dev/null +++ b/docs/api/generate.ts @@ -0,0 +1,48 @@ +import { join, dirname } from 'path'; + +import { promises as fs } from 'fs'; + +import api from './api'; + +const Template = (output, { api, title, redoc }) => + fs.writeFile(output, +`<DOCTYPE html> +<html> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="X-UA-Compatible" content="ie=edge" /> + <title>${title}</title> + </head> + <body> + <redoc spec-url="${api}" /> + <script src="${redoc}"></script> + </body> +</html> +`); + +const Api = output => + fs.writeFile(output, JSON.stringify(api)); + +const Redoc = output => + fs.copyFile(join( + dirname(require.resolve('redoc')), + 'redoc.standalone.js'), + output); + +export default (async () => { + const out = join(__dirname, 'static'); + const apiFile = 'api.json'; + const redocFile = 'redoc.js'; + await fs.mkdir(out, { recursive: true }); + return Promise.all([ + Api(join(out, apiFile)), + Redoc(join(out, redocFile)), + Template(join(out, 'index.html'), { + api: apiFile, + title: api.info.title, + redoc: redocFile + }), + + ]); +})(); |