nitrostack 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/templates/typescript-auth/.env.example +23 -0
- package/templates/typescript-auth/src/app.module.ts +103 -0
- package/templates/typescript-auth/src/db/database.ts +163 -0
- package/templates/typescript-auth/src/db/seed.ts +374 -0
- package/templates/typescript-auth/src/db/setup.ts +87 -0
- package/templates/typescript-auth/src/events/analytics.service.ts +52 -0
- package/templates/typescript-auth/src/events/notification.service.ts +40 -0
- package/templates/typescript-auth/src/filters/global-exception.filter.ts +28 -0
- package/templates/typescript-auth/src/guards/README.md +75 -0
- package/templates/typescript-auth/src/guards/jwt.guard.ts +105 -0
- package/templates/typescript-auth/src/health/database.health.ts +41 -0
- package/templates/typescript-auth/src/index.ts +26 -0
- package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +24 -0
- package/templates/typescript-auth/src/middleware/logging.middleware.ts +42 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +16 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +114 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +40 -0
- package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +241 -0
- package/templates/typescript-auth/src/modules/auth/auth.module.ts +16 -0
- package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +147 -0
- package/templates/typescript-auth/src/modules/auth/auth.resources.ts +84 -0
- package/templates/typescript-auth/src/modules/auth/auth.tools.ts +139 -0
- package/templates/typescript-auth/src/modules/cart/cart.module.ts +16 -0
- package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +95 -0
- package/templates/typescript-auth/src/modules/cart/cart.resources.ts +44 -0
- package/templates/typescript-auth/src/modules/cart/cart.tools.ts +281 -0
- package/templates/typescript-auth/src/modules/orders/orders.module.ts +16 -0
- package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +88 -0
- package/templates/typescript-auth/src/modules/orders/orders.resources.ts +48 -0
- package/templates/typescript-auth/src/modules/orders/orders.tools.ts +281 -0
- package/templates/typescript-auth/src/modules/products/products.module.ts +16 -0
- package/templates/typescript-auth/src/modules/products/products.prompts.ts +146 -0
- package/templates/typescript-auth/src/modules/products/products.resources.ts +98 -0
- package/templates/typescript-auth/src/modules/products/products.tools.ts +266 -0
- package/templates/typescript-auth/src/pipes/validation.pipe.ts +42 -0
- package/templates/typescript-auth/src/services/database.service.ts +90 -0
- package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +122 -0
- package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +116 -0
- package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +105 -0
- package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +139 -0
- package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +153 -0
- package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +86 -0
- package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +116 -0
- package/templates/typescript-auth/src/widgets/app/categories/page.tsx +134 -0
- package/templates/typescript-auth/src/widgets/app/layout.tsx +21 -0
- package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +129 -0
- package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +206 -0
- package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +225 -0
- package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +218 -0
- package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +121 -0
- package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +173 -0
- package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +187 -0
- package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +165 -0
- package/templates/typescript-auth/src/widgets/next.config.js +38 -0
- package/templates/typescript-auth/src/widgets/package.json +18 -0
- package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +169 -0
- package/templates/typescript-auth/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-auth/src/widgets/types/tool-data.ts +141 -0
- package/templates/typescript-auth/src/widgets/widget-manifest.json +464 -0
- package/templates/typescript-auth/tsconfig.json +27 -0
- package/templates/typescript-auth-api-key/.env +15 -0
- package/templates/typescript-auth-api-key/.env.example +4 -0
- package/templates/typescript-auth-api-key/src/app.module.ts +38 -0
- package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +47 -0
- package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +157 -0
- package/templates/typescript-auth-api-key/src/health/system.health.ts +55 -0
- package/templates/typescript-auth-api-key/src/index.ts +47 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +12 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +73 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +60 -0
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +71 -0
- package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +18 -0
- package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +155 -0
- package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +123 -0
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-auth-api-key/src/widgets/next.config.js +37 -0
- package/templates/typescript-auth-api-key/src/widgets/package.json +24 -0
- package/templates/typescript-auth-api-key/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-auth-api-key/tsconfig.json +23 -0
- package/templates/typescript-oauth/.env.example +91 -0
- package/templates/typescript-oauth/src/app.module.ts +89 -0
- package/templates/typescript-oauth/src/guards/oauth.guard.ts +127 -0
- package/templates/typescript-oauth/src/index.ts +74 -0
- package/templates/typescript-oauth/src/modules/demo/demo.module.ts +16 -0
- package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +190 -0
- package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-oauth/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-oauth/src/widgets/next.config.js +37 -0
- package/templates/typescript-oauth/src/widgets/package.json +24 -0
- package/templates/typescript-oauth/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-oauth/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-oauth/tsconfig.json +23 -0
- package/templates/typescript-starter/.env.example +4 -0
- package/templates/typescript-starter/src/app.module.ts +34 -0
- package/templates/typescript-starter/src/health/system.health.ts +55 -0
- package/templates/typescript-starter/src/index.ts +27 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.module.ts +12 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.prompts.ts +73 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +60 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.tools.ts +71 -0
- package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +133 -0
- package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +134 -0
- package/templates/typescript-starter/src/widgets/app/layout.tsx +14 -0
- package/templates/typescript-starter/src/widgets/next.config.js +37 -0
- package/templates/typescript-starter/src/widgets/package.json +24 -0
- package/templates/typescript-starter/src/widgets/tsconfig.json +28 -0
- package/templates/typescript-starter/src/widgets/widget-manifest.json +48 -0
- package/templates/typescript-starter/tsconfig.json +23 -0
- package/LICENSE_URLS_UPDATE_COMPLETE.md +0 -388
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PromptDecorator as Prompt, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cart Prompts
|
|
5
|
+
* Provides helpful prompts for cart management
|
|
6
|
+
*/
|
|
7
|
+
export class CartPrompts {
|
|
8
|
+
/**
|
|
9
|
+
* Cart management help prompt
|
|
10
|
+
*/
|
|
11
|
+
@Prompt({
|
|
12
|
+
name: 'cart-management-help',
|
|
13
|
+
description: 'Get help managing your shopping cart',
|
|
14
|
+
})
|
|
15
|
+
async cartHelp(args: Record<string, any>, context: ExecutionContext) {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
role: 'user' as const,
|
|
19
|
+
content: 'I need help managing my shopping cart',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
role: 'assistant' as const,
|
|
23
|
+
content: `**Shopping Cart Management Guide**
|
|
24
|
+
|
|
25
|
+
**Available Tools (Requires Authentication):**
|
|
26
|
+
1. \`add_to_cart\` - Add products to cart
|
|
27
|
+
2. \`view_cart\` - View cart contents and total
|
|
28
|
+
3. \`update_cart_item\` - Change quantity or remove items
|
|
29
|
+
4. \`clear_cart\` - Empty entire cart
|
|
30
|
+
|
|
31
|
+
**Adding Items:**
|
|
32
|
+
\`\`\`
|
|
33
|
+
add_to_cart({
|
|
34
|
+
product_id: "product-uuid",
|
|
35
|
+
quantity: 2
|
|
36
|
+
})
|
|
37
|
+
\`\`\`
|
|
38
|
+
- Make sure to login first
|
|
39
|
+
- Check product stock availability
|
|
40
|
+
- Quantity must be > 0
|
|
41
|
+
|
|
42
|
+
**Viewing Cart:**
|
|
43
|
+
\`\`\`
|
|
44
|
+
view_cart({})
|
|
45
|
+
\`\`\`
|
|
46
|
+
- Shows all items with images
|
|
47
|
+
- Displays individual and total prices
|
|
48
|
+
- Item count included
|
|
49
|
+
|
|
50
|
+
**Updating Items:**
|
|
51
|
+
\`\`\`
|
|
52
|
+
update_cart_item({
|
|
53
|
+
product_id: "product-uuid",
|
|
54
|
+
quantity: 5 // or 0 to remove
|
|
55
|
+
})
|
|
56
|
+
\`\`\`
|
|
57
|
+
- Set quantity to 0 to remove item
|
|
58
|
+
- Must have sufficient stock
|
|
59
|
+
|
|
60
|
+
**Clearing Cart:**
|
|
61
|
+
\`\`\`
|
|
62
|
+
clear_cart({})
|
|
63
|
+
\`\`\`
|
|
64
|
+
- Removes ALL items
|
|
65
|
+
- Cannot be undone
|
|
66
|
+
|
|
67
|
+
**Common Operations:**
|
|
68
|
+
📦 **Add Multiple Items:**
|
|
69
|
+
Call \`add_to_cart\` multiple times with different product_ids
|
|
70
|
+
|
|
71
|
+
🔄 **Update Quantity:**
|
|
72
|
+
Use \`update_cart_item\` with new quantity
|
|
73
|
+
|
|
74
|
+
🗑️ **Remove Single Item:**
|
|
75
|
+
Use \`update_cart_item\` with quantity: 0
|
|
76
|
+
|
|
77
|
+
💰 **Check Total:**
|
|
78
|
+
Call \`view_cart\` to see current total
|
|
79
|
+
|
|
80
|
+
**Best Practices:**
|
|
81
|
+
✓ Login before adding to cart
|
|
82
|
+
✓ Check stock before adding large quantities
|
|
83
|
+
✓ Review cart before checkout
|
|
84
|
+
✓ Use \`view_cart\` to verify changes
|
|
85
|
+
|
|
86
|
+
**Tips:**
|
|
87
|
+
- Cart persists between sessions
|
|
88
|
+
- Items added increment existing quantities
|
|
89
|
+
- Checkout with \`create_order\` when ready
|
|
90
|
+
- Cart clears automatically after order`,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ResourceDecorator as Resource, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cart Resources
|
|
5
|
+
* Provides cart-related resource endpoints
|
|
6
|
+
*/
|
|
7
|
+
export class CartResources {
|
|
8
|
+
/**
|
|
9
|
+
* Cart schema resource
|
|
10
|
+
*/
|
|
11
|
+
@Resource({
|
|
12
|
+
uri: 'cart://schema',
|
|
13
|
+
name: 'Cart Schema',
|
|
14
|
+
description: 'Schema definition for shopping cart objects',
|
|
15
|
+
mimeType: 'application/json',
|
|
16
|
+
})
|
|
17
|
+
async getCartSchema(context: ExecutionContext) {
|
|
18
|
+
return {
|
|
19
|
+
type: 'json' as const,
|
|
20
|
+
data: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
items: {
|
|
24
|
+
type: 'array',
|
|
25
|
+
items: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
id: { type: 'string', description: 'Cart item ID' },
|
|
29
|
+
product_id: { type: 'string', description: 'Product ID' },
|
|
30
|
+
name: { type: 'string', description: 'Product name' },
|
|
31
|
+
price: { type: 'number', description: 'Product price' },
|
|
32
|
+
quantity: { type: 'integer', minimum: 1, description: 'Quantity in cart' },
|
|
33
|
+
image_url: { type: 'string', nullable: true, description: 'Product image' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
total: { type: 'number', description: 'Total cart value' },
|
|
38
|
+
itemCount: { type: 'integer', description: 'Number of items in cart' },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { ToolDecorator as Tool, Widget, UseGuards, z, ExecutionContext } from 'nitrostack';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { getDatabase } from '../../db/database.js';
|
|
4
|
+
import { JWTGuard } from '../../guards/jwt.guard.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Cart Tools
|
|
8
|
+
* Handles shopping cart operations (requires authentication)
|
|
9
|
+
*/
|
|
10
|
+
export class CartTools {
|
|
11
|
+
/**
|
|
12
|
+
* Add product to cart - Requires authentication
|
|
13
|
+
*/
|
|
14
|
+
@Tool({
|
|
15
|
+
name: 'add_to_cart',
|
|
16
|
+
description: 'Add a product to the shopping cart. Requires authentication.',
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
product_id: z.string().describe('The ID of the product to add'),
|
|
19
|
+
quantity: z.number().min(1).default(1).describe('Quantity to add'),
|
|
20
|
+
}),
|
|
21
|
+
examples: {
|
|
22
|
+
request: {
|
|
23
|
+
product_id: 'prod-1',
|
|
24
|
+
quantity: 2
|
|
25
|
+
},
|
|
26
|
+
response: {
|
|
27
|
+
message: 'Added to cart!',
|
|
28
|
+
product_id: 'prod-1',
|
|
29
|
+
product_name: 'Essence Mascara Lash Princess',
|
|
30
|
+
price: 9.99,
|
|
31
|
+
quantity: 2,
|
|
32
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/essence-mascara-lash-princess/thumbnail.webp',
|
|
33
|
+
cartItemCount: 2
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
@Widget('add-to-cart')
|
|
38
|
+
@UseGuards(JWTGuard)
|
|
39
|
+
async addToCart(input: any, context: ExecutionContext) {
|
|
40
|
+
const db = getDatabase();
|
|
41
|
+
const userId = context.auth?.subject;
|
|
42
|
+
|
|
43
|
+
// Check if product exists and has stock
|
|
44
|
+
const product: any = db.prepare('SELECT * FROM products WHERE id = ?').get(input.product_id);
|
|
45
|
+
|
|
46
|
+
if (!product) {
|
|
47
|
+
throw new Error(`Product with ID ${input.product_id} not found`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (product.stock < (input.quantity || 1)) {
|
|
51
|
+
throw new Error(`Insufficient stock. Only ${product.stock} units available.`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if item already in cart
|
|
55
|
+
const existing: any = db.prepare(`
|
|
56
|
+
SELECT * FROM carts WHERE user_id = ? AND product_id = ?
|
|
57
|
+
`).get(userId, input.product_id);
|
|
58
|
+
|
|
59
|
+
if (existing) {
|
|
60
|
+
// Update quantity
|
|
61
|
+
const newQuantity = existing.quantity + input.quantity;
|
|
62
|
+
|
|
63
|
+
if (product.stock < newQuantity) {
|
|
64
|
+
throw new Error(`Cannot add ${input.quantity} more units. Only ${product.stock - existing.quantity} additional units available.`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
db.prepare(`
|
|
68
|
+
UPDATE carts SET quantity = ? WHERE id = ?
|
|
69
|
+
`).run(newQuantity, existing.id);
|
|
70
|
+
|
|
71
|
+
context.logger.info(`Updated cart: product=${product.name}, quantity=${newQuantity}`);
|
|
72
|
+
|
|
73
|
+
// Get total cart count
|
|
74
|
+
const cartCount: any = db.prepare(`
|
|
75
|
+
SELECT SUM(quantity) as total FROM carts WHERE user_id = ?
|
|
76
|
+
`).get(userId);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
message: `Added to cart!`,
|
|
80
|
+
item: {
|
|
81
|
+
id: input.product_id,
|
|
82
|
+
name: product.name,
|
|
83
|
+
price: product.price,
|
|
84
|
+
quantity: input.quantity,
|
|
85
|
+
image_url: product.image_url,
|
|
86
|
+
},
|
|
87
|
+
cartItemCount: cartCount.total || 0,
|
|
88
|
+
};
|
|
89
|
+
} else {
|
|
90
|
+
// Add new item
|
|
91
|
+
const cartId = uuidv4();
|
|
92
|
+
|
|
93
|
+
db.prepare(`
|
|
94
|
+
INSERT INTO carts (id, user_id, product_id, quantity)
|
|
95
|
+
VALUES (?, ?, ?, ?)
|
|
96
|
+
`).run(cartId, userId, input.product_id, input.quantity);
|
|
97
|
+
|
|
98
|
+
context.logger.info(`Added to cart: product=${product.name}, quantity=${input.quantity}`);
|
|
99
|
+
|
|
100
|
+
// Get total cart count
|
|
101
|
+
const cartCount: any = db.prepare(`
|
|
102
|
+
SELECT SUM(quantity) as total FROM carts WHERE user_id = ?
|
|
103
|
+
`).get(userId);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
message: `Added to cart!`,
|
|
107
|
+
item: {
|
|
108
|
+
id: input.product_id,
|
|
109
|
+
name: product.name,
|
|
110
|
+
price: product.price,
|
|
111
|
+
quantity: input.quantity,
|
|
112
|
+
image_url: product.image_url,
|
|
113
|
+
},
|
|
114
|
+
cartItemCount: cartCount.total || 0,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* View shopping cart - Requires authentication
|
|
121
|
+
*/
|
|
122
|
+
@Tool({
|
|
123
|
+
name: 'view_cart',
|
|
124
|
+
description: 'View the current shopping cart with all items and total price. Requires authentication.',
|
|
125
|
+
inputSchema: z.object({}),
|
|
126
|
+
examples: {
|
|
127
|
+
request: {},
|
|
128
|
+
response: {
|
|
129
|
+
items: [
|
|
130
|
+
{
|
|
131
|
+
id: 'cart-item-1',
|
|
132
|
+
quantity: 2,
|
|
133
|
+
product_id: 'prod-1',
|
|
134
|
+
name: 'Essence Mascara Lash Princess',
|
|
135
|
+
price: 9.99,
|
|
136
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/essence-mascara-lash-princess/thumbnail.webp'
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'cart-item-2',
|
|
140
|
+
quantity: 1,
|
|
141
|
+
product_id: 'prod-2',
|
|
142
|
+
name: 'Eyeshadow Palette with Mirror',
|
|
143
|
+
price: 19.99,
|
|
144
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/eyeshadow-palette-with-mirror/thumbnail.webp'
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
total: 39.97,
|
|
148
|
+
itemCount: 2
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
@Widget('shopping-cart')
|
|
153
|
+
@UseGuards(JWTGuard)
|
|
154
|
+
async viewCart(input: any, context: ExecutionContext) {
|
|
155
|
+
const db = getDatabase();
|
|
156
|
+
const userId = context.auth?.subject;
|
|
157
|
+
|
|
158
|
+
const items: any[] = db.prepare(`
|
|
159
|
+
SELECT c.id, c.quantity, p.id as product_id, p.name, p.price, p.image_url
|
|
160
|
+
FROM carts c
|
|
161
|
+
JOIN products p ON c.product_id = p.id
|
|
162
|
+
WHERE c.user_id = ?
|
|
163
|
+
`).all(userId);
|
|
164
|
+
|
|
165
|
+
const total = items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
|
|
166
|
+
|
|
167
|
+
context.logger.info(`Viewed cart: ${items.length} items, total=$${total.toFixed(2)}`);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
items,
|
|
171
|
+
total,
|
|
172
|
+
itemCount: items.length,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Update cart item quantity - Requires authentication
|
|
178
|
+
*/
|
|
179
|
+
@Tool({
|
|
180
|
+
name: 'update_cart_item',
|
|
181
|
+
description: 'Update the quantity of a product in the cart. Set to 0 to remove. Requires authentication.',
|
|
182
|
+
inputSchema: z.object({
|
|
183
|
+
product_id: z.string().describe('The ID of the product to update'),
|
|
184
|
+
quantity: z.number().min(0).describe('New quantity (0 to remove)'),
|
|
185
|
+
}),
|
|
186
|
+
examples: {
|
|
187
|
+
request: {
|
|
188
|
+
product_id: 'prod-1',
|
|
189
|
+
quantity: 3
|
|
190
|
+
},
|
|
191
|
+
response: {
|
|
192
|
+
message: 'Cart updated successfully',
|
|
193
|
+
product: 'Essence Mascara Lash Princess',
|
|
194
|
+
quantity: 3
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
@Widget('cart-updated')
|
|
199
|
+
@UseGuards(JWTGuard)
|
|
200
|
+
async updateCartItem(input: any, context: ExecutionContext) {
|
|
201
|
+
const db = getDatabase();
|
|
202
|
+
const userId = context.auth?.subject;
|
|
203
|
+
|
|
204
|
+
if (input.quantity === 0) {
|
|
205
|
+
// Remove item
|
|
206
|
+
db.prepare(`
|
|
207
|
+
DELETE FROM carts WHERE user_id = ? AND product_id = ?
|
|
208
|
+
`).run(userId, input.product_id);
|
|
209
|
+
|
|
210
|
+
context.logger.info(`Removed from cart: product_id=${input.product_id}`);
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
message: 'Item removed from cart',
|
|
214
|
+
product: input.product_id,
|
|
215
|
+
};
|
|
216
|
+
} else {
|
|
217
|
+
// Check stock
|
|
218
|
+
const product: any = db.prepare('SELECT * FROM products WHERE id = ?').get(input.product_id);
|
|
219
|
+
|
|
220
|
+
if (!product) {
|
|
221
|
+
throw new Error(`Product with ID ${input.product_id} not found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (product.stock < input.quantity) {
|
|
225
|
+
throw new Error(`Insufficient stock. Only ${product.stock} units available.`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Update quantity
|
|
229
|
+
db.prepare(`
|
|
230
|
+
UPDATE carts SET quantity = ? WHERE user_id = ? AND product_id = ?
|
|
231
|
+
`).run(input.quantity, userId, input.product_id);
|
|
232
|
+
|
|
233
|
+
context.logger.info(`Updated cart item: product=${product.name}, quantity=${input.quantity}`);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
message: 'Cart updated successfully',
|
|
237
|
+
product: product.name,
|
|
238
|
+
quantity: input.quantity,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Clear shopping cart - Requires authentication
|
|
245
|
+
*/
|
|
246
|
+
@Tool({
|
|
247
|
+
name: 'clear_cart',
|
|
248
|
+
description: 'Remove all items from the shopping cart. Requires authentication.',
|
|
249
|
+
inputSchema: z.object({}),
|
|
250
|
+
examples: {
|
|
251
|
+
request: {},
|
|
252
|
+
response: {
|
|
253
|
+
message: 'Shopping cart cleared',
|
|
254
|
+
itemsRemoved: 2
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
@Widget('cart-cleared')
|
|
259
|
+
@UseGuards(JWTGuard)
|
|
260
|
+
async clearCart(input: any, context: ExecutionContext) {
|
|
261
|
+
const db = getDatabase();
|
|
262
|
+
const userId = context.auth?.subject;
|
|
263
|
+
|
|
264
|
+
// Get count before clearing
|
|
265
|
+
const count: any = db.prepare(`
|
|
266
|
+
SELECT COUNT(*) as count FROM carts WHERE user_id = ?
|
|
267
|
+
`).get(userId);
|
|
268
|
+
|
|
269
|
+
db.prepare(`
|
|
270
|
+
DELETE FROM carts WHERE user_id = ?
|
|
271
|
+
`).run(userId);
|
|
272
|
+
|
|
273
|
+
context.logger.info(`Cleared cart: removed ${count.count} items`);
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
message: 'Shopping cart cleared',
|
|
277
|
+
itemsRemoved: count.count,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Module } from 'nitrostack';
|
|
2
|
+
import { OrdersTools } from './orders.tools.js';
|
|
3
|
+
import { OrdersResources } from './orders.resources.js';
|
|
4
|
+
import { OrdersPrompts } from './orders.prompts.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Orders Module
|
|
8
|
+
* Provides order creation, history, resources, and prompts
|
|
9
|
+
*/
|
|
10
|
+
@Module({
|
|
11
|
+
name: 'orders',
|
|
12
|
+
description: 'Order creation and management',
|
|
13
|
+
controllers: [OrdersTools, OrdersResources, OrdersPrompts],
|
|
14
|
+
})
|
|
15
|
+
export class OrdersModule {}
|
|
16
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { PromptDecorator as Prompt, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Orders Prompts
|
|
5
|
+
* Provides helpful prompts for order management
|
|
6
|
+
*/
|
|
7
|
+
export class OrdersPrompts {
|
|
8
|
+
/**
|
|
9
|
+
* Order help prompt
|
|
10
|
+
*/
|
|
11
|
+
@Prompt({
|
|
12
|
+
name: 'order-help',
|
|
13
|
+
description: 'Get help with placing and managing orders',
|
|
14
|
+
})
|
|
15
|
+
async orderHelp(args: Record<string, any>, context: ExecutionContext) {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
role: 'user' as const,
|
|
19
|
+
content: 'I need help with orders',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
role: 'assistant' as const,
|
|
23
|
+
content: `**Order Management Guide**
|
|
24
|
+
|
|
25
|
+
**Available Tools (Requires Authentication):**
|
|
26
|
+
1. \`create_order\` - Place order from cart
|
|
27
|
+
2. \`get_order_history\` - View all your orders
|
|
28
|
+
3. \`get_order_details\` - View specific order details
|
|
29
|
+
|
|
30
|
+
**Creating an Order:**
|
|
31
|
+
\`\`\`
|
|
32
|
+
create_order({
|
|
33
|
+
payment_method: "credit_card" | "paypal" | "apple_pay",
|
|
34
|
+
shipping_address_id: "optional-address-id"
|
|
35
|
+
})
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
**Prerequisites:**
|
|
39
|
+
✓ Must be logged in
|
|
40
|
+
✓ Must have items in cart
|
|
41
|
+
✓ Must have a shipping address (or set default)
|
|
42
|
+
|
|
43
|
+
**Order Process:**
|
|
44
|
+
1. **Add items to cart** → \`add_to_cart\`
|
|
45
|
+
2. **Review cart** → \`view_cart\`
|
|
46
|
+
3. **Set shipping address** → \`add_address\` or use default
|
|
47
|
+
4. **Place order** → \`create_order\`
|
|
48
|
+
5. **Get confirmation** → Order ID returned
|
|
49
|
+
|
|
50
|
+
**Payment Methods:**
|
|
51
|
+
- \`credit_card\` - Credit/Debit card
|
|
52
|
+
- \`paypal\` - PayPal account
|
|
53
|
+
- \`apple_pay\` - Apple Pay
|
|
54
|
+
|
|
55
|
+
**After Order Created:**
|
|
56
|
+
- Cart is automatically cleared
|
|
57
|
+
- Product stock is updated
|
|
58
|
+
- Order appears in history
|
|
59
|
+
- Status starts as "pending"
|
|
60
|
+
|
|
61
|
+
**Viewing Orders:**
|
|
62
|
+
\`\`\`
|
|
63
|
+
get_order_history({}) // All your orders
|
|
64
|
+
get_order_details({ order_id: "order-uuid" }) // Specific order
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
**Order Statuses:**
|
|
68
|
+
- 🟡 **pending** - Order placed, awaiting processing
|
|
69
|
+
- 🔵 **processing** - Being prepared
|
|
70
|
+
- 📦 **shipped** - In transit
|
|
71
|
+
- ✅ **delivered** - Completed
|
|
72
|
+
- ❌ **cancelled** - Cancelled
|
|
73
|
+
|
|
74
|
+
**Common Issues:**
|
|
75
|
+
❌ "Cart is empty" → Add items first
|
|
76
|
+
❌ "No shipping address" → Add address with \`add_address\`
|
|
77
|
+
❌ "Insufficient stock" → Product sold out, update cart
|
|
78
|
+
|
|
79
|
+
**Tips:**
|
|
80
|
+
- Review cart before ordering
|
|
81
|
+
- Ensure correct shipping address
|
|
82
|
+
- Keep order ID for tracking
|
|
83
|
+
- Check order history anytime`,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ResourceDecorator as Resource, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Orders Resources
|
|
5
|
+
* Provides order-related resource endpoints
|
|
6
|
+
*/
|
|
7
|
+
export class OrdersResources {
|
|
8
|
+
/**
|
|
9
|
+
* Order schema resource
|
|
10
|
+
*/
|
|
11
|
+
@Resource({
|
|
12
|
+
uri: 'orders://schema',
|
|
13
|
+
name: 'Order Schema',
|
|
14
|
+
description: 'Schema definition for order objects',
|
|
15
|
+
mimeType: 'application/json',
|
|
16
|
+
})
|
|
17
|
+
async getOrderSchema(context: ExecutionContext) {
|
|
18
|
+
return {
|
|
19
|
+
type: 'json' as const,
|
|
20
|
+
data: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
id: { type: 'string', format: 'uuid', description: 'Order ID' },
|
|
24
|
+
user_id: { type: 'string', description: 'User ID' },
|
|
25
|
+
total: { type: 'number', minimum: 0, description: 'Order total' },
|
|
26
|
+
status: { type: 'string', enum: ['pending', 'processing', 'shipped', 'delivered', 'cancelled'], description: 'Order status' },
|
|
27
|
+
payment_method: { type: 'string', enum: ['credit_card', 'paypal', 'apple_pay'], description: 'Payment method' },
|
|
28
|
+
shipping_address_id: { type: 'string', description: 'Shipping address ID' },
|
|
29
|
+
created_at: { type: 'string', format: 'date-time', description: 'Order creation time' },
|
|
30
|
+
items: {
|
|
31
|
+
type: 'array',
|
|
32
|
+
items: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
id: { type: 'string', description: 'Order item ID' },
|
|
36
|
+
product_id: { type: 'string', description: 'Product ID' },
|
|
37
|
+
name: { type: 'string', description: 'Product name' },
|
|
38
|
+
quantity: { type: 'integer', minimum: 1, description: 'Quantity ordered' },
|
|
39
|
+
price: { type: 'number', description: 'Price at time of order' },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|