@coretext-ai/qa-looker-b5c6d7e8-f9a0-4123-a456-567890123456
Version:
MCP server with looker integration
2,232 lines • 102 kB
JavaScript
import axios from 'axios';
import { Logger } from '../services/logger.js';
export class LookerClient {
constructor(config) {
this.config = config;
// Generate unique session ID for this client instance
this.sessionId = `looker-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
// Initialize logger (fallback to console if not provided)
this.logger = config.logger || new Logger({
logLevel: 'ERROR',
component: 'client',
enableConsole: true,
enableShipping: false,
serverName: 'looker-mcp-server'
});
this.logger.info('CLIENT_INIT', 'Client instance created', {
baseUrl: this.resolveBaseUrl(),
timeout: this.config.timeout || 30000,
hasRateLimit: !!this.config.rateLimit,
configKeys: Object.keys(config)
});
this.httpClient = axios.create({
baseURL: this.resolveBaseUrl(),
timeout: this.config.timeout || 30000,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'User-Agent': 'looker-mcp-server/1.0.0',
...this.getAuthHeaders()
},
});
// Add request interceptor for rate limiting
if (this.config.rateLimit) {
this.setupRateLimit(this.config.rateLimit);
}
// Add request interceptor for logging
this.httpClient.interceptors.request.use((config) => {
this.logger.logRequestStart(config.method?.toUpperCase() || 'GET', `${config.baseURL}${config.url}`, {
hasData: !!config.data,
hasParams: !!(config.params && Object.keys(config.params).length > 0),
headers: Object.keys(config.headers || {})
});
if (config.data) {
this.logger.debug('HTTP_REQUEST_BODY', 'Request body data', {
dataType: typeof config.data,
dataSize: JSON.stringify(config.data).length
});
}
if (config.params && Object.keys(config.params).length > 0) {
this.logger.debug('HTTP_REQUEST_PARAMS', 'Query parameters', {
paramCount: Object.keys(config.params).length,
paramKeys: Object.keys(config.params)
});
}
return config;
}, (error) => {
this.logger.error('HTTP_REQUEST_ERROR', 'Request interceptor error', {
error: error.message,
code: error.code
});
return Promise.reject(error);
});
// Add response interceptor for logging and error handling
this.httpClient.interceptors.response.use((response) => {
this.logger.logRequestSuccess(response.config?.method?.toUpperCase() || 'GET', `${response.config?.baseURL}${response.config?.url}`, response.status, 0, // Duration will be calculated in endpoint methods
{
statusText: response.statusText,
responseSize: JSON.stringify(response.data).length,
headers: Object.keys(response.headers || {})
});
return response;
}, (error) => {
this.logger.logRequestError(error.config?.method?.toUpperCase() || 'GET', `${error.config?.baseURL}${error.config?.url}`, error, 0, // Duration will be calculated in endpoint methods
{
hasResponseData: !!error.response?.data
});
throw error;
});
}
setupRateLimit(requestsPerMinute) {
const interval = 60000 / requestsPerMinute; // ms between requests
let lastRequestTime = 0;
this.logger.info('RATE_LIMIT_SETUP', 'Rate limiting configured', {
requestsPerMinute,
intervalMs: interval
});
this.httpClient.interceptors.request.use(async (config) => {
const now = Date.now();
const timeSinceLastRequest = now - lastRequestTime;
if (timeSinceLastRequest < interval) {
const delayMs = interval - timeSinceLastRequest;
this.logger.logRateLimit('HTTP_REQUEST', delayMs, {
timeSinceLastRequest,
requiredInterval: interval
});
await new Promise(resolve => setTimeout(resolve, delayMs));
}
lastRequestTime = Date.now();
return config;
});
}
resolveBaseUrl() {
let baseUrl = 'https://{instance_name}.looker.com';
// Handle dynamic domain replacement (e.g., YOUR_DOMAIN placeholder)
if (baseUrl.includes('YOUR_DOMAIN')) {
const domainEnvVar = `LOOKER_DOMAIN`;
const domain = process.env[domainEnvVar];
if (!domain) {
throw new Error(`Missing domain configuration. Please set ${domainEnvVar} environment variable.`);
}
baseUrl = baseUrl.replace('YOUR_DOMAIN', domain);
console.error(`[LOOKER] Resolved base URL: ${baseUrl}`);
}
return baseUrl;
}
getAuthHeaders() {
// Bearer/API key authentication
const token = this.config.authToken || this.config['lOOKERCLIENTCREDENTIALS'] || process.env.LOOKER_CLIENT_CREDENTIALS;
if (token) {
this.logger.logAuthEvent('bearer_auth_setup', true, {
authType: 'client_credentials',
tokenPreview: token.substring(0, 8) + '...',
header: 'Authorization'
});
return {
'Authorization': `Bearer ${token}`
};
}
this.logger.warn('AUTH_WARNING', 'No authentication token found', {
authType: 'client_credentials',
warning: 'API calls may be rate limited',
checkedSources: ['config.authToken', 'environment variables']
});
return {};
}
/**
* Initialize the client (for OAuth clients that need initialization)
*/
async initialize() {
this.logger.debug('CLIENT_INITIALIZE', 'No initialization required for this auth type');
}
/**
* Get the session ID for this client instance
*/
getSessionId() {
return this.sessionId;
}
/**
* Make an authenticated request with proper headers
*/
async makeAuthenticatedRequest(config) {
return this.httpClient.request(config);
}
buildPath(template, params) {
let path = template;
for (const [key, value] of Object.entries(params)) {
path = path.replace(`{${key}}`, encodeURIComponent(String(value)));
}
this.logger.debug('PATH_BUILD', 'Built API path from template', {
template,
resultPath: path,
paramCount: Object.keys(params).length,
paramKeys: Object.keys(params)
});
return path;
}
async login(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'login',
method: 'POST',
path: '/api/4.0/login',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/login'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.client_id) {
throw new Error(`Missing required parameter: client_id`);
}
if (!params.client_secret) {
throw new Error(`Missing required parameter: client_secret`);
}
const path = this.buildPath('/api/4.0/login', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'login',
method: 'POST',
path: '/api/4.0/login',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'login',
method: 'POST',
path: '/api/4.0/login',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute login: ${error instanceof Error ? error.message : String(error)}`);
}
}
async logout(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'logout',
method: 'DELETE',
path: '/api/4.0/logout',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/logout'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
const path = this.buildPath('/api/4.0/logout', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.delete(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'logout',
method: 'DELETE',
path: '/api/4.0/logout',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'logout',
method: 'DELETE',
path: '/api/4.0/logout',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute logout: ${error instanceof Error ? error.message : String(error)}`);
}
}
async me(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'me',
method: 'GET',
path: '/api/4.0/user',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/user'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/user', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'me',
method: 'GET',
path: '/api/4.0/user',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'me',
method: 'GET',
path: '/api/4.0/user',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute me: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listUsers(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_users',
method: 'GET',
path: '/api/4.0/users',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/users'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/users', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_users',
method: 'GET',
path: '/api/4.0/users',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_users',
method: 'GET',
path: '/api/4.0/users',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_users: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createUser(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_user',
method: 'POST',
path: '/api/4.0/users',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/users'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.first_name) {
throw new Error(`Missing required parameter: first_name`);
}
if (!params.last_name) {
throw new Error(`Missing required parameter: last_name`);
}
if (!params.email) {
throw new Error(`Missing required parameter: email`);
}
const path = this.buildPath('/api/4.0/users', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_user',
method: 'POST',
path: '/api/4.0/users',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_user',
method: 'POST',
path: '/api/4.0/users',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_user: ${error instanceof Error ? error.message : String(error)}`);
}
}
async updateUser(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'update_user',
method: 'PATCH',
path: '/api/4.0/users/{user_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/users/{user_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.user_id) {
throw new Error(`Missing required parameter: user_id`);
}
const path = this.buildPath('/api/4.0/users/{user_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'update_user',
method: 'PATCH',
path: '/api/4.0/users/{user_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'update_user',
method: 'PATCH',
path: '/api/4.0/users/{user_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute update_user: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listDashboards(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_dashboards',
method: 'GET',
path: '/api/4.0/dashboards',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/dashboards', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_dashboards',
method: 'GET',
path: '/api/4.0/dashboards',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_dashboards',
method: 'GET',
path: '/api/4.0/dashboards',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_dashboards: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getDashboard(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_dashboard',
method: 'GET',
path: '/api/4.0/dashboards/{dashboard_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards/{dashboard_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.dashboard_id) {
throw new Error(`Missing required parameter: dashboard_id`);
}
const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_dashboard',
method: 'GET',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_dashboard',
method: 'GET',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_dashboard: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createDashboard(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_dashboard',
method: 'POST',
path: '/api/4.0/dashboards',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.title) {
throw new Error(`Missing required parameter: title`);
}
const path = this.buildPath('/api/4.0/dashboards', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_dashboard',
method: 'POST',
path: '/api/4.0/dashboards',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_dashboard',
method: 'POST',
path: '/api/4.0/dashboards',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_dashboard: ${error instanceof Error ? error.message : String(error)}`);
}
}
async updateDashboard(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'update_dashboard',
method: 'PATCH',
path: '/api/4.0/dashboards/{dashboard_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards/{dashboard_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.dashboard_id) {
throw new Error(`Missing required parameter: dashboard_id`);
}
const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'update_dashboard',
method: 'PATCH',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'update_dashboard',
method: 'PATCH',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute update_dashboard: ${error instanceof Error ? error.message : String(error)}`);
}
}
async deleteDashboard(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'delete_dashboard',
method: 'DELETE',
path: '/api/4.0/dashboards/{dashboard_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards/{dashboard_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.dashboard_id) {
throw new Error(`Missing required parameter: dashboard_id`);
}
const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.delete(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'delete_dashboard',
method: 'DELETE',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'delete_dashboard',
method: 'DELETE',
path: '/api/4.0/dashboards/{dashboard_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute delete_dashboard: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listLooks(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_looks',
method: 'GET',
path: '/api/4.0/looks',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/looks'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/looks', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_looks',
method: 'GET',
path: '/api/4.0/looks',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_looks',
method: 'GET',
path: '/api/4.0/looks',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_looks: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getLook(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/looks/{look_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.look_id) {
throw new Error(`Missing required parameter: look_id`);
}
const path = this.buildPath('/api/4.0/looks/{look_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_look: ${error instanceof Error ? error.message : String(error)}`);
}
}
async runLook(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'run_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}/run/{result_format}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/looks/{look_id}/run/{result_format}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.look_id) {
throw new Error(`Missing required parameter: look_id`);
}
if (!params.result_format) {
throw new Error(`Missing required parameter: result_format`);
}
const path = this.buildPath('/api/4.0/looks/{look_id}/run/{result_format}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'run_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}/run/{result_format}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'run_look',
method: 'GET',
path: '/api/4.0/looks/{look_id}/run/{result_format}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute run_look: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createLook(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_look',
method: 'POST',
path: '/api/4.0/looks',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/looks'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.title) {
throw new Error(`Missing required parameter: title`);
}
if (!params.query_id) {
throw new Error(`Missing required parameter: query_id`);
}
const path = this.buildPath('/api/4.0/looks', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_look',
method: 'POST',
path: '/api/4.0/looks',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_look',
method: 'POST',
path: '/api/4.0/looks',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_look: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listQueries(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_queries',
method: 'GET',
path: '/api/4.0/queries',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/queries'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/queries', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_queries',
method: 'GET',
path: '/api/4.0/queries',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_queries',
method: 'GET',
path: '/api/4.0/queries',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_queries: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getQuery(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/queries/{query_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.query_id) {
throw new Error(`Missing required parameter: query_id`);
}
const path = this.buildPath('/api/4.0/queries/{query_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_query: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createQuery(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_query',
method: 'POST',
path: '/api/4.0/queries',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/queries'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.model) {
throw new Error(`Missing required parameter: model`);
}
if (!params.explore) {
throw new Error(`Missing required parameter: explore`);
}
const path = this.buildPath('/api/4.0/queries', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_query',
method: 'POST',
path: '/api/4.0/queries',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_query',
method: 'POST',
path: '/api/4.0/queries',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_query: ${error instanceof Error ? error.message : String(error)}`);
}
}
async runQuery(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'run_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}/run/{result_format}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/queries/{query_id}/run/{result_format}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.query_id) {
throw new Error(`Missing required parameter: query_id`);
}
if (!params.result_format) {
throw new Error(`Missing required parameter: result_format`);
}
const path = this.buildPath('/api/4.0/queries/{query_id}/run/{result_format}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'run_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}/run/{result_format}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'run_query',
method: 'GET',
path: '/api/4.0/queries/{query_id}/run/{result_format}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute run_query: ${error instanceof Error ? error.message : String(error)}`);
}
}
async runInlineQuery(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'run_inline_query',
method: 'POST',
path: '/api/4.0/queries/run/{result_format}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/queries/run/{result_format}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.result_format) {
throw new Error(`Missing required parameter: result_format`);
}
if (!params.model) {
throw new Error(`Missing required parameter: model`);
}
if (!params.explore) {
throw new Error(`Missing required parameter: explore`);
}
const path = this.buildPath('/api/4.0/queries/run/{result_format}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'run_inline_query',
method: 'POST',
path: '/api/4.0/queries/run/{result_format}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'run_inline_query',
method: 'POST',
path: '/api/4.0/queries/run/{result_format}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute run_inline_query: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listSpaces(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_spaces',
method: 'GET',
path: '/api/4.0/spaces',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/spaces'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/spaces', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_spaces',
method: 'GET',
path: '/api/4.0/spaces',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_spaces',
method: 'GET',
path: '/api/4.0/spaces',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_spaces: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getSpace(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_space',
method: 'GET',
path: '/api/4.0/spaces/{space_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/spaces/{space_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.space_id) {
throw new Error(`Missing required parameter: space_id`);
}
const path = this.buildPath('/api/4.0/spaces/{space_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_space',
method: 'GET',
path: '/api/4.0/spaces/{space_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_space',
method: 'GET',
path: '/api/4.0/spaces/{space_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_space: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createSpace(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_space',
method: 'POST',
path: '/api/4.0/spaces',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/spaces'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.name) {
throw new Error(`Missing required parameter: name`);
}
const path = this.buildPath('/api/4.0/spaces', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_space',
method: 'POST',
path: '/api/4.0/spaces',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_space',
method: 'POST',
path: '/api/4.0/spaces',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_space: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listFolders(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_folders',
method: 'GET',
path: '/api/4.0/folders',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/folders'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/folders', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_folders',
method: 'GET',
path: '/api/4.0/folders',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_folders',
method: 'GET',
path: '/api/4.0/folders',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_folders: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getFolder(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_folder',
method: 'GET',
path: '/api/4.0/folders/{folder_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/folders/{folder_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.folder_id) {
throw new Error(`Missing required parameter: folder_id`);
}
const path = this.buildPath('/api/4.0/folders/{folder_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_folder',
method: 'GET',
path: '/api/4.0/folders/{folder_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_folder',
method: 'GET',
path: '/api/4.0/folders/{folder_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_folder: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createFolder(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_folder',
method: 'POST',
path: '/api/4.0/folders',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/folders'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.name) {
throw new Error(`Missing required parameter: name`);
}
const path = this.buildPath('/api/4.0/folders', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_folder',
method: 'POST',
path: '/api/4.0/folders',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_folder',
method: 'POST',
path: '/api/4.0/folders',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_folder: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createQueryTask(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'create_query_task',
method: 'POST',
path: '/api/4.0/query_tasks',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/query_tasks'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.result_format) {
throw new Error(`Missing required parameter: result_format`);
}
const path = this.buildPath('/api/4.0/query_tasks', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.post(path, remainingParams);
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'create_query_task',
method: 'POST',
path: '/api/4.0/query_tasks',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'create_query_task',
method: 'POST',
path: '/api/4.0/query_tasks',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute create_query_task: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getQueryTask(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_query_task',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/query_tasks/{query_task_id}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.query_task_id) {
throw new Error(`Missing required parameter: query_task_id`);
}
const path = this.buildPath('/api/4.0/query_tasks/{query_task_id}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_query_task',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_query_task',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_query_task: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getQueryTaskResults(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_query_task_results',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}/results',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/query_tasks/{query_task_id}/results'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.query_task_id) {
throw new Error(`Missing required parameter: query_task_id`);
}
const path = this.buildPath('/api/4.0/query_tasks/{query_task_id}/results', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_query_task_results',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}/results',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_query_task_results',
method: 'GET',
path: '/api/4.0/query_tasks/{query_task_id}/results',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_query_task_results: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listModels(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_models',
method: 'GET',
path: '/api/4.0/lookml_models',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/lookml_models'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/lookml_models', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_models',
method: 'GET',
path: '/api/4.0/lookml_models',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_models',
method: 'GET',
path: '/api/4.0/lookml_models',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_models: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getModel(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_model',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/lookml_models/{model_name}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.model_name) {
throw new Error(`Missing required parameter: model_name`);
}
const path = this.buildPath('/api/4.0/lookml_models/{model_name}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_model',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_model',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_model: ${error instanceof Error ? error.message : String(error)}`);
}
}
async listExplores(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'list_explores',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/lookml_models/{model_name}/explores'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.model_name) {
throw new Error(`Missing required parameter: model_name`);
}
const path = this.buildPath('/api/4.0/lookml_models/{model_name}/explores', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'list_explores',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'list_explores',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute list_explores: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getExplore(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'get_explore',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/lookml_models/{model_name}/explores/{explore_name}'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.model_name) {
throw new Error(`Missing required parameter: model_name`);
}
if (!params.explore_name) {
throw new Error(`Missing required parameter: explore_name`);
}
const path = this.buildPath('/api/4.0/lookml_models/{model_name}/explores/{explore_name}', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'get_explore',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'get_explore',
method: 'GET',
path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute get_explore: ${error instanceof Error ? error.message : String(error)}`);
}
}
async searchDashboards(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'search_dashboards',
method: 'GET',
path: '/api/4.0/dashboards/search',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/dashboards/search'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
const path = this.buildPath('/api/4.0/dashboards/search', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'search_dashboards',
method: 'GET',
path: '/api/4.0/dashboards/search',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'search_dashboards',
method: 'GET',
path: '/api/4.0/dashboards/search',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute search_dashboards: ${error instanceof Error ? error.message : String(error)}`);
}
}
async renderTaskResults(params) {
const startTime = Date.now();
this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
endpoint: 'render_task_results',
method: 'GET',
path: '/api/4.0/render_tasks/{render_task_id}/results',
paramCount: Object.keys(params || {}).length,
paramKeys: Object.keys(params || {})
});
try {
// Extract path parameters from URL template and separate from query/body params
const pathParamNames = '/api/4.0/render_tasks/{render_task_id}/results'.match(/{([^}]+)}/g) || [];
const pathParams = {};
const remainingParams = { ...params };
// Extract path parameters
pathParamNames.forEach(paramTemplate => {
const paramName = paramTemplate.slice(1, -1); // Remove { }
if (params[paramName] !== undefined) {
pathParams[paramName] = params[paramName];
delete remainingParams[paramName];
}
});
// Validate required parameters
if (!params.render_task_id) {
throw new Error(`Missing required parameter: render_task_id`);
}
const path = this.buildPath('/api/4.0/render_tasks/{render_task_id}/results', pathParams);
// Use standard HTTP client for other auth types
const response = await this.httpClient.get(path, { params: remainingParams });
const duration = Date.now() - startTime;
this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
endpoint: 'render_task_results',
method: 'GET',
path: '/api/4.0/render_tasks/{render_task_id}/results',
duration_ms: duration,
responseDataSize: JSON.stringify(response.data).length
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
endpoint: 'render_task_results',
method: 'GET',
path: '/api/4.0/render_tasks/{render_task_id}/results',
duration_ms: duration,
error: error instanceof Error ? error.message : String(error),
errorType: error instanceof Error ? error.constructor.name : 'unknown'
});
throw new Error(`Failed to execute render_task_results: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
//# sourceMappingURL=looker-client.js.map