/** * Test script for full sync with Autotask * Run with: npx tsx dev/test-full-sync.ts * * This script tests the full sync functionality with a small dataset * by limiting the number of records fetched from Autotask. */ import dotenv from 'dotenv'; import path from 'path'; // Load environment variables from .env.local FIRST dotenv.config({ path: path.resolve(__dirname, '../.env.local') }); import { AutotaskClient } from '../lib/services/autotask-client'; import { createSyncService } from '../lib/services/sync-service'; import { EntityType } from '../lib/types/sync'; import postgresClient from '../lib/services/postgres-client'; async function testFullSync() { console.log('šŸ” Testing Full Sync with Autotask\n'); // Check environment variables console.log('Environment Configuration:'); console.log(' AUTOTASK_API_URL:', process.env.AUTOTASK_API_URL); console.log(' AUTOTASK_USERNAME:', process.env.AUTOTASK_USERNAME ? '[SET]' : '[NOT SET]'); console.log(' AUTOTASK_SECRET:', process.env.AUTOTASK_SECRET ? '[SET]' : '[NOT SET]'); console.log(' AUTOTASK_API_INTEGRATION_CODE:', process.env.AUTOTASK_API_INTEGRATION_CODE ? '[SET]' : '[NOT SET]'); console.log(' POSTGRES_HOST:', process.env.POSTGRES_HOST); console.log(' POSTGRES_DB:', process.env.POSTGRES_DB); console.log(); // Validate required environment variables if (!process.env.AUTOTASK_API_URL || !process.env.AUTOTASK_USERNAME || !process.env.AUTOTASK_SECRET || !process.env.AUTOTASK_API_INTEGRATION_CODE) { console.error('āŒ Missing required Autotask environment variables'); console.error('Please ensure .env.local contains:'); console.error(' - AUTOTASK_API_URL'); console.error(' - AUTOTASK_USERNAME'); console.error(' - AUTOTASK_SECRET'); console.error(' - AUTOTASK_API_INTEGRATION_CODE'); process.exit(1); } try { // Test 1: Database connection console.log('Test 1: Verify database connection'); const dbConnected = await postgresClient.testConnection(); if (!dbConnected) { console.error('āŒ Database connection failed'); process.exit(1); } console.log('āœ… Database connection successful\n'); // Test 2: Create Autotask client console.log('Test 2: Initialize Autotask client'); const autotaskClient = new AutotaskClient({ apiUrl: process.env.AUTOTASK_API_URL!, username: process.env.AUTOTASK_USERNAME!, password: process.env.AUTOTASK_SECRET!, apiIntegrationCode: process.env.AUTOTASK_API_INTEGRATION_CODE!, }); console.log('āœ… Autotask client initialized\n'); // Test 3: Test Autotask API connection with a simple query console.log('Test 3: Test Autotask API connection'); try { // Try to fetch a small number of companies to test the connection const testCompanies = await autotaskClient.queryEntity('Companies', { filter: [{ field: 'isActive', op: 'eq', value: true }], maxRecords: 5, }); console.log(`āœ… Autotask API connection successful (fetched ${testCompanies.length} test companies)\n`); } catch (error) { console.error('āŒ Autotask API connection failed:', error); console.error('\nPlease verify:'); console.error(' 1. API credentials are correct'); console.error(' 2. API integration code is valid'); console.error(' 3. Network connectivity to Autotask API'); process.exit(1); } // Test 4: Create sync service console.log('Test 4: Initialize sync service'); const syncService = createSyncService(autotaskClient); console.log('āœ… Sync service initialized\n'); // Test 5: Sync a single entity (Companies) as a small test console.log('Test 5: Sync Companies entity (limited dataset)'); console.log('Note: This will sync only active companies to limit data volume\n'); const startTime = Date.now(); try { const result = await syncService.syncEntities( [EntityType.COMPANIES], undefined, 'test-script' ); const duration = Date.now() - startTime; console.log('\n=== SYNC RESULTS ==='); console.log(`Sync ID: ${result.syncId}`); console.log(`Status: ${result.status}`); console.log(`Duration: ${duration}ms`); console.log(`\nRecords:`); console.log(` Added: ${result.totalRecordsAdded}`); console.log(` Updated: ${result.totalRecordsUpdated}`); console.log(` Deleted: ${result.totalRecordsDeleted}`); if (result.errors && result.errors.length > 0) { console.log(`\nErrors:`); result.errors.forEach(error => console.log(` - ${error}`)); } console.log('\n=== ENTITY DETAILS ==='); result.entities.forEach(entity => { const status = entity.success ? 'āœ…' : 'āŒ'; console.log(`${status} ${entity.entityType}:`); console.log(` Added: ${entity.recordsAdded}, Updated: ${entity.recordsUpdated}, Deleted: ${entity.recordsDeleted}`); console.log(` Duration: ${entity.duration}ms`); if (entity.error) { console.log(` Error: ${entity.error}`); } }); if (result.status === 'completed') { console.log('\nāœ… Companies sync completed successfully!'); } else { console.log('\nāš ļø Companies sync completed with errors'); } } catch (error) { console.error('\nāŒ Sync failed:', error); throw error; } // Test 6: Verify data in database console.log('\nTest 6: Verify synced data in database'); const companyCount = await postgresClient.count('companies', { is_deleted: false }); console.log(`āœ… Found ${companyCount} companies in database\n`); // Test 7: Check sync history console.log('Test 7: Check sync history'); const syncHistory = await syncService.getSyncHistory(5, EntityType.COMPANIES); console.log(`āœ… Found ${syncHistory.length} sync history records`); if (syncHistory.length > 0) { const latest = syncHistory[0]; console.log(` Latest sync:`); console.log(` Entity: ${latest.entity_type}`); console.log(` Status: ${latest.status}`); console.log(` Started: ${latest.started_at}`); console.log(` Completed: ${latest.completed_at}`); console.log(` Records: +${latest.records_added} ~${latest.records_updated} -${latest.records_deleted}`); } console.log(); // Optional: Test 8: Sync multiple entities (commented out to keep test small) /* console.log('Test 8: Sync multiple entities'); const multiResult = await syncService.syncEntities( [EntityType.COMPANIES, EntityType.RESOURCES, EntityType.STATUSES], undefined, 'test-script-multi' ); console.log(`āœ… Multi-entity sync completed: ${multiResult.status}`); console.log(` Total records: +${multiResult.totalRecordsAdded} ~${multiResult.totalRecordsUpdated} -${multiResult.totalRecordsDeleted}\n`); */ console.log('šŸŽ‰ All sync tests passed successfully!'); console.log('\n=== SUMMARY ==='); console.log('āœ… Database connection working'); console.log('āœ… Autotask API connection working'); console.log('āœ… Sync service operational'); console.log('āœ… Entity sync working'); console.log('āœ… Data persisted to database'); console.log('āœ… Sync history tracking working'); } catch (error) { console.error('\nāŒ Test failed with error:', error); if (error instanceof Error) { console.error('Stack trace:', error.stack); } process.exit(1); } finally { // Close database connection await postgresClient.close(); console.log('\nšŸ”Œ Database connection closed'); } } // Run the tests testFullSync() .then(() => { console.log('\nāœ… Test script completed successfully'); process.exit(0); }) .catch((error) => { console.error('\nāŒ Test script failed:', error); process.exit(1); });