all repos — kitten @ 93ed15a9146fe5650eb8c207730a35b299ad116d

types: include different possible status codes + associated payloads
vi did:web:vt3e.cat
Fri, 19 Jun 2026 08:59:48 +0100
commit

93ed15a9146fe5650eb8c207730a35b299ad116d

parent

e55d280b5d06b56248a949d7c62b63fe09ffda55

3 files changed, 65 insertions(+), 22 deletions(-)

jump to
M pkgs/types/package.jsonpkgs/types/package.json

@@ -1,6 +1,6 @@

{ "name": "@purrkit/types", - "version": "1,0,0", + "version": "1.1.0", "files": [ "dist", "README.md",
M pkgs/types/scripts/generate.tspkgs/types/scripts/generate.ts

@@ -1,7 +1,7 @@

-import * as fs from "fs/promises"; -import * as path from "path"; -import { OpenAPISpec } from "../src/generator/types"; +import * as fs from "node:fs/promises"; +import * as path from "node:path"; import { generateModelsSpec, generateRoutesSpec } from "../src/generator/generator"; +import type { OpenAPISpec } from "../src/generator/types"; const SPEC_URL = "https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json";
M pkgs/types/src/generator/generator.tspkgs/types/src/generator/generator.ts

@@ -1,8 +1,18 @@

-import { JSONSchema } from "./types"; +import type { JSONSchema } from "./types"; + +const RESPONSE_REFS_MAP: Record<string, string> = { + ClientErrorResponse: "ErrorResponse", + ClientRatelimitedResponse: "RatelimitedResponse", + BadRequest: "ErrorResponse", + Unauthorized: "ErrorResponse", + Forbidden: "ErrorResponse", + NotFound: "ErrorResponse", +}; export function generateTypeScriptSpec( schemas: Record<string, JSONSchema>, paths: Record<string, any>, + responses: Record<string, any> = {}, ): string { const output: string[] = [];

@@ -35,7 +45,7 @@ continue;

} output.push(` ${method.toLowerCase()}: {`); - const opDetails = resolvePathOperation(operation); + const opDetails = resolvePathOperation(operation, "", responses); output.push(opDetails); output.push(" };"); }

@@ -69,7 +79,11 @@

return output.join("\n"); } -export function generateRoutesSpec(paths: Record<string, any>, modelNamespace = "Models"): string { +export function generateRoutesSpec( + paths: Record<string, any>, + modelNamespace = "Models", + responses: Record<string, any> = {}, +): string { const output: string[] = []; output.push("// this file is auto-generated. don;t edit it manually.");

@@ -88,7 +102,7 @@ continue;

} output.push(` ${method.toLowerCase()}: {`); - const opDetails = resolvePathOperation(operation, modelNamespace); + const opDetails = resolvePathOperation(operation, modelNamespace, responses); output.push(opDetails); output.push(" };"); }

@@ -183,9 +197,11 @@ export function resolvePropertyType(schema: JSONSchema, namespace = ""): string {

if (!schema) return "any"; if (schema.$ref) { - const refName = schema.$ref.split("/").pop() || "unknown"; + let refName = schema.$ref.split("/").pop() || "unknown"; if (refName.toLowerCase().includes("snowflake")) return namespace ? `${namespace}.Snowflake` : "Snowflake"; + + if (RESPONSE_REFS_MAP[refName]) refName = RESPONSE_REFS_MAP[refName]; return namespace ? `${namespace}.${refName}` : refName; }

@@ -213,7 +229,35 @@

return "any"; } -function resolvePathOperation(operation: any, namespace = ""): string { +function resolveResponse( + responseObj: any, + namespace = "", + responses: Record<string, any> = {}, +): string { + if (!responseObj) return "unknown"; + + if (responseObj.$ref) { + const refName = responseObj.$ref.split("/").pop(); + if (refName && responses[refName]) + return resolveResponse(responses[refName], namespace, responses); + + return resolvePropertyType(responseObj, namespace); + } + + const content = responseObj.content; + if (content?.["application/json"]) { + const schema = content["application/json"].schema; + return resolvePropertyType(schema, namespace); + } + + return "void"; +} + +function resolvePathOperation( + operation: any, + namespace = "", + responses: Record<string, any> = {}, +): string { const parts: string[] = []; const parameters = operation.parameters || []; const pathParams = parameters.filter((p: any) => p.in === "path");

@@ -248,26 +292,25 @@

const requestBody = operation.requestBody; if (requestBody) { const content = requestBody.content; - if (content && content["application/json"]) { + if (content?.["application/json"]) { const schema = content["application/json"].schema; parts.push(` requestBody: ${resolvePropertyType(schema, namespace)};`); } } - const responses = operation.responses || {}; - const successCode = Object.keys(responses).find((code) => code.startsWith("2")); - if (successCode) { - const responseObj = responses[successCode]; - const content = responseObj.content; + const opsResponses = operation.responses || {}; + const responseKeys = Object.keys(opsResponses); - if (content && content["application/json"]) { - const schema = content["application/json"].schema; - parts.push(` response: ${resolvePropertyType(schema, namespace)};`); - } else { - parts.push(" response: void;"); + if (responseKeys.length > 0) { + parts.push(" responses: {"); + for (const [code, responseObj] of Object.entries(opsResponses)) { + const formattedKey = /^\d+$/.test(code) ? code : `"${code}"`; + const resolvedType = resolveResponse(responseObj, namespace, responses); + parts.push(` ${formattedKey}: ${resolvedType};`); } + parts.push(" };"); } else { - parts.push(" response: unknown;"); + parts.push(" responses: {};"); } return parts.join("\n");