fix(generator): APIクライアントのパスにoperationIdが使われる問題を修正 (#13622)
This commit is contained in:
parent
a1bc8fa77b
commit
8f415d69cd
4 changed files with 1770 additions and 1752 deletions
File diff suppressed because it is too large
Load diff
|
@ -60,13 +60,17 @@ async function generateEndpoints(
|
||||||
// misskey-jsはPOST固定で送っているので、こちらも決め打ちする。別メソッドに対応することがあればこちらも直す必要あり
|
// misskey-jsはPOST固定で送っているので、こちらも決め打ちする。別メソッドに対応することがあればこちらも直す必要あり
|
||||||
const paths = openApiDocs.paths ?? {};
|
const paths = openApiDocs.paths ?? {};
|
||||||
const postPathItems = Object.keys(paths)
|
const postPathItems = Object.keys(paths)
|
||||||
.map(it => paths[it]?.post)
|
.map(it => ({
|
||||||
|
_path_: it.replace(/^\//, ''),
|
||||||
|
...paths[it]?.post,
|
||||||
|
}))
|
||||||
.filter(filterUndefined);
|
.filter(filterUndefined);
|
||||||
|
|
||||||
for (const operation of postPathItems) {
|
for (const operation of postPathItems) {
|
||||||
|
const path = operation._path_;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const operationId = operation.operationId!;
|
const operationId = operation.operationId!;
|
||||||
const endpoint = new Endpoint(operationId);
|
const endpoint = new Endpoint(path);
|
||||||
endpoints.push(endpoint);
|
endpoints.push(endpoint);
|
||||||
|
|
||||||
if (isRequestBodyObject(operation.requestBody)) {
|
if (isRequestBodyObject(operation.requestBody)) {
|
||||||
|
@ -76,19 +80,21 @@ async function generateEndpoints(
|
||||||
// いまのところ複数のメディアタイプをとるエンドポイントは無いので決め打ちする
|
// いまのところ複数のメディアタイプをとるエンドポイントは無いので決め打ちする
|
||||||
endpoint.request = new OperationTypeAlias(
|
endpoint.request = new OperationTypeAlias(
|
||||||
operationId,
|
operationId,
|
||||||
|
path,
|
||||||
supportMediaTypes[0],
|
supportMediaTypes[0],
|
||||||
OperationsAliasType.REQUEST,
|
OperationsAliasType.REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isResponseObject(operation.responses['200']) && operation.responses['200'].content) {
|
if (operation.responses && isResponseObject(operation.responses['200']) && operation.responses['200'].content) {
|
||||||
const resContent = operation.responses['200'].content;
|
const resContent = operation.responses['200'].content;
|
||||||
const supportMediaTypes = Object.keys(resContent);
|
const supportMediaTypes = Object.keys(resContent);
|
||||||
if (supportMediaTypes.length > 0) {
|
if (supportMediaTypes.length > 0) {
|
||||||
// いまのところ複数のメディアタイプを返すエンドポイントは無いので決め打ちする
|
// いまのところ複数のメディアタイプを返すエンドポイントは無いので決め打ちする
|
||||||
endpoint.response = new OperationTypeAlias(
|
endpoint.response = new OperationTypeAlias(
|
||||||
operationId,
|
operationId,
|
||||||
|
path,
|
||||||
supportMediaTypes[0],
|
supportMediaTypes[0],
|
||||||
OperationsAliasType.RESPONSE,
|
OperationsAliasType.RESPONSE,
|
||||||
);
|
);
|
||||||
|
@ -140,12 +146,19 @@ async function generateApiClientJSDoc(
|
||||||
endpointsFileName: string,
|
endpointsFileName: string,
|
||||||
warningsOutputPath: string,
|
warningsOutputPath: string,
|
||||||
) {
|
) {
|
||||||
const endpoints: { operationId: string; description: string; }[] = [];
|
const endpoints: {
|
||||||
|
operationId: string;
|
||||||
|
path: string;
|
||||||
|
description: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
// misskey-jsはPOST固定で送っているので、こちらも決め打ちする。別メソッドに対応することがあればこちらも直す必要あり
|
// misskey-jsはPOST固定で送っているので、こちらも決め打ちする。別メソッドに対応することがあればこちらも直す必要あり
|
||||||
const paths = openApiDocs.paths ?? {};
|
const paths = openApiDocs.paths ?? {};
|
||||||
const postPathItems = Object.keys(paths)
|
const postPathItems = Object.keys(paths)
|
||||||
.map(it => paths[it]?.post)
|
.map(it => ({
|
||||||
|
_path_: it.replace(/^\//, ''),
|
||||||
|
...paths[it]?.post,
|
||||||
|
}))
|
||||||
.filter(filterUndefined);
|
.filter(filterUndefined);
|
||||||
|
|
||||||
for (const operation of postPathItems) {
|
for (const operation of postPathItems) {
|
||||||
|
@ -155,6 +168,7 @@ async function generateApiClientJSDoc(
|
||||||
if (operation.description) {
|
if (operation.description) {
|
||||||
endpoints.push({
|
endpoints.push({
|
||||||
operationId: operationId,
|
operationId: operationId,
|
||||||
|
path: operation._path_,
|
||||||
description: operation.description,
|
description: operation.description,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -175,7 +189,7 @@ async function generateApiClientJSDoc(
|
||||||
' /**',
|
' /**',
|
||||||
` * ${endpoint.description.split('\n').join('\n * ')}`,
|
` * ${endpoint.description.split('\n').join('\n * ')}`,
|
||||||
' */',
|
' */',
|
||||||
` request<E extends '${endpoint.operationId}', P extends Endpoints[E][\'req\']>(`,
|
` request<E extends '${endpoint.path}', P extends Endpoints[E][\'req\']>(`,
|
||||||
' endpoint: E,',
|
' endpoint: E,',
|
||||||
' params: P,',
|
' params: P,',
|
||||||
' credential?: string | null,',
|
' credential?: string | null,',
|
||||||
|
@ -234,21 +248,24 @@ interface IOperationTypeAlias {
|
||||||
|
|
||||||
class OperationTypeAlias implements IOperationTypeAlias {
|
class OperationTypeAlias implements IOperationTypeAlias {
|
||||||
public readonly operationId: string;
|
public readonly operationId: string;
|
||||||
|
public readonly path: string;
|
||||||
public readonly mediaType: string;
|
public readonly mediaType: string;
|
||||||
public readonly type: OperationsAliasType;
|
public readonly type: OperationsAliasType;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
operationId: string,
|
operationId: string,
|
||||||
|
path: string,
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
type: OperationsAliasType,
|
type: OperationsAliasType,
|
||||||
) {
|
) {
|
||||||
this.operationId = operationId;
|
this.operationId = operationId;
|
||||||
|
this.path = path;
|
||||||
this.mediaType = mediaType;
|
this.mediaType = mediaType;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateName(): string {
|
generateName(): string {
|
||||||
const nameBase = this.operationId.replace(/\//g, '-');
|
const nameBase = this.path.replace(/\//g, '-');
|
||||||
return toPascal(nameBase + this.type);
|
return toPascal(nameBase + this.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,19 +298,19 @@ const emptyRequest = new EmptyTypeAlias(OperationsAliasType.REQUEST);
|
||||||
const emptyResponse = new EmptyTypeAlias(OperationsAliasType.RESPONSE);
|
const emptyResponse = new EmptyTypeAlias(OperationsAliasType.RESPONSE);
|
||||||
|
|
||||||
class Endpoint {
|
class Endpoint {
|
||||||
public readonly operationId: string;
|
public readonly path: string;
|
||||||
public request?: IOperationTypeAlias;
|
public request?: IOperationTypeAlias;
|
||||||
public response?: IOperationTypeAlias;
|
public response?: IOperationTypeAlias;
|
||||||
|
|
||||||
constructor(operationId: string) {
|
constructor(path: string) {
|
||||||
this.operationId = operationId;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
toLine(): string {
|
toLine(): string {
|
||||||
const reqName = this.request?.generateName() ?? emptyRequest.generateName();
|
const reqName = this.request?.generateName() ?? emptyRequest.generateName();
|
||||||
const resName = this.response?.generateName() ?? emptyResponse.generateName();
|
const resName = this.response?.generateName() ?? emptyResponse.generateName();
|
||||||
|
|
||||||
return `'${this.operationId}': { req: ${reqName}; res: ${resName} };`;
|
return `'${this.path}': { req: ${reqName}; res: ${resName} };`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue