43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
|
|
import { z } from "zod/v4";
|
||
|
|
|
||
|
|
import type { ResourceDefinitionSpec } from "../common";
|
||
|
|
import { CatalogResponseSchema, SaveDefinitionResponseSchema } from "../common";
|
||
|
|
export const catalogKeys = { scope: (scope: string) => ["resource-catalog", scope] };
|
||
|
|
export class CatalogApiError extends Error {
|
||
|
|
constructor(public readonly code: string) {
|
||
|
|
super(code);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async function request(path: string, body?: unknown, csrfToken?: string) {
|
||
|
|
const response = await fetch(`/api/resource-catalog/${path}`, {
|
||
|
|
method: body === undefined ? "GET" : "POST",
|
||
|
|
credentials: "same-origin",
|
||
|
|
headers:
|
||
|
|
body === undefined
|
||
|
|
? {}
|
||
|
|
: { "content-type": "application/json", "x-csrf-token": csrfToken ?? "" },
|
||
|
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
||
|
|
});
|
||
|
|
const json: unknown = await response.json();
|
||
|
|
if (!response.ok) {
|
||
|
|
const error = z.object({ code: z.string() }).safeParse(json);
|
||
|
|
throw new CatalogApiError(error.success ? error.data.code : "INTERNAL_ERROR");
|
||
|
|
}
|
||
|
|
return json;
|
||
|
|
}
|
||
|
|
export const catalogApi = {
|
||
|
|
async get(scope: string) {
|
||
|
|
return CatalogResponseSchema.parse(await request(scope));
|
||
|
|
},
|
||
|
|
async save(scope: string, values: ResourceDefinitionSpec, csrfToken: string, id?: string) {
|
||
|
|
return SaveDefinitionResponseSchema.parse(
|
||
|
|
await request(`${scope}${id ? `/${id}/update` : ""}`, { values }, csrfToken)
|
||
|
|
);
|
||
|
|
},
|
||
|
|
async status(scope: string, id: string, active: boolean | null, csrfToken: string) {
|
||
|
|
return CatalogResponseSchema.parse(
|
||
|
|
await request(`${scope}/${id}/status`, { active }, csrfToken)
|
||
|
|
);
|
||
|
|
},
|
||
|
|
};
|