Skip to main content

Overview

File: src/tools/ProductsTool.ts Six tools demonstrating complete product management with the Products API.

Tools Included

Search

Find products by query

Get All

List with pagination

Filter

Query by attributes

Create

Add new products

Update

Modify existing

Delete

Remove products

Example Tools

SearchProductsTool

import { LuaTool, Products } from 'lua-cli';
import { z } from 'zod';

export class SearchProductsTool implements LuaTool {
  name = "search_products";
  description = "Search products by name or description";
  
  inputSchema = z.object({
    query: z.string().describe("Search query")
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const results = await Products.search(input.query);
    
    return {
      products: results.data.map(p => ({
        id: p.id,
        name: p.name,
        price: `$${p.price.toFixed(2)}`,
        inStock: p.inStock
      })),
      count: results.data.length
    };
  }
}

CreateProductTool

export class CreateProductTool implements LuaTool {
  name = "create_product";
  description = "Add a new product to the catalog";
  
  inputSchema = z.object({
    name: z.string(),
    price: z.number().positive(),
    category: z.string().optional(),
    sku: z.string().optional(),
    description: z.string().optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const result = await Products.create({
      ...input,
      id: generateId(),  // Generate unique ID
      inStock: true
    });
    
    return {
      success: true,
      productId: result.product.id,
      message: `Product "${input.name}" created`
    };
  }
}

UpdateProductTool

export class UpdateProductTool implements LuaTool {
  name = "update_product";
  description = "Update product information";
  
  inputSchema = z.object({
    id: z.string(),
    name: z.string().optional(),
    price: z.number().positive().optional(),
    inStock: z.boolean().optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const { id, ...updates } = input;
    
    await Products.update(updates, id);
    
    return {
      success: true,
      message: "Product updated successfully"
    };
  }
}

BrowseProductsTool (with Filters)

export class BrowseProductsTool implements LuaTool {
  name = "browse_products";
  description = "Browse and filter products by category, price, or availability";
  
  inputSchema = z.object({
    category: z.string().optional().describe("Product category"),
    minPrice: z.number().optional().describe("Minimum price"),
    maxPrice: z.number().optional().describe("Maximum price"),
    inStockOnly: z.boolean().optional().describe("Only show in-stock items"),
    page: z.number().optional().default(1)
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Build filter from input
    const filter: Record<string, any> = {};
    
    if (input.category) {
      filter.category = input.category;
    }
    
    if (input.minPrice !== undefined || input.maxPrice !== undefined) {
      filter.price = {};
      if (input.minPrice !== undefined) filter.price.$gte = input.minPrice;
      if (input.maxPrice !== undefined) filter.price.$lte = input.maxPrice;
    }
    
    if (input.inStockOnly) {
      filter.inStock = true;
    }
    
    const results = await Products.get({
      page: input.page,
      limit: 10,
      filter
    });
    
    return {
      products: results.data.map(p => ({
        id: p.id,
        name: p.name,
        price: `$${p.price.toFixed(2)}`,
        category: p.category,
        inStock: p.inStock
      })),
      pagination: {
        page: results.pagination.currentPage,
        totalPages: results.pagination.totalPages,
        totalProducts: results.pagination.totalCount
      }
    };
  }
}

Use Cases

E-commerce Catalog

// Browse products with pagination
const products = await Products.get({ page: 1, limit: 20 });

// Search for specific items (semantic search)
const laptops = await Products.search('laptop');

// Filter by category
const electronics = await Products.get({
  filter: { category: 'Electronics' }
});

// Get product details
const product = await Products.getById(laptops.data[0].id);

Filtering Products

// Filter by price range
const affordable = await Products.get({
  filter: {
    price: { $gte: 50, $lte: 200 }
  }
});

// Filter by category and stock status
const availablePhones = await Products.get({
  filter: {
    category: 'Phones',
    inStock: true
  }
});

// Filter by nested fields
const appleProducts = await Products.get({
  filter: {
    'metadata.brand': 'Apple'
  }
});

// Multiple categories
const gadgets = await Products.get({
  filter: {
    category: { $in: ['Phones', 'Tablets', 'Watches'] }
  }
});

Inventory Management

// Update stock status
await Products.update({ inStock: false }, productId);

// Update price
await Products.update({ price: 899.99 }, productId);

// Get out-of-stock products
const outOfStock = await Products.get({
  filter: { inStock: false }
});

// Bulk update by category
const electronics = await Products.get({
  limit: 100,
  filter: { category: 'Electronics' }
});

for (const product of electronics.data) {
  await Products.update({ onSale: true }, product.id);
}

Admin Dashboard

// Get all products
const all = await Products.get({ page: 1, limit: 1000 });

// Statistics
const totalValue = all.data.reduce((sum, p) => sum + p.price, 0);
const inStock = all.data.filter(p => p.inStock).length;
const categories = [...new Set(all.data.map(p => p.category))];

// Get low-stock items (custom field)
const lowStock = await Products.get({
  filter: {
    stockCount: { $lte: 10 },
    inStock: true
  }
});

Using save() Method (New!)

// Get product and modify multiple fields
const product = await Products.getById('product_123');

// Modify properties directly
product.price = 899.99;
product.inStock = true;
product.category = 'Electronics - Sale';
product.description = 'Updated description';

// Save all changes at once
await product.save();

// Much cleaner than calling update()!

Practical Example: Bulk Price Update

export class BulkDiscountTool implements LuaTool {
  name = "apply_discount";
  description = "Apply discount to products in a category";
  
  inputSchema = z.object({
    category: z.string(),
    discountPercent: z.number()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Use filter to get only products in the target category
    const products = await Products.get({
      limit: 1000,
      filter: { category: input.category }
    });
    
    let updatedCount = 0;
    for (const product of products.data) {
      // Modify and save
      product.price = product.price * (1 - input.discountPercent / 100);
      await product.save();
      updatedCount++;
    }
    
    return { 
      message: `Discount applied to ${updatedCount} ${input.category} products` 
    };
  }
}

What You’ll Learn

CRUD Operations

Create, Read, Update, Delete

Pagination

Handle large datasets

Search

Semantic search with vector embeddings

Filtering

MongoDB-style queries for structured data

Next Steps