fix misskey-js generator compatibility with openapi-typescript 7.x
This commit is contained in:
parent
48edf3d71f
commit
d0f2463bc6
4 changed files with 6949 additions and 5548 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@readme/openapi-parser": "5.0.1",
|
"@readme/openapi-parser": "5.0.1",
|
||||||
|
"@redocly/openapi-core": "1.34.5",
|
||||||
"@types/node": "22.18.1",
|
"@types/node": "22.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||||
"@typescript-eslint/parser": "8.44.1",
|
"@typescript-eslint/parser": "8.44.1",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ import assert from 'assert';
|
||||||
import { mkdir, readFile, writeFile } from 'fs/promises';
|
import { mkdir, readFile, writeFile } from 'fs/promises';
|
||||||
import { OpenAPIV3_1 } from 'openapi-types';
|
import { OpenAPIV3_1 } from 'openapi-types';
|
||||||
import { toPascal } from 'ts-case-convert';
|
import { toPascal } from 'ts-case-convert';
|
||||||
import OpenAPIParser from '@readme/openapi-parser';
|
import * as OpenAPIParser from '@readme/openapi-parser';
|
||||||
import openapiTS, { OpenAPI3, OperationObject, PathItemObject } from 'openapi-typescript';
|
import openapiTS, { astToString, OpenAPI3, OperationObject, PathItemObject } from 'openapi-typescript';
|
||||||
|
import ts from 'typescript';
|
||||||
|
import { createConfig } from '@redocly/openapi-core';
|
||||||
|
|
||||||
async function generateBaseTypes(
|
async function generateBaseTypes(
|
||||||
openApiDocs: OpenAPIV3_1.Document,
|
openApiDocs: OpenAPIV3_1.Document,
|
||||||
|
|
@ -21,6 +23,10 @@ async function generateBaseTypes(
|
||||||
}
|
}
|
||||||
lines.push('');
|
lines.push('');
|
||||||
|
|
||||||
|
// https://openapi-ts.dev/node#transform-posttransform
|
||||||
|
const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Blob'));
|
||||||
|
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull());
|
||||||
|
|
||||||
// NOTE: Align `operationId` of GET and POST to avoid duplication of type definitions
|
// NOTE: Align `operationId` of GET and POST to avoid duplication of type definitions
|
||||||
const openApi = JSON.parse(await readFile(openApiJsonPath, 'utf8')) as OpenAPI3;
|
const openApi = JSON.parse(await readFile(openApiJsonPath, 'utf8')) as OpenAPI3;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
|
@ -43,15 +49,54 @@ async function generateBaseTypes(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn off redocly so it doesn't complain about our schema.
|
||||||
|
// https://openapi-ts.dev/node#redoc-config
|
||||||
|
const redocly = await createConfig({
|
||||||
|
extends: [],
|
||||||
|
rules: {},
|
||||||
|
});
|
||||||
|
// redocly.getRulesForSpecVersion ??= () => [];
|
||||||
|
|
||||||
const generatedTypes = await openapiTS(openApi, {
|
const generatedTypes = await openapiTS(openApi, {
|
||||||
|
redocly,
|
||||||
exportType: true,
|
exportType: true,
|
||||||
transform(schemaObject) {
|
transform(schemaObject) {
|
||||||
if ('format' in schemaObject && schemaObject.format === 'binary') {
|
if ('format' in schemaObject && schemaObject.format === 'binary') {
|
||||||
return schemaObject.nullable ? 'Blob | null' : 'Blob';
|
return schemaObject.nullable ? ts.factory.createUnionTypeNode([BLOB, NULL]) : BLOB;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
lines.push(generatedTypes);
|
|
||||||
|
// Remove duplicate operations.
|
||||||
|
// Our schema depends on having get/post both point to the same object, but redocly doesn't collapse them like the previous implementation did.
|
||||||
|
for (let i = 0; i < generatedTypes.length; i++) {
|
||||||
|
const node = generatedTypes[i];
|
||||||
|
if (!ts.isInterfaceDeclaration(node) || node.name.text !== 'operations') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const seenNames = new Set<string>();
|
||||||
|
const newMembers = ts.visitNodes(node.members, member => {
|
||||||
|
if (ts.isPropertySignature(member) && 'text' in member.name) {
|
||||||
|
if (seenNames.has(member.name.text)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
seenNames.add(member.name.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return member;
|
||||||
|
}, ts.isTypeElement);
|
||||||
|
|
||||||
|
// Replace the node with a copy containing new members array
|
||||||
|
const newOperations: ts.InterfaceDeclaration = {
|
||||||
|
...node,
|
||||||
|
members: newMembers,
|
||||||
|
};
|
||||||
|
generatedTypes[i] = newOperations;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push(astToString(generatedTypes));
|
||||||
lines.push('');
|
lines.push('');
|
||||||
|
|
||||||
await writeFile(typeFileName, lines.join('\n'));
|
await writeFile(typeFileName, lines.join('\n'));
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ export class APIClient {
|
||||||
return ep in endpointReqTypes;
|
return ep in endpointReqTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public request<E extends keyof Endpoints, P extends Endpoints[E]['req']>(
|
public request<E extends keyof Endpoints, P extends Endpoints[E]['req'] & object>(
|
||||||
endpoint: E,
|
endpoint: E,
|
||||||
params: P = {} as P,
|
params: P = {} as P,
|
||||||
credential?: string | null,
|
credential?: string | null,
|
||||||
|
|
|
||||||
12441
pnpm-lock.yaml
generated
12441
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue