summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/openapi/gen-spec.ts
diff options
context:
space:
mode:
authorKagami Sascha Rosylight <saschanaz@outlook.com>2023-03-09 18:37:44 +0100
committerGitHub <noreply@github.com>2023-03-10 02:37:44 +0900
commite0b7633a7adb6f2744e1142637bbbd6ac6624031 (patch)
treedab693ed58c315cc0d4ea3ab2348512b72ccba67 /packages/backend/src/server/api/openapi/gen-spec.ts
parentfix(client): Solve the problem of not automatically jumping to /admin/overvie... (diff)
downloadsharkey-e0b7633a7adb6f2744e1142637bbbd6ac6624031.tar.gz
sharkey-e0b7633a7adb6f2744e1142637bbbd6ac6624031.tar.bz2
sharkey-e0b7633a7adb6f2744e1142637bbbd6ac6624031.zip
enhance(backend): restore OpenAPI endpoints (#10281)
* enhance(backend): restore OpenAPI endpoints * Update CHANGELOG.md * version * set max-age * update redoc * follow redoc documentation --------- Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Diffstat (limited to 'packages/backend/src/server/api/openapi/gen-spec.ts')
-rw-r--r--packages/backend/src/server/api/openapi/gen-spec.ts193
1 files changed, 193 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts
new file mode 100644
index 0000000000..fa62480c02
--- /dev/null
+++ b/packages/backend/src/server/api/openapi/gen-spec.ts
@@ -0,0 +1,193 @@
+import type { Config } from '@/config.js';
+import endpoints from '../endpoints.js';
+import { errors as basicErrors } from './errors.js';
+import { schemas, convertSchemaToOpenApiSchema } from './schemas.js';
+
+export function genOpenapiSpec(config: Config) {
+ const spec = {
+ openapi: '3.0.0',
+
+ info: {
+ version: config.version,
+ title: 'Misskey API',
+ 'x-logo': { url: '/static-assets/api-doc.png' },
+ },
+
+ externalDocs: {
+ description: 'Repository',
+ url: 'https://github.com/misskey-dev/misskey',
+ },
+
+ servers: [{
+ url: config.apiUrl,
+ }],
+
+ paths: {} as any,
+
+ components: {
+ schemas: schemas,
+
+ securitySchemes: {
+ ApiKeyAuth: {
+ type: 'apiKey',
+ in: 'body',
+ name: 'i',
+ },
+ },
+ },
+ };
+
+ for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) {
+ const errors = {} as any;
+
+ if (endpoint.meta.errors) {
+ for (const e of Object.values(endpoint.meta.errors)) {
+ errors[e.code] = {
+ value: {
+ error: e,
+ },
+ };
+ }
+ }
+
+ const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {};
+
+ let desc = (endpoint.meta.description ? endpoint.meta.description : 'No description provided.') + '\n\n';
+ desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;
+ if (endpoint.meta.kind) {
+ const kind = endpoint.meta.kind;
+ desc += ` / **Permission**: *${kind}*`;
+ }
+
+ const requestType = endpoint.meta.requireFile ? 'multipart/form-data' : 'application/json';
+ const schema = { ...endpoint.params };
+
+ if (endpoint.meta.requireFile) {
+ schema.properties = {
+ ...schema.properties,
+ file: {
+ type: 'string',
+ format: 'binary',
+ description: 'The file contents.',
+ },
+ };
+ schema.required = [...schema.required ?? [], 'file'];
+ }
+
+ const info = {
+ operationId: endpoint.name,
+ summary: endpoint.name,
+ description: desc,
+ externalDocs: {
+ description: 'Source code',
+ url: `https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`,
+ },
+ ...(endpoint.meta.tags ? {
+ tags: [endpoint.meta.tags[0]],
+ } : {}),
+ ...(endpoint.meta.requireCredential ? {
+ security: [{
+ ApiKeyAuth: [],
+ }],
+ } : {}),
+ requestBody: {
+ required: true,
+ content: {
+ [requestType]: {
+ schema,
+ },
+ },
+ },
+ responses: {
+ ...(endpoint.meta.res ? {
+ '200': {
+ description: 'OK (with results)',
+ content: {
+ 'application/json': {
+ schema: resSchema,
+ },
+ },
+ },
+ } : {
+ '204': {
+ description: 'OK (without any results)',
+ },
+ }),
+ '400': {
+ description: 'Client error',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: { ...errors, ...basicErrors['400'] },
+ },
+ },
+ },
+ '401': {
+ description: 'Authentication error',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: basicErrors['401'],
+ },
+ },
+ },
+ '403': {
+ description: 'Forbidden error',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: basicErrors['403'],
+ },
+ },
+ },
+ '418': {
+ description: 'I\'m Ai',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: basicErrors['418'],
+ },
+ },
+ },
+ ...(endpoint.meta.limit ? {
+ '429': {
+ description: 'To many requests',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: basicErrors['429'],
+ },
+ },
+ },
+ } : {}),
+ '500': {
+ description: 'Internal server error',
+ content: {
+ 'application/json': {
+ schema: {
+ $ref: '#/components/schemas/Error',
+ },
+ examples: basicErrors['500'],
+ },
+ },
+ },
+ },
+ };
+
+ spec.paths['/' + endpoint.name] = {
+ post: info,
+ };
+ }
+
+ return spec;
+}