summaryrefslogtreecommitdiff
path: root/src/server/api/openapi
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
commit0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch)
tree40874799472fa07416f17b50a398ac33b7771905 /src/server/api/openapi
parentupdate deps (diff)
downloadsharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip
refactoring
Resolve #7779
Diffstat (limited to 'src/server/api/openapi')
-rw-r--r--src/server/api/openapi/description.ts51
-rw-r--r--src/server/api/openapi/errors.ts69
-rw-r--r--src/server/api/openapi/gen-spec.ts237
-rw-r--r--src/server/api/openapi/schemas.ts56
4 files changed, 0 insertions, 413 deletions
diff --git a/src/server/api/openapi/description.ts b/src/server/api/openapi/description.ts
deleted file mode 100644
index e51b312259..0000000000
--- a/src/server/api/openapi/description.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import endpoints from '../endpoints';
-import * as locale from '../../../../locales/index';
-import { kinds as kindsList } from '@/misc/api-permissions';
-
-export interface IKindInfo {
- endpoints: string[];
- descs: { [x: string]: string; };
-}
-
-export function kinds() {
- const kinds = Object.fromEntries(
- kindsList
- .map(k => [k, {
- endpoints: [],
- descs: Object.fromEntries(
- Object.keys(locale)
- .map(l => [l, locale[l]._permissions[k] as string])
- )
- } as IKindInfo])
- );
-
- const errors = [] as string[][];
-
- for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) {
- if (endpoint.meta.kind) {
- const kind = endpoint.meta.kind;
- if (kind in kinds) kinds[kind].endpoints.push(endpoint.name);
- else errors.push([kind, endpoint.name]);
- }
- }
-
- if (errors.length > 0) throw Error('\n ' + errors.map((e) => `Unknown kind (permission) "${e[0]}" found at ${e[1]}.`).join('\n '));
-
- return kinds;
-}
-
-export function getDescription(lang = 'ja-JP'): string {
- const permissionTable = Object.entries(kinds())
- .map(e => `|${e[0]}|${e[1].descs[lang]}|${e[1].endpoints.map(f => `[${f}](#operation/${f})`).join(', ')}|`)
- .join('\n');
-
- const descriptions: { [x: string]: string } = {
- 'ja-JP': `
-# Permissions
-|Permisson (kind)|Description|Endpoints|
-|:--|:--|:--|
-${permissionTable}
-`
- };
- return lang in descriptions ? descriptions[lang] : descriptions['ja-JP'];
-}
diff --git a/src/server/api/openapi/errors.ts b/src/server/api/openapi/errors.ts
deleted file mode 100644
index 43bcc323ba..0000000000
--- a/src/server/api/openapi/errors.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-
-export const errors = {
- '400': {
- 'INVALID_PARAM': {
- value: {
- error: {
- message: 'Invalid param.',
- code: 'INVALID_PARAM',
- id: '3d81ceae-475f-4600-b2a8-2bc116157532',
- }
- }
- }
- },
- '401': {
- 'CREDENTIAL_REQUIRED': {
- value: {
- error: {
- message: 'Credential required.',
- code: 'CREDENTIAL_REQUIRED',
- id: '1384574d-a912-4b81-8601-c7b1c4085df1',
- }
- }
- }
- },
- '403': {
- 'AUTHENTICATION_FAILED': {
- value: {
- error: {
- message: 'Authentication failed. Please ensure your token is correct.',
- code: 'AUTHENTICATION_FAILED',
- id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14',
- }
- }
- }
- },
- '418': {
- 'I_AM_AI': {
- value: {
- error: {
- message: 'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.',
- code: 'I_AM_AI',
- id: '60c46cd1-f23a-46b1-bebe-5d2b73951a84',
- }
- }
- }
- },
- '429': {
- 'RATE_LIMIT_EXCEEDED': {
- value: {
- error: {
- message: 'Rate limit exceeded. Please try again later.',
- code: 'RATE_LIMIT_EXCEEDED',
- id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef',
- }
- }
- }
- },
- '500': {
- 'INTERNAL_ERROR': {
- value: {
- error: {
- message: 'Internal error occurred. Please contact us if the error persists.',
- code: 'INTERNAL_ERROR',
- id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac',
- }
- }
- }
- }
-};
diff --git a/src/server/api/openapi/gen-spec.ts b/src/server/api/openapi/gen-spec.ts
deleted file mode 100644
index 9db47c6dfc..0000000000
--- a/src/server/api/openapi/gen-spec.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-import endpoints from '../endpoints';
-import { Context } from 'cafy';
-import config from '@/config/index';
-import { errors as basicErrors } from './errors';
-import { schemas, convertSchemaToOpenApiSchema } from './schemas';
-import { getDescription } from './description';
-
-export function genOpenapiSpec(lang = 'ja-JP') {
- const spec = {
- openapi: '3.0.0',
-
- info: {
- version: 'v1',
- title: 'Misskey API',
- description: getDescription(lang),
- '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'
- }
- }
- }
- };
-
- function genProps(props: { [key: string]: Context; }) {
- const properties = {} as any;
-
- for (const [k, v] of Object.entries(props)) {
- properties[k] = genProp(v);
- }
-
- return properties;
- }
-
- function genProp(param: Context): any {
- const required = param.name === 'Object' ? (param as any).props ? Object.entries((param as any).props).filter(([k, v]: any) => !v.isOptional).map(([k, v]) => k) : [] : [];
- return {
- description: (param.data || {}).desc,
- default: (param.data || {}).default,
- deprecated: (param.data || {}).deprecated,
- ...((param.data || {}).default ? { default: (param.data || {}).default } : {}),
- type: param.name === 'ID' ? 'string' : param.name.toLowerCase(),
- ...(param.name === 'ID' ? { example: 'xxxxxxxxxx', format: 'id' } : {}),
- nullable: param.isNullable,
- ...(param.name === 'String' ? {
- ...((param as any).enum ? { enum: (param as any).enum } : {}),
- ...((param as any).minLength ? { minLength: (param as any).minLength } : {}),
- ...((param as any).maxLength ? { maxLength: (param as any).maxLength } : {}),
- } : {}),
- ...(param.name === 'Number' ? {
- ...((param as any).minimum ? { minimum: (param as any).minimum } : {}),
- ...((param as any).maximum ? { maximum: (param as any).maximum } : {}),
- } : {}),
- ...(param.name === 'Object' ? {
- ...(required.length > 0 ? { required } : {}),
- properties: (param as any).props ? genProps((param as any).props) : {}
- } : {}),
- ...(param.name === 'Array' ? {
- items: (param as any).ctx ? genProp((param as any).ctx) : {}
- } : {})
- };
- }
-
- for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) {
- const porops = {} as any;
- const errors = {} as any;
-
- if (endpoint.meta.errors) {
- for (const e of Object.values(endpoint.meta.errors)) {
- errors[e.code] = {
- value: {
- error: e
- }
- };
- }
- }
-
- if (endpoint.meta.params) {
- for (const [k, v] of Object.entries(endpoint.meta.params)) {
- if (v.validator.data == null) v.validator.data = {};
- if (v.desc) v.validator.data.desc = v.desc[lang];
- if (v.deprecated) v.validator.data.deprecated = v.deprecated;
- if (v.default) v.validator.data.default = v.default;
- porops[k] = v.validator;
- }
- }
-
- const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : [];
-
- const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {};
-
- let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : '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 info = {
- operationId: endpoint.name,
- summary: endpoint.name,
- description: desc,
- externalDocs: {
- description: 'Source code',
- url: `https://github.com/misskey-dev/misskey/blob/develop/src/server/api/endpoints/${endpoint.name}.ts`
- },
- ...(endpoint.meta.tags ? {
- tags: [endpoint.meta.tags[0]]
- } : {}),
- ...(endpoint.meta.requireCredential ? {
- security: [{
- ApiKeyAuth: []
- }]
- } : {}),
- requestBody: {
- required: true,
- content: {
- 'application/json': {
- schema: {
- type: 'object',
- ...(required.length > 0 ? { required } : {}),
- properties: endpoint.meta.params ? genProps(porops) : {}
- }
- }
- }
- },
- 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;
-}
diff --git a/src/server/api/openapi/schemas.ts b/src/server/api/openapi/schemas.ts
deleted file mode 100644
index 12fc207c47..0000000000
--- a/src/server/api/openapi/schemas.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { refs, Schema } from '@/misc/schema';
-
-export function convertSchemaToOpenApiSchema(schema: Schema) {
- const res: any = schema;
-
- if (schema.type === 'object' && schema.properties) {
- res.required = Object.entries(schema.properties).filter(([k, v]) => !v.optional).map(([k]) => k);
-
- for (const k of Object.keys(schema.properties)) {
- res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
- }
- }
-
- if (schema.type === 'array' && schema.items) {
- res.items = convertSchemaToOpenApiSchema(schema.items);
- }
-
- if (schema.ref) {
- res.$ref = `#/components/schemas/${schema.ref}`;
- }
-
- return res;
-}
-
-export const schemas = {
- Error: {
- type: 'object',
- properties: {
- error: {
- type: 'object',
- description: 'An error object.',
- properties: {
- code: {
- type: 'string',
- description: 'An error code. Unique within the endpoint.',
- },
- message: {
- type: 'string',
- description: 'An error message.',
- },
- id: {
- type: 'string',
- format: 'uuid',
- description: 'An error ID. This ID is static.',
- }
- },
- required: ['code', 'id', 'message']
- },
- },
- required: ['error']
- },
-
- ...Object.fromEntries(
- Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)])
- ),
-};