Skip to main content

πŸš€ Quick Start

Installation

npm install snake-query

Basic Usage

const SnakeQuery = require('snake-query');
const { SchemaBuilder } = SnakeQuery;

// Initialize client with your API key
const client = new SnakeQuery('your-api-key-here');

// Query with structured response
const result = await client.query({
  query: 'Find products under $100',
  fetchUrl: 'https://api.example.com/products',
  responseSchema: SchemaBuilder.create()
    .array(
      SchemaBuilder.create()
        .object()
        .addStringProperty('name')
        .addNumberProperty('price', { minimum: 0 })
        .required(['name', 'price'])
        .build()
    )
    .build()
});

console.log(result.response); // Structured data array
console.log(result.usageCount); // Token usage info

🎯 What is SnakeQuery?

SnakeQuery transforms natural language into structured data queries using AI. Instead of writing complex filtering, mapping, and aggregation logic, simply describe what you want in plain language. Example:
// Instead of this:
const result = data
  .filter(item => item.price < 100 && item.category === 'electronics')
  .map(item => ({ name: item.title, price: item.price }))
  .sort((a, b) => a.price - b.price);

// Write this:
const result = await client.query({
  query: 'Find electronics under $100, show name and price, sort by price',
  data: products
});

πŸ” Authentication

Get your API key from the SnakeQuery Dashboard and initialize the client:
const client = new SnakeQuery('1234567890abcdef...');
export SNAKE_QUERY_API_KEY="1234567890abcdef..."
require('dotenv').config();
const client = new SnakeQuery(process.env.SNAKE_QUERY_API_KEY);

πŸ“š API Reference

SnakeQuery Class

Constructor

new SnakeQuery(apiKey: string)

Methods

query(options: QueryOptions): Promise<SnakeQueryResponse>
Main method for all query operations. Parameters:
interface QueryOptions {
  query: string;                    // Natural language query
  data?: any;                      // Direct data to query (optional)
  fetchUrl?: string;               // URL to fetch data from (optional)
  responseSchema?: Schema;         // Response structure schema (optional)
}
Response:
interface SnakeQueryResponse<T = any> {
  usageCount: UsageCount;         // Token usage information
  response: T;                    // Query results
}

interface UsageCount {
  inputTokens: number;
  outputTokens: number;
  totalTokens: number;
}

πŸ—οΈ Schema Building

SchemaBuilder Class

Create structured response schemas using fluent API:

Basic Types

const { SchemaBuilder } = SnakeQuery;

// String field
SchemaBuilder.create()
  .string({ minLength: 1, maxLength: 100 })
  .build();

// Number field
SchemaBuilder.create()
  .number({ minimum: 0, maximum: 1000 })
  .build();

// Boolean field
SchemaBuilder.create()
  .boolean()
  .build();

Objects

const userSchema = SchemaBuilder.create()
  .object()
  .addStringProperty('name')
  .addNumberProperty('age', { minimum: 0 })
  .addStringProperty('email')
  .required(['name', 'age'])
  .build();

Arrays

const usersArraySchema = SchemaBuilder.create()
  .array(userSchema)
  .build();

// Or inline
const productsSchema = SchemaBuilder.create()
  .array(
    SchemaBuilder.create()
      .object()
      .addStringProperty('title')
      .addNumberProperty('price', { minimum: 0 })
      .required(['title', 'price'])
      .build()
  )
  .build();

Nested Objects

const orderSchema = SchemaBuilder.create()
  .object()
  .addStringProperty('orderId')
  .addObjectProperty('customer', {
    name: { type: 'string' },
    email: { type: 'string' }
  })
  .addArrayProperty('items', {
    type: 'object',
    properties: {
      product: { type: 'string' },
      quantity: { type: 'number', minimum: 1 },
      price: { type: 'number', minimum: 0 }
    }
  })
  .required(['orderId', 'customer', 'items'])
  .build();

