82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
/**
|
|
* Regenerates src/endpoints.ts from the live Clarizen API docs.
|
|
* Requires CLARIZEN_API_KEY (or API_KEY_AW) in .env for Accept: text/html.
|
|
*/
|
|
import { writeFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const baseUrl = process.env.CLARIZEN_BASE_URL ?? "https://api.clarizen.com";
|
|
const apiKey = process.env.CLARIZEN_API_KEY ?? process.env.API_KEY_AW;
|
|
|
|
if (!apiKey) {
|
|
console.error("Set CLARIZEN_API_KEY or API_KEY_AW");
|
|
process.exit(1);
|
|
}
|
|
|
|
const indexRes = await fetch(`${baseUrl}/V2.0/services/`, {
|
|
headers: {
|
|
Authorization: `ApiKey ${apiKey}`,
|
|
Accept: "text/html",
|
|
},
|
|
});
|
|
|
|
const html = await indexRes.text();
|
|
const linkRe = /href="(\/V2\.0\/services\/[^"]+)"/g;
|
|
const paths = [...new Set([...html.matchAll(linkRe)].map((m) => m[1]))].filter(
|
|
(p) => !p.endsWith("/objects"),
|
|
);
|
|
|
|
const endpoints: Array<{
|
|
namespace: string;
|
|
operation: string;
|
|
path: string;
|
|
httpMethods: string[];
|
|
description: string;
|
|
}> = [];
|
|
|
|
for (const docPath of paths) {
|
|
const res = await fetch(`${baseUrl}${docPath}`, {
|
|
headers: {
|
|
Authorization: `ApiKey ${apiKey}`,
|
|
Accept: "text/html",
|
|
},
|
|
});
|
|
const page = await res.text();
|
|
const parts = docPath.split("/");
|
|
const namespace = parts[3] ?? "";
|
|
const operation = parts[4] ?? "";
|
|
const pathMatch = page.match(/<samp>([^<]+)<\/samp>/);
|
|
const methodMatch = page.match(
|
|
/<dt>HTTP Method<\/dt>\s*<dd><code>([^<]+)<\/code>/,
|
|
);
|
|
const descMatch = page.match(/<dt>Description<\/dt>\s*<dd>([^<]+)/);
|
|
|
|
endpoints.push({
|
|
namespace,
|
|
operation,
|
|
path: pathMatch?.[1] ?? docPath,
|
|
httpMethods: (methodMatch?.[1] ?? "POST")
|
|
.split(",")
|
|
.map((m) => m.trim().toUpperCase()),
|
|
description: (descMatch?.[1] ?? "")
|
|
.replace(/\u00a0/g, " ")
|
|
.trim(),
|
|
});
|
|
}
|
|
|
|
const namespaces = [...new Set(endpoints.map((e) => e.namespace))];
|
|
|
|
const out = `import type { EndpointDefinition } from "./types.js";
|
|
|
|
/** Auto-generated from ${baseUrl}/V2.0/services/ — run: npm run scrape */
|
|
export const ENDPOINTS: EndpointDefinition[] = ${JSON.stringify(endpoints, null, 2)};
|
|
|
|
export const NAMESPACES = ${JSON.stringify(namespaces, null, 2)} as const;
|
|
|
|
export type ClarizenNamespace = (typeof NAMESPACES)[number];
|
|
`;
|
|
|
|
const target = resolve(import.meta.dirname, "../src/endpoints.ts");
|
|
writeFileSync(target, out);
|
|
console.log(`Wrote ${endpoints.length} endpoints to ${target}`);
|