> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Products Tools Example

> Complete CRUD operations for product catalog

## Overview

**File**: `src/tools/ProductsTool.ts`

Six tools demonstrating complete product management with the Products API.

## Tools Included

<CardGroup cols={3}>
  <Card title="Search" icon="magnifying-glass">
    Find products by query
  </Card>

  <Card title="Get All" icon="list">
    List with pagination
  </Card>

  <Card title="Filter" icon="filter">
    Query by attributes
  </Card>

  <Card title="Create" icon="plus">
    Add new products
  </Card>

  <Card title="Update" icon="pen">
    Modify existing
  </Card>

  <Card title="Delete" icon="trash">
    Remove products
  </Card>
</CardGroup>

## Example Tools

### SearchProductsTool

```typescript theme={null}
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.map(p => ({
        id: p.id,
        name: p.name,
        price: `$${p.price.toFixed(2)}`,
        inStock: p.inStock
      })),
      count: results.length
    };
  }
}
```

### CreateProductTool

```typescript theme={null}
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

```typescript theme={null}
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)

```typescript theme={null}
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.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

```typescript theme={null}
// 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 — laptops is ProductSearchInstance, use .products[0] or index directly
const product = await Products.getById(laptops.products[0].id);
```

### Filtering Products

```typescript theme={null}
// 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

```typescript theme={null}
// 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) {
  await Products.update({ onSale: true }, product.id);
}
```

### Admin Dashboard

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

// Statistics
const totalValue = all.reduce((sum, p) => sum + p.price, 0);
const inStock = all.filter(p => p.inStock).length;
const categories = [...new Set(all.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!)

```typescript theme={null}
// 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

```typescript theme={null}
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

<CardGroup cols={2}>
  <Card title="CRUD Operations" icon="database">
    Create, Read, Update, Delete
  </Card>

  <Card title="Pagination" icon="table">
    Handle large datasets
  </Card>

  <Card title="Search" icon="magnifying-glass">
    Semantic search with vector embeddings
  </Card>

  <Card title="Filtering" icon="filter">
    MongoDB-style queries for structured data
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Products API" icon="book" href="/api/products">
    Complete API reference
  </Card>

  <Card title="Baskets Example" icon="cart-shopping" href="/examples/baskets">
    Add products to carts
  </Card>
</CardGroup>
