🚀 Features:
- 269 MCP tools across 19+ categories
- Complete GoHighLevel API integration
- Private Integrations API key support
- One-click deployment to Vercel/Railway
- Comprehensive documentation
- Community-driven development
Built for the GoHighLevel community to accelerate AI automation adoption.
319 lines
7.6 KiB
TypeScript
319 lines
7.6 KiB
TypeScript
/**
|
|
* Mock implementation of GHLApiClient for testing
|
|
* Provides realistic test data without making actual API calls
|
|
*/
|
|
|
|
import {
|
|
GHLApiResponse,
|
|
GHLContact,
|
|
GHLConversation,
|
|
GHLMessage,
|
|
GHLBlogPost,
|
|
GHLBlogSite,
|
|
GHLBlogAuthor,
|
|
GHLBlogCategory
|
|
} from '../../src/types/ghl-types.js';
|
|
|
|
// Mock test data
|
|
export const mockContact: GHLContact = {
|
|
id: 'contact_123',
|
|
locationId: 'test_location_123',
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
name: 'John Doe',
|
|
email: 'john.doe@example.com',
|
|
phone: '+1-555-123-4567',
|
|
tags: ['test', 'customer'],
|
|
source: 'ChatGPT MCP',
|
|
dateAdded: '2024-01-01T00:00:00.000Z',
|
|
dateUpdated: '2024-01-01T00:00:00.000Z'
|
|
};
|
|
|
|
export const mockConversation: GHLConversation = {
|
|
id: 'conv_123',
|
|
contactId: 'contact_123',
|
|
locationId: 'test_location_123',
|
|
lastMessageBody: 'Test message',
|
|
lastMessageType: 'TYPE_SMS',
|
|
type: 'SMS',
|
|
unreadCount: 0,
|
|
fullName: 'John Doe',
|
|
contactName: 'John Doe',
|
|
email: 'john.doe@example.com',
|
|
phone: '+1-555-123-4567'
|
|
};
|
|
|
|
export const mockMessage: GHLMessage = {
|
|
id: 'msg_123',
|
|
type: 1,
|
|
messageType: 'TYPE_SMS',
|
|
locationId: 'test_location_123',
|
|
contactId: 'contact_123',
|
|
conversationId: 'conv_123',
|
|
dateAdded: '2024-01-01T00:00:00.000Z',
|
|
body: 'Test SMS message',
|
|
direction: 'outbound',
|
|
status: 'sent',
|
|
contentType: 'text/plain'
|
|
};
|
|
|
|
export const mockBlogPost: GHLBlogPost = {
|
|
_id: 'post_123',
|
|
title: 'Test Blog Post',
|
|
description: 'Test blog post description',
|
|
imageUrl: 'https://example.com/image.jpg',
|
|
imageAltText: 'Test image',
|
|
urlSlug: 'test-blog-post',
|
|
author: 'author_123',
|
|
publishedAt: '2024-01-01T00:00:00.000Z',
|
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
|
status: 'PUBLISHED',
|
|
categories: ['cat_123'],
|
|
tags: ['test', 'blog'],
|
|
archived: false,
|
|
rawHTML: '<h1>Test Content</h1>'
|
|
};
|
|
|
|
export const mockBlogSite: GHLBlogSite = {
|
|
_id: 'blog_123',
|
|
name: 'Test Blog Site'
|
|
};
|
|
|
|
export const mockBlogAuthor: GHLBlogAuthor = {
|
|
_id: 'author_123',
|
|
name: 'Test Author',
|
|
locationId: 'test_location_123',
|
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
|
canonicalLink: 'https://example.com/author/test'
|
|
};
|
|
|
|
export const mockBlogCategory: GHLBlogCategory = {
|
|
_id: 'cat_123',
|
|
label: 'Test Category',
|
|
locationId: 'test_location_123',
|
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
|
canonicalLink: 'https://example.com/category/test',
|
|
urlSlug: 'test-category'
|
|
};
|
|
|
|
/**
|
|
* Mock GHL API Client class
|
|
*/
|
|
export class MockGHLApiClient {
|
|
private config = {
|
|
accessToken: 'test_token',
|
|
baseUrl: 'https://test.leadconnectorhq.com',
|
|
version: '2021-07-28',
|
|
locationId: 'test_location_123'
|
|
};
|
|
|
|
// Contact methods
|
|
async createContact(contactData: any): Promise<GHLApiResponse<GHLContact>> {
|
|
return {
|
|
success: true,
|
|
data: { ...mockContact, ...contactData, id: 'contact_' + Date.now() }
|
|
};
|
|
}
|
|
|
|
async getContact(contactId: string): Promise<GHLApiResponse<GHLContact>> {
|
|
if (contactId === 'not_found') {
|
|
throw new Error('GHL API Error (404): Contact not found');
|
|
}
|
|
return {
|
|
success: true,
|
|
data: { ...mockContact, id: contactId }
|
|
};
|
|
}
|
|
|
|
async updateContact(contactId: string, updates: any): Promise<GHLApiResponse<GHLContact>> {
|
|
return {
|
|
success: true,
|
|
data: { ...mockContact, ...updates, id: contactId }
|
|
};
|
|
}
|
|
|
|
async deleteContact(contactId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
return {
|
|
success: true,
|
|
data: { succeded: true }
|
|
};
|
|
}
|
|
|
|
async searchContacts(searchParams: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
contacts: [mockContact],
|
|
total: 1
|
|
}
|
|
};
|
|
}
|
|
|
|
async addContactTags(contactId: string, tags: string[]): Promise<GHLApiResponse<{ tags: string[] }>> {
|
|
return {
|
|
success: true,
|
|
data: { tags: [...mockContact.tags!, ...tags] }
|
|
};
|
|
}
|
|
|
|
async removeContactTags(contactId: string, tags: string[]): Promise<GHLApiResponse<{ tags: string[] }>> {
|
|
return {
|
|
success: true,
|
|
data: { tags: mockContact.tags!.filter(tag => !tags.includes(tag)) }
|
|
};
|
|
}
|
|
|
|
// Conversation methods
|
|
async sendSMS(contactId: string, message: string, fromNumber?: string): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
messageId: 'msg_' + Date.now(),
|
|
conversationId: 'conv_123'
|
|
}
|
|
};
|
|
}
|
|
|
|
async sendEmail(contactId: string, subject: string, message?: string, html?: string, options?: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
messageId: 'msg_' + Date.now(),
|
|
conversationId: 'conv_123',
|
|
emailMessageId: 'email_' + Date.now()
|
|
}
|
|
};
|
|
}
|
|
|
|
async searchConversations(searchParams: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
conversations: [mockConversation],
|
|
total: 1
|
|
}
|
|
};
|
|
}
|
|
|
|
async getConversation(conversationId: string): Promise<GHLApiResponse<GHLConversation>> {
|
|
return {
|
|
success: true,
|
|
data: { ...mockConversation, id: conversationId }
|
|
};
|
|
}
|
|
|
|
async createConversation(conversationData: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
id: 'conv_' + Date.now(),
|
|
dateUpdated: new Date().toISOString(),
|
|
dateAdded: new Date().toISOString(),
|
|
deleted: false,
|
|
contactId: conversationData.contactId,
|
|
locationId: conversationData.locationId,
|
|
lastMessageDate: new Date().toISOString()
|
|
}
|
|
};
|
|
}
|
|
|
|
async updateConversation(conversationId: string, updates: any): Promise<GHLApiResponse<GHLConversation>> {
|
|
return {
|
|
success: true,
|
|
data: { ...mockConversation, ...updates, id: conversationId }
|
|
};
|
|
}
|
|
|
|
async getConversationMessages(conversationId: string, options?: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
lastMessageId: 'msg_123',
|
|
nextPage: false,
|
|
messages: [mockMessage]
|
|
}
|
|
};
|
|
}
|
|
|
|
// Blog methods
|
|
async createBlogPost(postData: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
data: { ...mockBlogPost, ...postData, _id: 'post_' + Date.now() }
|
|
}
|
|
};
|
|
}
|
|
|
|
async updateBlogPost(postId: string, postData: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
updatedBlogPost: { ...mockBlogPost, ...postData, _id: postId }
|
|
}
|
|
};
|
|
}
|
|
|
|
async getBlogPosts(params: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
blogs: [mockBlogPost]
|
|
}
|
|
};
|
|
}
|
|
|
|
async getBlogSites(params: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
data: [mockBlogSite]
|
|
}
|
|
};
|
|
}
|
|
|
|
async getBlogAuthors(params: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
authors: [mockBlogAuthor]
|
|
}
|
|
};
|
|
}
|
|
|
|
async getBlogCategories(params: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
categories: [mockBlogCategory]
|
|
}
|
|
};
|
|
}
|
|
|
|
async checkUrlSlugExists(params: any): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
exists: params.urlSlug === 'existing-slug'
|
|
}
|
|
};
|
|
}
|
|
|
|
async testConnection(): Promise<GHLApiResponse<any>> {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
status: 'connected',
|
|
locationId: this.config.locationId
|
|
}
|
|
};
|
|
}
|
|
|
|
getConfig() {
|
|
return { ...this.config };
|
|
}
|
|
|
|
updateAccessToken(newToken: string): void {
|
|
this.config.accessToken = newToken;
|
|
}
|
|
}
|