import { executeAzCommand, CommandResult } from '../lib/cli-executor.js';
import { withCache, CacheKeys } from '../lib/cache.js';
import { logger } from '../lib/logger.js';
export interface ServiceResult<T = unknown> {
success: boolean;
data?: T;
count?: number;
error?: string;
command?: string;
cached?: boolean;
}
export abstract class AzureService {
abstract readonly serviceName: string;
abstract readonly cliPrefix: string;
protected async execute(subCmd: string, options: Record<string, string> = {}): Promise<CommandResult> {
const args = Object.entries(options)
.filter(([_, v]) => v)
.map(([k, v]) => `--${k} "${v}"`)
.join(' ');
const cmd = `az ${this.cliPrefix} ${subCmd}${args ? ' ' + args : ''}`;
logger.debug(`${this.serviceName} execute`, { cmd });
return executeAzCommand(cmd, { enableRetry: true });
}
protected toResult<T>(result: CommandResult, cmd?: string): ServiceResult<T> {
if (!result.success) {
return { success: false, error: result.stderr || 'Command failed', command: cmd };
}
const data = result.parsedOutput as T;
const count = Array.isArray(data) ? data.length : undefined;
return { success: true, data, count, command: cmd };
}
protected async cachedExecute<T>(
cacheKey: string,
operation: () => Promise<ServiceResult<T>>,
bypassCache = false
): Promise<ServiceResult<T>> {
if (bypassCache) return operation();
return withCache(cacheKey, operation);
}
abstract list(resourceGroup?: string): Promise<ServiceResult>;
}