Add wave-mcp/src/services/wave-client.ts
This commit is contained in:
parent
bc56a8cda8
commit
0228ee1f09
1 changed files with 62 additions and 0 deletions
62
wave-mcp/src/services/wave-client.ts
Normal file
62
wave-mcp/src/services/wave-client.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { WaveConfig, GraphQLResponse } from "../types.js";
|
||||
import { WAVE_GRAPHQL_URL, CHARACTER_LIMIT } from "../constants.js";
|
||||
|
||||
export class WaveClient {
|
||||
private accessToken: string;
|
||||
|
||||
constructor(config: WaveConfig) {
|
||||
this.accessToken = config.accessToken;
|
||||
}
|
||||
|
||||
// ── Core GraphQL executor ──────────────────────────────────────────────────
|
||||
|
||||
async query<T = unknown>(
|
||||
query: string,
|
||||
variables?: Record<string, unknown>
|
||||
): Promise<T> {
|
||||
const response = await fetch(WAVE_GRAPHQL_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify({ query, variables: variables ?? {} }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text().catch(() => "(no body)");
|
||||
throw new Error(
|
||||
`Wave API HTTP error ${response.status} ${response.statusText}: ${text.slice(0, 300)}`
|
||||
);
|
||||
}
|
||||
|
||||
const json = (await response.json()) as GraphQLResponse<T>;
|
||||
|
||||
if (json.errors?.length) {
|
||||
const messages = json.errors.map((e) => e.message).join("; ");
|
||||
throw new Error(`Wave GraphQL error: ${messages}`);
|
||||
}
|
||||
|
||||
if (json.data === undefined) {
|
||||
throw new Error("Wave API returned no data and no errors.");
|
||||
}
|
||||
|
||||
return json.data;
|
||||
}
|
||||
|
||||
// ── Formatting helpers ─────────────────────────────────────────────────────
|
||||
|
||||
/** Truncate a JSON response string if it exceeds CHARACTER_LIMIT */
|
||||
static truncate(text: string): string {
|
||||
if (text.length <= CHARACTER_LIMIT) return text;
|
||||
return (
|
||||
text.slice(0, CHARACTER_LIMIT) +
|
||||
`\n\n...[TRUNCATED: response exceeded ${CHARACTER_LIMIT} characters. Use pagination (page, pageSize) to retrieve more data.]`
|
||||
);
|
||||
}
|
||||
|
||||
static formatCurrency(value: number, code: string): string {
|
||||
return `${code} ${value.toFixed(2)}`;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue