/**
* Twenty CRM GraphQL Client
*
* Infrastructure layer client for Twenty CRM GraphQL API.
* Handles GraphQL queries and mutations for all Twenty CRM entities.
*/
import { GraphQLClient } from 'graphql-request';
import { ILogger } from '../logging/logger.js';
/**
* GraphQL client interface for Twenty CRM
*/
export interface ITwentyGraphQLClient {
query<T>(query: string, variables?: Record<string, any>): Promise<T | null>;
mutate<T>(mutation: string, variables?: Record<string, any>): Promise<T | null>;
}
/**
* Twenty CRM GraphQL Client implementation
*/
export class TwentyGraphQLClient implements ITwentyGraphQLClient {
private readonly client: GraphQLClient;
private readonly logger: ILogger;
constructor(apiUrl: string, apiKey: string, logger: ILogger) {
this.logger = logger;
const graphqlEndpoint = `${apiUrl}/graphql`;
this.client = new GraphQLClient(graphqlEndpoint, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
});
this.logger.info('Twenty GraphQL client initialized', { endpoint: graphqlEndpoint });
}
/**
* Execute a GraphQL query
*
* @param query - GraphQL query string
* @param variables - Query variables
* @returns Query result or null on error
*/
async query<T>(query: string, variables?: Record<string, any>): Promise<T | null> {
try {
this.logger.debug('Executing GraphQL query', { query, variables });
const result = await this.client.request<T>(query, variables);
this.logger.debug('GraphQL query successful');
return result;
} catch (error) {
this.logger.error(
'GraphQL query failed',
error instanceof Error ? error : new Error(String(error)),
{ query, variables }
);
return null;
}
}
/**
* Execute a GraphQL mutation
*
* @param mutation - GraphQL mutation string
* @param variables - Mutation variables
* @returns Mutation result or null on error
*/
async mutate<T>(mutation: string, variables?: Record<string, any>): Promise<T | null> {
try {
this.logger.debug('Executing GraphQL mutation', { mutation, variables });
const result = await this.client.request<T>(mutation, variables);
this.logger.debug('GraphQL mutation successful');
return result;
} catch (error) {
this.logger.error(
'GraphQL mutation failed',
error instanceof Error ? error : new Error(String(error)),
{ mutation, variables }
);
return null;
}
}
}
/**
* Factory function to create Twenty GraphQL client
*
* @param logger - Logger instance
* @returns Twenty GraphQL client instance
*/
export function createTwentyGraphQLClient(logger: ILogger): ITwentyGraphQLClient {
const apiUrl = process.env.TWENTY_API_URL || 'https://api.twenty.com';
const apiKey = process.env.TWENTY_API_KEY || '';
if (!apiKey) {
logger.error('TWENTY_API_KEY environment variable is not set', new Error('Missing API key'));
throw new Error('TWENTY_API_KEY environment variable is required');
}
return new TwentyGraphQLClient(apiUrl, apiKey, logger);
}