πŸ’» Examples

Your First Query

const SnakeQuery = require('snake-query');

async function firstQuery() {
  // Initialize client
  const client = new SnakeQuery('your-api-key-here');
  
  // Sample data
  const products = [
    { name: 'iPhone 14', price: 999, category: 'electronics' },
    { name: 'Nike Shoes', price: 129, category: 'fashion' },
    { name: 'Coffee Mug', price: 19, category: 'home' }
  ];
  
  try {
    const result = await client.query({
      query: 'Find products under $200',
      data: products
    });
    
    console.log('Results:', result.response);
    console.log('Tokens used:', result.usageCount.totalTokens);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

firstQuery();

Query Direct Data

const products = [
  { name: 'iPhone', price: 999, category: 'electronics' },
  { name: 'Shoes', price: 129, category: 'fashion' },
  { name: 'Book', price: 19, category: 'books' }
];

const result = await client.query({
  query: 'Find products under $500 and group by category',
  data: products,
  responseSchema: SchemaBuilder.create()
    .array(
      SchemaBuilder.create()
        .object()
        .addStringProperty('category')
        .addArrayProperty('products', {
          type: 'object',
          properties: {
            name: { type: 'string' },
            price: { type: 'number' }
          }
        })
        .required(['category', 'products'])
        .build()
    )
    .build()
});

Query External API

const result = await client.query({
  query: 'Show me the top 5 most expensive products with their details',
  fetchUrl: 'https://api.store.com/products',
  responseSchema: SchemaBuilder.create()
    .array(
      SchemaBuilder.create()
        .object()
        .addStringProperty('productName')
        .addNumberProperty('price', { minimum: 0 })
        .addStringProperty('description')
        .addStringProperty('category')
        .required(['productName', 'price'])
        .build()
    )
    .build()
});

Structured Query with Schema

const SnakeQuery = require('snake-query');
const { SchemaBuilder } = SnakeQuery;

async function structuredQuery() {
  const client = new SnakeQuery('your-api-key-here');
  
  const products = [
    { name: 'MacBook Pro', price: 2399, category: 'electronics', rating: 4.8 },
    { name: 'iPad Air', price: 599, category: 'electronics', rating: 4.5 },
    { name: 'AirPods', price: 179, category: 'electronics', rating: 4.3 }
  ];
  
  // Define response structure
  const productSchema = SchemaBuilder.create()
    .array(
      SchemaBuilder.create()
        .object()
        .addStringProperty('productName')
        .addNumberProperty('price', { minimum: 0 })
        .addNumberProperty('rating', { minimum: 0, maximum: 5 })
        .required(['productName', 'price'])
        .build()
    )
    .build();
  
  try {
    const result = await client.query({
      query: 'Show all products with their names, prices, and ratings',
      data: products,
      responseSchema: productSchema
    });
    
    // Result is guaranteed to match schema
    console.log('Structured results:', result.response);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

structuredQuery();

Complex Analytics

const result = await client.query({
  query: 'Calculate average order value by month and show trends',
  fetchUrl: 'https://api.store.com/orders',
  responseSchema: SchemaBuilder.create()
    .object()
    .addArrayProperty('monthlyStats', {
      type: 'object',
      properties: {
        month: { type: 'string' },
        averageOrderValue: { type: 'number', minimum: 0 },
        totalOrders: { type: 'number', minimum: 0 },
        revenue: { type: 'number', minimum: 0 }
      }
    })
    .addObjectProperty('trends', {
      direction: { type: 'string' },
      percentageChange: { type: 'number' },
      insight: { type: 'string' }
    })
    .required(['monthlyStats'])
    .build()
});

🎯 Common Use Cases

1. Data Filtering and Analysis

const salesData = [
  { date: '2024-01-01', amount: 1500, rep: 'John' },
  { date: '2024-01-02', amount: 2200, rep: 'Jane' },
  { date: '2024-01-03', amount: 800, rep: 'John' }
];

const result = await client.query({
  query: 'Show total sales by sales rep, sorted by amount',
  data: salesData
});

2. API Data Processing

const result = await client.query({
  query: 'Find the top 5 most expensive products with their categories',
  fetchUrl: 'https://api.store.com/products',
  responseSchema: topProductsSchema
});

3. Complex Aggregations

const result = await client.query({
  query: 'Calculate monthly revenue trends and identify best performing month',
  fetchUrl: 'https://api.company.com/orders',
  responseSchema: revenueAnalysisSchema
});

⚠️ Error Handling

Common Errors

try {
  const result = await client.query({
    query: 'Analyze sales data',
    fetchUrl: 'https://api.example.com/sales'
  });
} catch (error) {
  switch (error.status) {
    case 401:
      console.error('Invalid API key');
      break;
    case 402:
      console.error('Insufficient credits');
      break;
    case 500:
      console.error('Server error:', error.message);
      break;
    case 504:
      console.error('Request timeout - try a simpler query');
      break;
    default:
      console.error('Unknown error:', error.message);
  }
}

Network Errors

try {
  const result = await client.query(options);
} catch (error) {
  if (error.message.includes('Network error')) {
    console.error('Check your internet connection');
  } else if (error.message.includes('timeout')) {
    console.error('Query took too long - try optimizing your request');
  }
}

✨ Best Practices

1. Always Use Schemas for Production

// ❌ Don't rely on free-form responses
const result = await client.query({
  query: 'Get user data',
  data: users
});

// βœ… Use structured schemas
const result = await client.query({
  query: 'Get user data',
  data: users,
  responseSchema: userSchema
});

2. Environment Variables for API Keys

// ❌ Don't hardcode API keys
const client = new SnakeQuery('1234567890abcdef...');

// βœ… Use environment variables
const client = new SnakeQuery(process.env.SNAKE_QUERY_API_KEY);

3. Handle Errors Gracefully

// βœ… Always wrap in try-catch
try {
  const result = await client.query(options);
  return result.response;
} catch (error) {
  console.error('Query failed:', error.message);
  return null; // or default value
}

4. Optimize Queries for Performance

// βœ… Be specific in your queries
const result = await client.query({
  query: 'Find the 5 most recent orders with status "completed"',
  fetchUrl: url,
  responseSchema: schema
});

// ❌ Avoid overly broad queries
const result = await client.query({
  query: 'Give me everything about all orders',
  fetchUrl: url
});

5. Use Appropriate Data Sources

// βœ… For small datasets, use direct data
const result = await client.query({
  query: 'Find users by department',
  data: smallUserList,
  responseSchema: schema
});

// βœ… For large datasets, use URL endpoints
const result = await client.query({
  query: 'Analyze sales trends',
  fetchUrl: 'https://api.company.com/sales/big-data',
  responseSchema: schema
});

⚑ Performance Tips

  1. Use specific queries: β€œFind top 10 products” vs β€œShow all products”
  2. Define schemas: Structured responses are faster and more reliable
  3. Batch related queries: Combine multiple questions into one query
  4. Cache results: Store frequently used query results

🚨 Common Pitfalls

  1. Missing API key: Always check your API key is set correctly
  2. No error handling: Always wrap queries in try-catch blocks
  3. Overly complex queries: Break down complex requests into simpler ones
  4. Ignoring schemas: Use schemas for consistent, type-safe responses

πŸ“Š Response Format

All successful queries return:
{
  usageCount: {
    inputTokens: 150,
    outputTokens: 75,
    totalTokens: 225
  },
  response: [
    // Your structured data here
    {
      "productName": "iPhone 14",
      "price": 999,
      "category": "Electronics"
    }
  ]
}

πŸŽ‰ Next Steps

πŸ”— Additional Resources

πŸ“ License

MIT License - see LICENSE file for details.
⌘I