Skip to main content
Glama
by RadonX
trilium-client.js•3.64 kB
import axios from 'axios'; import { logger } from './logger.js'; export class TriliumAPIError extends Error { constructor(message, status, details) { super(message); this.name = 'TriliumAPIError'; this.status = status; this.details = details; } } export class TriliumClient { constructor() { this.baseURL = process.env.TRILIUM_URL || 'http://localhost:8080'; this.authToken = process.env.TRILIUM_AUTH_TOKEN; this.timeout = parseInt(process.env.REQUEST_TIMEOUT, 10) || 30000; if (!this.authToken) { logger.warn('No TRILIUM_AUTH_TOKEN provided - authentication may fail'); } this.client = axios.create({ baseURL: `${this.baseURL}/etapi`, timeout: this.timeout, headers: { 'Content-Type': 'application/json', ...(this.authToken && { 'Authorization': `Bearer ${this.authToken}` }) } }); // Add request/response interceptors for logging and error handling this.client.interceptors.request.use( (config) => { logger.debug(`Making request: ${config.method?.toUpperCase()} ${config.url}`); return config; }, (error) => { logger.error('Request error:', error.message); return Promise.reject(error); } ); this.client.interceptors.response.use( (response) => { logger.debug(`Response: ${response.status} ${response.statusText}`); return response; }, (error) => { const status = error.response?.status; const message = error.response?.data?.message || error.message; const details = error.response?.data; logger.error(`API error: ${status} - ${message}`); if (status === 401) { throw new TriliumAPIError('Authentication failed - check your TRILIUM_AUTH_TOKEN', status, details); } else if (status === 403) { throw new TriliumAPIError('Access forbidden - insufficient permissions', status, details); } else if (status === 404) { throw new TriliumAPIError('Resource not found', status, details); } else if (status >= 500) { throw new TriliumAPIError('TriliumNext server error', status, details); } else { throw new TriliumAPIError(message, status, details); } } ); } async makeRequest(method, endpoint, data = null) { try { const config = { method, url: endpoint, ...(data && { data }) }; const response = await this.client(config); return response.data; } catch (error) { if (error instanceof TriliumAPIError) { throw error; } throw new TriliumAPIError(`Request failed: ${error.message}`, 0, { originalError: error.message }); } } async get(endpoint) { return this.makeRequest('GET', endpoint); } async post(endpoint, data) { return this.makeRequest('POST', endpoint, data); } async put(endpoint, data) { return this.makeRequest('PUT', endpoint, data); } async putRaw(endpoint, content) { try { const config = { method: 'PUT', url: endpoint, data: content, headers: { 'Content-Type': 'text/plain' } }; const response = await this.client(config); return response.data; } catch (error) { if (error instanceof TriliumAPIError) { throw error; } throw new TriliumAPIError(`Request failed: ${error.message}`, 0, { originalError: error.message }); } } async delete(endpoint) { return this.makeRequest('DELETE', endpoint); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RadonX/mcp-trilium'

If you have feedback or need assistance with the MCP directory API, please join our Discord server