diff options
Diffstat (limited to 'src/server/api/openapi')
| -rw-r--r-- | src/server/api/openapi/description.ts | 51 | ||||
| -rw-r--r-- | src/server/api/openapi/errors.ts | 69 | ||||
| -rw-r--r-- | src/server/api/openapi/gen-spec.ts | 237 | ||||
| -rw-r--r-- | src/server/api/openapi/schemas.ts | 56 |
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)]) - ), -}; |