feat: agregar página de debug para Metabase
- Crear componente MetabaseCardDisplay para mostrar detalles de queries - Crear componente MetabaseCardsTable para listar todas las queries - Crear página /metabase-debug con vistas de tabla, cards y queries Panorama - Agregar API routes para cards de Metabase (GET, POST, export) - Actualizar metabase.ts para soportar API Key authentication - Agregar configuración de Metabase API Key en nuxt.config.ts - Documentar todos los endpoints disponibles en METABASE_API_ENDPOINTS.md
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const METABASE_URL = config.metabaseUrl || 'http://metabase:3000'
|
||||
const METABASE_API_KEY = config.metabaseApiKey || ''
|
||||
const METABASE_EMAIL = config.metabaseEmail || 'claudeCode0@nucleoriofrio.com'
|
||||
const METABASE_PASSWORD = config.metabasePassword || 'vK^NyZdZDH#p'
|
||||
|
||||
@@ -50,29 +51,37 @@ export async function getMetabaseToken(): Promise<string> {
|
||||
|
||||
/**
|
||||
* Make an authenticated request to Metabase API
|
||||
* Supports both API Key and Session Token authentication
|
||||
*/
|
||||
export async function metabaseFetch<T = any>(
|
||||
endpoint: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<T> {
|
||||
const token = await getMetabaseToken()
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers as Record<string, string>
|
||||
}
|
||||
|
||||
// Prefer API Key if available
|
||||
if (METABASE_API_KEY) {
|
||||
headers['X-API-KEY'] = METABASE_API_KEY
|
||||
} else {
|
||||
const token = await getMetabaseToken()
|
||||
headers['X-Metabase-Session'] = token
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await $fetch<T>(`${METABASE_URL}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
...options.headers,
|
||||
'X-Metabase-Session': token,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
headers
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error: any) {
|
||||
console.error(`[Metabase] Request failed for ${endpoint}:`, error)
|
||||
|
||||
// If token is invalid, clear it and retry once
|
||||
if (error.statusCode === 401) {
|
||||
// If using session token and it's invalid, clear it and retry once
|
||||
if (error.statusCode === 401 && !METABASE_API_KEY) {
|
||||
console.log('[Metabase] Token invalid, clearing and retrying...')
|
||||
sessionToken = null
|
||||
tokenExpiry = 0
|
||||
@@ -126,3 +135,36 @@ export async function queryMetabaseTable(databaseId: number, tableId: number, qu
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cards/questions
|
||||
*/
|
||||
export async function getMetabaseCards(filter?: string) {
|
||||
const endpoint = filter ? `/api/card?f=${filter}` : '/api/card'
|
||||
return metabaseFetch(endpoint)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific card by ID
|
||||
*/
|
||||
export async function getMetabaseCard(cardId: number) {
|
||||
return metabaseFetch(`/api/card/${cardId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a card query with optional parameters
|
||||
*/
|
||||
export async function executeCardQuery(cardId: number, parameters?: any[]) {
|
||||
const body = parameters ? { parameters } : {}
|
||||
return metabaseFetch(`/api/card/${cardId}/query`, {
|
||||
method: 'POST',
|
||||
body
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a card query with cache (GET)
|
||||
*/
|
||||
export async function executeCardQueryCached(cardId: number) {
|
||||
return metabaseFetch(`/api/card/${cardId}/query`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user