api.jsonがswagger-cli validateでエラーにならないように生成ロジックを修正

This commit is contained in:
osamu 2023-11-21 11:43:58 +09:00
parent e0de86359c
commit 1e36284a27
3 changed files with 40 additions and 20 deletions

View File

@ -16,12 +16,9 @@ export const meta = {
requireCredential: false, requireCredential: false,
res: { res: {
oneOf: [{ type: 'object',
type: 'object', optional: false, nullable: true,
ref: 'FederationInstance', ref: 'FederationInstance',
}, {
type: 'null',
}],
}, },
} as const; } as const;

View File

@ -31,14 +31,6 @@ export function genOpenapiSpec(config: Config) {
components: { components: {
schemas: schemas, schemas: schemas,
securitySchemes: {
ApiKeyAuth: {
type: 'apiKey',
in: 'body',
name: 'i',
},
},
}, },
}; };
@ -67,6 +59,21 @@ export function genOpenapiSpec(config: Config) {
const requestType = endpoint.meta.requireFile ? 'multipart/form-data' : 'application/json'; const requestType = endpoint.meta.requireFile ? 'multipart/form-data' : 'application/json';
const schema = { ...endpoint.params }; const schema = { ...endpoint.params };
if (endpoint.meta.requireCredential) {
// https://swagger.io/docs/specification/authentication/api-keys/
// ↑曰く、「can be "header", "query" or "cookie"」とのこと。
// Misskeyはbodyに埋め込む形にしているので、各エンドポイントのパラメータに直接APIキー用のフィールドを追加する必要がある
schema.properties = {
'i': {
type: 'string',
nullable: false,
description: 'API Key',
},
...schema.properties,
};
schema.required = ['i', ...schema.required ?? []];
}
if (endpoint.meta.requireFile) { if (endpoint.meta.requireFile) {
schema.properties = { schema.properties = {
...schema.properties, ...schema.properties,
@ -79,6 +86,11 @@ export function genOpenapiSpec(config: Config) {
schema.required = [...schema.required ?? [], 'file']; schema.required = [...schema.required ?? [], 'file'];
} }
if (schema.required && schema.required.length <= 0) {
// 空配列は許可されない
schema.required = undefined;
}
const info = { const info = {
operationId: endpoint.name, operationId: endpoint.name,
summary: endpoint.name, summary: endpoint.name,
@ -90,11 +102,6 @@ export function genOpenapiSpec(config: Config) {
...(endpoint.meta.tags ? { ...(endpoint.meta.tags ? {
tags: [endpoint.meta.tags[0]], tags: [endpoint.meta.tags[0]],
} : {}), } : {}),
...(endpoint.meta.requireCredential ? {
security: [{
ApiKeyAuth: [],
}],
} : {}),
requestBody: { requestBody: {
required: true, required: true,
content: { content: {
@ -118,6 +125,11 @@ export function genOpenapiSpec(config: Config) {
description: 'OK (without any results)', description: 'OK (without any results)',
}, },
}), }),
...(endpoint.meta.res?.optional === true || endpoint.meta.res?.nullable === true ? {
'204': {
description: 'OK (without any results)',
},
} : {}),
'400': { '400': {
description: 'Client error', description: 'Client error',
content: { content: {

View File

@ -10,7 +10,11 @@ export function convertSchemaToOpenApiSchema(schema: Schema) {
const res: any = schema; const res: any = schema;
if (schema.type === 'object' && schema.properties) { if (schema.type === 'object' && schema.properties) {
res.required = Object.entries(schema.properties).filter(([k, v]) => !v.optional).map(([k]) => k); const required = Object.entries(schema.properties).filter(([k, v]) => !v.optional).map(([k]) => k);
if (required.length > 0) {
// 空配列は許可されない
res.required = required;
}
for (const k of Object.keys(schema.properties)) { for (const k of Object.keys(schema.properties)) {
res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]); res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
@ -32,8 +36,15 @@ export function convertSchemaToOpenApiSchema(schema: Schema) {
} else { } else {
res.$ref = $ref; res.$ref = $ref;
} }
// $refを抽出したので不要.
res.ref = undefined;
} }
// requiredを抽出したので不要.
// object以外の型も親階層のobjectによって列挙されているはずなので構わず消す
res.optional = undefined;
return res; return res;
} }