import { AzureService, ServiceResult } from './base-service.js';
import { CacheKeys } from '../lib/cache.js';
import { executeAzCommand } from '../lib/cli-executor.js';
interface KustoCluster {
name: string;
resourceGroup: string;
location: string;
state: string;
uri: string;
}
interface KustoDatabase {
name: string;
softDeletePeriod: string;
hotCachePeriod: string;
}
interface KustoTable {
name: string;
folder: string;
}
export class KustoService extends AzureService {
readonly serviceName = 'Kusto';
readonly cliPrefix = 'kusto';
async list(resourceGroup?: string): Promise<ServiceResult<KustoCluster[]>> {
const cacheKey = CacheKeys.service('kusto', 'clusters', resourceGroup ?? '');
return this.cachedExecute(cacheKey, async () => {
const opts: Record<string, string> = {};
if (resourceGroup) opts['resource-group'] = resourceGroup;
const result = await this.execute('cluster list', opts);
return this.toResult<KustoCluster[]>(result);
});
}
async listDatabases(clusterName: string, resourceGroup: string): Promise<ServiceResult<KustoDatabase[]>> {
const cacheKey = CacheKeys.service('kusto', 'databases', clusterName);
return this.cachedExecute(cacheKey, async () => {
const result = await this.execute('database list', {
'cluster-name': clusterName,
'resource-group': resourceGroup
});
return this.toResult<KustoDatabase[]>(result);
});
}
async listTables(clusterName: string, resourceGroup: string, databaseName: string): Promise<ServiceResult> {
const cacheKey = CacheKeys.service('kusto', 'tables', clusterName, databaseName);
return this.cachedExecute(cacheKey, async () => {
const query = '.show tables';
return this.runKql(clusterName, resourceGroup, databaseName, query);
});
}
async getTableSchema(clusterName: string, resourceGroup: string, databaseName: string, tableName: string): Promise<ServiceResult> {
const query = `.show table ${tableName} schema as json`;
return this.runKql(clusterName, resourceGroup, databaseName, query);
}
async sampleTable(clusterName: string, resourceGroup: string, databaseName: string, tableName: string, count = 10): Promise<ServiceResult> {
const query = `${tableName} | take ${count}`;
return this.runKql(clusterName, resourceGroup, databaseName, query);
}
async runKql(clusterName: string, resourceGroup: string, databaseName: string, query: string): Promise<ServiceResult> {
const escapedQuery = query.replace(/"/g, '\\"');
const cmd = `az kusto query --cluster-name "${clusterName}" --resource-group "${resourceGroup}" --database-name "${databaseName}" --query "${escapedQuery}"`;
const result = await executeAzCommand(cmd, { enableRetry: true });
return this.toResult(result, cmd);
}
}