UNPKG

snake-query

Version:
109 lines (91 loc) 3.03 kB
const SchemaBuilder = require('./schema-builder'); class SnakeQuery { constructor(apiKey) { if (!apiKey) { throw new Error('API key is required'); } this.apiKey = apiKey; this.baseUrl = 'https://app.snakequery.com/api/query'; } async query(options) { if (!options) { throw new Error('Query options are required'); } if (!options.query) { throw new Error('Query is required'); } if (!options.data && !options.fetchUrl) { throw new Error('Either data or fetchUrl must be provided'); } if (options.data && options.fetchUrl) { throw new Error('Cannot provide both data and fetchUrl, choose one'); } const requestBody = { query: options.query, ...(options.data && { data: options.data }), ...(options.fetchUrl && { fetchUrl: options.fetchUrl }), ...(options.responseSchema && { responseSchema: options.responseSchema }), ...(options.debug !== undefined && { debug: options.debug }) }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 60 * 1000 * 10); const response = await fetch(this.baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify(requestBody), signal: controller.signal, }); clearTimeout(timeoutId); const contentType = response.headers.get('content-type'); let result; if (contentType && contentType.includes('application/json')) { result = await response.json(); } else { const textResult = await response.text(); result = { message: `Server returned non-JSON response: ${response.statusText}`, statusCode: response.status, body: textResult.substring(0, 200) + (textResult.length > 200 ? '...' : '') }; } if (!response.ok) { const error = new Error(result.message || `HTTP ${response.status}: ${response.statusText}`); error.status = response.status; error.response = result; throw error; } if(result?.code !== 200) { throw new Error(result) } return result?.data; } catch (error) { if (error.name === 'AbortError') { throw new Error('Request timeout: Snake Query API took too long to respond (10 minute limit)'); } if (error.name === 'TypeError' && error.message.includes('fetch')) { throw new Error('Network error: Unable to connect to Snake Query API'); } throw error; } } async queryWithData(query, data, options = {}) { return this.query({ query, data, ...options }); } async queryWithUrl(query, fetchUrl, options = {}) { return this.query({ query, fetchUrl, ...options }); } } SnakeQuery.SchemaBuilder = SchemaBuilder; module.exports = SnakeQuery;