import { z } from "zod";
import { RestApiValidationError } from "../../errors.js";
import type { TraceMetadata } from "../registry.js";
import { RestApiClientBase } from "./rest-api-client-base.js";
import type {
ApiRequestOptions,
ApiRequestSchema,
RestApiResponseType,
SupportsApiRequest,
} from "./types.js";
export abstract class RestApiIntegrationClient
extends RestApiClientBase
implements SupportsApiRequest
{
async apiRequest
(
options: ApiRequestOptions & {
responseType?: Exclude;
},
schema: ApiRequestSchema & {
response: z.ZodSchema;
},
metadata?: TraceMetadata,
): Promise;
async apiRequest(
options: ApiRequestOptions & {
responseType: "binary";
},
schema?: ApiRequestSchema,
metadata?: TraceMetadata,
): Promise;
async apiRequest(
options: ApiRequestOptions & {
responseType: "text";
},
schema?: ApiRequestSchema,
metadata?: TraceMetadata,
): Promise;
async apiRequest(
options: ApiRequestOptions,
schema?: ApiRequestSchema,
metadata?: TraceMetadata,
): Promise {
if ((options.responseType ?? "json") === "json" && !schema?.response) {
throw new RestApiValidationError(
'apiRequest() with responseType "json" requires a response schema. Provide one, or set responseType to "text" or "binary"',
{
zodError: new z.ZodError([
{
code: z.ZodIssueCode.custom,
message: "response schema is required for JSON responses",
path: ["response"],
},
]),
data: undefined,
},
);
}
const result = await this.executeApiRequest(
options,
schema?.body,
metadata,
);
if (!schema?.response) {
return result;
}
const responseParseResult = schema.response.safeParse(result);
if (!responseParseResult.success) {
throw new RestApiValidationError(
`Response validation failed: ${responseParseResult.error.message}`,
{
data: result,
zodError: responseParseResult.error,
},
);
}
return responseParseResult.data;
}
}