Skip to content

Commit

Permalink
Format typegen script
Browse files Browse the repository at this point in the history
  • Loading branch information
ZiomaleQ committed Sep 3, 2023
1 parent c1bb7dd commit 330ac2d
Showing 1 changed file with 58 additions and 57 deletions.
115 changes: 58 additions & 57 deletions scripts/endpoint_typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,82 @@ const $ = async (...cmd: string[]) => {
const proc = new Deno.Command(cmd.join(" "), {
stdout: "piped",
stderr: "piped",
})
const childProc = proc.spawn()
const status = await childProc.status
return status.code
}
});
const childProc = proc.spawn();
const status = await childProc.status;
return status.code;
};

const API_DOCS_URL =
"https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json"
"https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json";

interface Endpoint {
title: string
name: string
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"
url: string
params: string[]
title: string;
name: string;
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
url: string;
params: string[];
}

const endpoints: Endpoint[] = []
const endpoints: Endpoint[] = [];

const jsonDocs = await fetch(API_DOCS_URL).then((e) => e.json())
const jsonDocs = await fetch(API_DOCS_URL).then((e) => e.json());

type ApiParam = {
name: string
in: "query" | "path"
name: string;
in: "query" | "path";
schema: {
type: string[]
format: string
}
}
type: string[];
format: string;
};
};

type OpenApiInfo = {
operationId: string
responses: Record<string, { description: string; content: string }>
security: Record<string, never>[]
parameters?: ApiParam[]
}
operationId: string;
responses: Record<string, { description: string; content: string }>;
security: Record<string, never>[];
parameters?: ApiParam[];
};

for (const [path, data] of Object.entries(jsonDocs.paths)) {
const preParams: ApiParam[] = []
const preParams: ApiParam[] = [];

Object.entries(data as Record<string, OpenApiInfo | ApiParam[]>).find(
([method, info]) => {
if (method === "parameters") {
preParams.push(...info as ApiParam[])
preParams.push(...info as ApiParam[]);
}
},
)
);

for (
const [method, info] of Object.entries(data as Record<string, OpenApiInfo>)
) {
if (method === "parameters") continue
if (method === "parameters") continue;

const swapped: Record<string, string> = {}
const swapped: Record<string, string> = {};

const splitName = info.operationId.split("_").map((e) =>
e[0].toUpperCase() + e.slice(1)
)
);

const params = [...preParams, ...(info?.parameters ?? [])].filter((e) =>
e.in === "path"
)
);

let url = path
let url = path;

params.forEach((param) => {
const oldName = param.name
const oldName = param.name;
const newName = param.name.split("_").map((e) =>
e[0].toUpperCase() + e.slice(1)
).join("").replace("Id", "ID")
).join("").replace("Id", "ID");

swapped[oldName] = newName
})
swapped[oldName] = newName;
});

for (const [oldName, newName] of Object.entries(swapped)) {
url = url.replace(`{${oldName}}`, "${" + newName + "}")
url = url.replace(`{${oldName}}`, "${" + newName + "}");
}

endpoints.push({
Expand All @@ -86,51 +86,52 @@ for (const [path, data] of Object.entries(jsonDocs.paths)) {
method: method.toUpperCase() as Endpoint["method"],
url: url,
params: params.map((e) => swapped[e.name]),
})
});
}
}

let types =
`// NOTE: This file is auto-generated by scripts/endpoint_typegen.ts\n\nimport { snowflake } from "./common.ts";\n\n`
`// NOTE: This file is auto-generated by scripts/endpoint_typegen.ts\n\nimport { snowflake } from "./common.ts";\n\n`;

function getParamType(name: string): string {
if (name.endsWith("ID")) {
return "snowflake"
return "snowflake";
} else if (
name.endsWith("Token") || name.endsWith("Emoji") || name.endsWith("Code") ||
name === "EmojiName"
) {
return "string"
} else throw new Error(`Unable to infer Param Type: ${name}`)
return "string";
} else throw new Error(`Unable to infer Param Type: ${name}`);
}

for (const endpoint of endpoints) {
types += `/**\n * ${endpoint.title}\n * @method ${endpoint.method}\n */\n`
types += `export type ${endpoint.name}Endpoint`
types += `/**\n * ${endpoint.title}\n * @method ${endpoint.method}\n */\n`;
types += `export type ${endpoint.name}Endpoint`;
if (endpoint.params.length) {
types += `<\n`
types += `<\n`;
for (const param of endpoint.params) {
const type = getParamType(param)
types += ` ${param} extends ${type} = ${type},\n`
const type = getParamType(param);
types += ` ${param} extends ${type} = ${type},\n`;
}
types += `>`
types += `>`;
}
types += ` = \`${endpoint.url}\`;\n\n`
types += ` = \`${endpoint.url}\`;\n\n`;
}

types += `export type Endpoint =\n`
types += `export type Endpoint =\n`;
for (const _ in endpoints) {
const i = Number(_)
const endpoint = endpoints[i]
types += ` | ${endpoint.name}Endpoint${i === endpoints.length - 1 ? ";" : ""
}\n`
const i = Number(_);
const endpoint = endpoints[i];
types += ` | ${endpoint.name}Endpoint${
i === endpoints.length - 1 ? ";" : ""
}\n`;
}

const TYPES_FILE = new URL("../types/src/endpoints.ts", import.meta.url)
const TYPES_FILE = new URL("../types/src/endpoints.ts", import.meta.url);
await Deno.writeTextFile(
TYPES_FILE,
types,
)
);

await $(
"deno",
Expand All @@ -140,4 +141,4 @@ await $(
TYPES_FILE.pathname,
);

console.log("Generated Endpoint Types!")
console.log("Generated Endpoint Types!");

0 comments on commit 330ac2d

Please sign in to comment.