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.
Overview
The Products API provides complete CRUD operations for managing an e-commerce product catalog. Returns ProductInstance objects with direct property access.
import { Products } from 'lua-cli' ;
// Search products - returns ProductSearchInstance
const results = await Products . search ( 'laptop' );
// Direct property access on results
const names = results . map ( p => p . name );
const prices = results . map ( p => p . price );
// Create product - returns ProductInstance
const product = await Products . create ({
name: 'MacBook Pro' ,
price: 1999.99
});
// Direct property access
console . log ( product . name ); // "MacBook Pro"
console . log ( product . price ); // 1999.99
// Instance methods
await product . update ({ price: 1799.99 });
await product . save ();
await product . delete ();
Direct Access Access properties with product.name not product.data.name
Array Methods Use .map(), .filter() on search results
Instance Methods Built-in update(), save(), and delete()
Iteration Use for...of loops
Return Shape Reference
Products.search() and Products.get() do NOT return arrays with a .data property. They return instance wrappers that are directly iterable.
Method Returns How to use Products.search(q, limit?)ProductSearchInstance — iterable, has .products, .lengthresults.map(p => p.name), results.products, results.length — no .data Products.get(page?, limit?) or Products.get({page, limit, filter})ProductPaginationInstance — iterable, has .products, .pagination, .lengthresults.map(p => p.name), results.pagination.totalPages — no .data Products.create(product)ProductInstanceproduct.name, product.price, await product.update({...})Products.getById(id)ProductInstanceDirect property access Products.update(data, id)UpdateProductResponse{ product }Products.delete(id)DeleteProductResponse{ success }
Quick examples:
// ✅ Products.search → ProductSearchInstance (iterable)
const results = await Products . search ( 'laptop' );
results . forEach ( p => console . log ( p . name , p . price )); // iterate directly
const names = results . map ( p => p . name ); // array methods work
console . log ( results . length ); // ✅ count
// ❌ results.data → does not exist
// ✅ Products.get → ProductPaginationInstance
const page = await Products . get ({ page: 1 , limit: 20 , filter: { inStock: true } });
page . map ( p => p . name ); // iterate directly
console . log ( page . pagination . totalPages ); // ✅ pagination
// ❌ page.data → does not exist
Methods
search()
Search products by name or description using semantic search.
Products . search ( query : string ): Promise < ProductSearchInstance >
Search query to match against product names and descriptions
Returns: ProductSearchInstance - Array-like collection with direct access to products via .products property
Example:
// Search with default limit (5)
const results = await Products . search ( 'laptop' );
// Search with custom limit
const moreResults = await Products . search ( 'laptop' , 10 );
// Direct array methods
results . forEach ( product => {
console . log ( ` ${ product . name } - $ ${ product . price } ` );
});
// Or use .map()
const names = results . map ( p => p . name );
const prices = results . map ( p => p . price );
// Filter
const affordable = results . filter ( p => p . price < 1000 );
// Find
const specific = results . find ( p => p . sku === 'LAP-001' );
// Check length
console . log ( `Found ${ results . length } products` );
// For...of iteration
for ( const product of results ) {
console . log ( product . name );
}
get()
Retrieve products with pagination and optional filtering.
// Simple pagination (backward compatible)
Products . get ( page ?: number , limit ?: number ): Promise < ProductPaginationInstance >
// With filter options (recommended)
Products . get ( options ?: ProductFilterOptions ): Promise < ProductPaginationInstance >
ProductFilterOptions:
interface ProductFilterOptions {
page ?: number ; // Page number (1-indexed), default: 1
limit ?: number ; // Items per page, default: 10
filter ?: object ; // MongoDB-style filter for product data
}
Number of products per page
MongoDB-style filter object to query product data fields
Returns: ProductPaginationInstance - Array-like collection with pagination support
Examples:
// Simple pagination (backward compatible)
const page = await Products . get ( 1 , 20 );
// Using options object (recommended)
const page = await Products . get ({ page: 1 , limit: 20 });
// With filters - exact match
const electronics = await Products . get ({
page: 1 ,
limit: 20 ,
filter: { category: 'Electronics' }
});
// With filters - price range
const affordable = await Products . get ({
filter: {
price: { $lte: 100 }
}
});
// With filters - multiple conditions
const inStockLaptops = await Products . get ({
filter: {
category: 'Laptops' ,
inStock: true ,
price: { $gte: 500 , $lte: 1500 }
}
});
// Direct array methods
page . forEach ( product => {
console . log ( ` ${ product . name } - $ ${ product . price } ` );
});
// Access pagination info
console . log ( `Page ${ page . pagination . currentPage } of ${ page . pagination . totalPages } ` );
console . log ( `Showing ${ page . length } of ${ page . pagination . totalCount } products` );
// Navigate pages
if ( page . pagination . hasNextPage ) {
const nextPage = await page . nextPage ();
}
if ( page . pagination . hasPrevPage ) {
const prevPage = await page . prevPage ();
}
// Use array methods
const names = page . map ( p => p . name );
const inStock = page . filter ( p => p . inStock );
Filter Operators:
The filter supports MongoDB-style operators:
// Comparison
{ price : { $eq : 99.99 } } // Equal
{ price : { $ne : 99.99 } } // Not equal
{ price : { $gt : 50 } } // Greater than
{ price : { $gte : 50 } } // Greater than or equal
{ price : { $lt : 100 } } // Less than
{ price : { $lte : 100 } } // Less than or equal
// Array matching
{ category : { $in : [ 'Electronics' , 'Computers' ] } }
// Nested fields (dot notation)
{ 'specs.color' : 'black' }
{ 'metadata.brand' : 'Apple' }
getById()
Get a specific product by ID.
Products . getById ( id : string ): Promise < ProductInstance >
Returns: ProductInstance with direct property access and methods
Example:
const product = await Products . getById ( 'product_abc123' );
// Direct property access
console . log ( product . name ); // "MacBook Pro"
console . log ( product . price ); // 1999.99
console . log ( product . sku ); // "MBP-14"
// Instance methods
await product . update ({ price: 1799.99 });
await product . delete ();
create()
Create a new product.
Products . create ( product : Product ): Promise < ProductInstance >
Whether product is in stock
Returns: ProductInstance with direct property access and methods
Example:
const product = await Products . create ({
name: 'Wireless Mouse' ,
price: 29.99 ,
category: 'Electronics' ,
sku: 'MOUSE-001' ,
inStock: true ,
description: 'Ergonomic wireless mouse'
});
// Direct property access
console . log ( product . id ); // "product_xyz789"
console . log ( product . name ); // "Wireless Mouse"
console . log ( product . price ); // 29.99
// Instance methods available
await product . update ({ price: 24.99 });
update() (Instance Method)
Update an existing product via an instance. Use product.update() on a retrieved product — there is no static Products.update() method.
product . update ( data : Record < string , any > ): Promise < Product >
Partial product data to update
Example:
const product = await Products . getById ( 'product_xyz789' );
// Update via instance method
await product . update ({
price: 24.99 ,
inStock: false
});
// Access updated properties
console . log ( product . price ); // 24.99
console . log ( product . inStock ); // false
save() (Instance Method)
Save the current state of the product to the server. This is a convenience method that persists all changes made to the product instance.
product . save (): Promise < boolean >
Returns: Promise resolving to true if successful
Example:
const product = await Products . getById ( 'product_xyz789' );
// Modify product properties directly
product . price = 24.99 ;
product . inStock = false ;
product . description = "Updated description" ;
// Save all changes at once
await product . save ();
// Much cleaner workflow!
New in Latest Version: The save() method provides a simpler workflow - modify properties then save, rather than calling Products.update() with the product ID.
delete()
Delete a product.
Products . delete ( id : string ): Promise < DeleteProductResponse >
Example:
await Products . delete ( 'product_xyz789' );
ProductInstance
All product methods return ProductInstance objects with:
Direct Property Access:
product . name
product . price
product . sku
product . inStock
product . category
product . description
// Any custom fields
Instance Methods:
await product . update ({ price: 999.99 });
await product . save ();
await product . delete ();
Backward Compatible:
product . name ; // ✅ New way
product . data . name ; // ✅ Old way still works
Complete Examples
import { LuaTool , Products } from 'lua-cli' ;
import { z } from 'zod' ;
export class SearchProductsTool implements LuaTool {
name = "search_products" ;
description = "Search for products by name or description" ;
inputSchema = z . object ({
query: z . string (). describe ( "Search query" ),
maxPrice: z . number (). optional ()
});
async execute ( input : z . infer < typeof this . inputSchema >) {
const results = await Products . search ( input . query );
// Filter by price if specified
let products = results . products ;
if ( input . maxPrice ) {
products = products . filter ( p => p . price <= input . maxPrice );
}
return {
products: products . map ( p => ({
id: p . id ,
name: p . name ,
price: `$ ${ p . price . toFixed ( 2 ) } ` ,
inStock: p . inStock ? '✅ In Stock' : '❌ Out of Stock'
})),
total: products . length
};
}
}
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 ,
inStock: true
});
return {
success: true ,
productId: result . id ,
message: `Product " ${ input . name } " created successfully`
};
}
}
export class UpdateStockTool implements LuaTool {
name = "update_stock" ;
description = "Update product stock status" ;
inputSchema = z . object ({
productId: z . string (),
inStock: z . boolean ()
});
async execute ( input : z . infer < typeof this . inputSchema >) {
await Products . update (
{ inStock: input . inStock },
input . productId
);
return {
success: true ,
message: `Stock status updated to ${ input . inStock ? 'in stock' : 'out of stock' } `
};
}
}
Use Cases
E-commerce Catalog
// Browse products with pagination
const products = await Products . get ({ page: 1 , limit: 20 });
// Search 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 . products [ 0 ]. id );
Inventory Management
// Update product price
await Products . update ({ price: 899.99 }, productId );
// Mark as out of stock
await Products . update ({ inStock: false }, productId );
// Update multiple fields
await Products . update ({
price: 799.99 ,
inStock: true ,
category: 'Electronics - Sale'
}, productId );
// Get all out-of-stock products
const outOfStock = await Products . get ({
filter: { inStock: false }
});
Filtering Products
// By price range
const affordable = await Products . get ({
filter: {
price: { $gte: 50 , $lte: 200 }
}
});
// By category and availability
const availablePhones = await Products . get ({
filter: {
category: 'Phones' ,
inStock: true
}
});
// By nested properties
const appleProducts = await Products . get ({
filter: {
'metadata.brand' : 'Apple'
}
});
// Multiple categories
const gadgets = await Products . get ({
filter: {
category: { $in: [ 'Phones' , 'Tablets' , 'Watches' ] }
}
});
Product Recommendations
// Search similar products
const similar = await Products . search ( product . category );
// Or filter by same category
const sameCategory = await Products . get ({
filter: {
category: product . category ,
price: {
$gte: product . price * 0.8 ,
$lte: product . price * 1.2
}
}
});
Search vs Filter
When to Use Search
When to Use Filter
Use Products.search() for semantic/fuzzy matching:
“laptop for students”
“wireless headphones”
Natural language queries
// Finds products by meaning, not exact match
const results = await Products . search ( 'affordable gaming laptop' );
Use Products.get() with filter for structured queries:
Exact category matches
Price ranges
Stock status
Attribute combinations
// Finds products matching exact criteria
const results = await Products . get ({
filter: {
category: 'Laptops' ,
price: { $lte: 1000 },
inStock: true
}
});
Best Practices
Always check if product exists: const product = await Products . getById ( input . productId );
if ( ! product ) {
throw new Error ( `Product not found: ${ input . productId } ` );
}
Check Stock Before Adding to Cart
const product = await Products . getById ( productId );
if ( ! product . inStock ) {
return {
success: false ,
message: ` ${ product . name } is currently out of stock`
};
}
Format Prices for Display
Handle Search with No Results
const results = await Products . search ( query );
if ( results . products . length === 0 ) {
return {
products: [],
message: `No products found for " ${ query } ". Try different search terms.`
};
}
If product results don’t look right, log the raw return to see the actual shape: const results = await Products . search ( input . query );
console . log ( 'Products.search result:' , JSON . stringify ( results , null , 2 ));
Then run lua logs --type skill --limit 5 after a test message to inspect the output. See the Debugging Skills guide for the full workflow.
Next Steps
Baskets API Add products to shopping carts
Product Examples See complete tool examples
Debugging Skills Inspect runtime return values