fix misskey-js generator compatibility with openapi-typescript 7.x

This commit is contained in:
Hazelnoot 2025-10-02 22:02:22 -04:00
parent 48edf3d71f
commit d0f2463bc6
4 changed files with 6949 additions and 5548 deletions

View file

@ -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",

View file

@ -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'));

View file

@ -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

File diff suppressed because it is too large Load diff