Initial commit: Cloud Instances API
Multi-cloud VM instance database with Cloudflare Workers - Linode, Vultr, AWS connector integration - D1 database with regions, instances, pricing - Query API with filtering, caching, pagination - Cron-based auto-sync (daily + 6-hourly) - Health monitoring endpoint Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
121
src/repositories/providers.ts
Normal file
121
src/repositories/providers.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Providers Repository
|
||||
* Handles CRUD operations for cloud providers
|
||||
*/
|
||||
|
||||
import { BaseRepository } from './base';
|
||||
import { Provider, ProviderInput, RepositoryError, ErrorCodes } from '../types';
|
||||
|
||||
export class ProvidersRepository extends BaseRepository<Provider> {
|
||||
protected tableName = 'providers';
|
||||
|
||||
/**
|
||||
* Find provider by name
|
||||
*/
|
||||
async findByName(name: string): Promise<Provider | null> {
|
||||
try {
|
||||
const result = await this.db
|
||||
.prepare('SELECT * FROM providers WHERE name = ?')
|
||||
.bind(name)
|
||||
.first<Provider>();
|
||||
|
||||
return result || null;
|
||||
} catch (error) {
|
||||
console.error('[ProvidersRepository] findByName failed:', error);
|
||||
throw new RepositoryError(
|
||||
`Failed to find provider by name: ${name}`,
|
||||
ErrorCodes.DATABASE_ERROR,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sync status for a provider
|
||||
*/
|
||||
async updateSyncStatus(
|
||||
name: string,
|
||||
status: 'pending' | 'syncing' | 'success' | 'error',
|
||||
error?: string
|
||||
): Promise<Provider> {
|
||||
try {
|
||||
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
||||
|
||||
const result = await this.db
|
||||
.prepare(
|
||||
`UPDATE providers
|
||||
SET sync_status = ?,
|
||||
sync_error = ?,
|
||||
last_sync_at = ?
|
||||
WHERE name = ?
|
||||
RETURNING *`
|
||||
)
|
||||
.bind(status, error || null, now, name)
|
||||
.first<Provider>();
|
||||
|
||||
if (!result) {
|
||||
throw new RepositoryError(
|
||||
`Provider not found: ${name}`,
|
||||
ErrorCodes.NOT_FOUND
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('[ProvidersRepository] updateSyncStatus failed:', error);
|
||||
|
||||
if (error instanceof RepositoryError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new RepositoryError(
|
||||
`Failed to update sync status for provider: ${name}`,
|
||||
ErrorCodes.DATABASE_ERROR,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all providers with specific sync status
|
||||
*/
|
||||
async findByStatus(status: Provider['sync_status']): Promise<Provider[]> {
|
||||
try {
|
||||
const result = await this.db
|
||||
.prepare('SELECT * FROM providers WHERE sync_status = ?')
|
||||
.bind(status)
|
||||
.all<Provider>();
|
||||
|
||||
return result.results;
|
||||
} catch (error) {
|
||||
console.error('[ProvidersRepository] findByStatus failed:', error);
|
||||
throw new RepositoryError(
|
||||
`Failed to find providers by status: ${status}`,
|
||||
ErrorCodes.DATABASE_ERROR,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a provider
|
||||
*/
|
||||
async upsert(data: ProviderInput): Promise<Provider> {
|
||||
try {
|
||||
const existing = await this.findByName(data.name);
|
||||
|
||||
if (existing) {
|
||||
return await this.update(existing.id, data);
|
||||
}
|
||||
|
||||
return await this.create(data);
|
||||
} catch (error) {
|
||||
console.error('[ProvidersRepository] upsert failed:', error);
|
||||
throw new RepositoryError(
|
||||
`Failed to upsert provider: ${data.name}`,
|
||||
ErrorCodes.DATABASE_ERROR,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user