nitrostack 1.0.0 → 1.0.2
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 +30 -0
- package/dist/cli/index.js +4 -1
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/src/studio/README.md +140 -0
- package/src/studio/app/api/auth/fetch-metadata/route.ts +71 -0
- package/src/studio/app/api/auth/register-client/route.ts +67 -0
- package/src/studio/app/api/chat/route.ts +123 -0
- package/src/studio/app/api/health/checks/route.ts +42 -0
- package/src/studio/app/api/health/route.ts +13 -0
- package/src/studio/app/api/init/route.ts +85 -0
- package/src/studio/app/api/ping/route.ts +13 -0
- package/src/studio/app/api/prompts/[name]/route.ts +21 -0
- package/src/studio/app/api/prompts/route.ts +13 -0
- package/src/studio/app/api/resources/[...uri]/route.ts +18 -0
- package/src/studio/app/api/resources/route.ts +13 -0
- package/src/studio/app/api/roots/route.ts +13 -0
- package/src/studio/app/api/sampling/route.ts +14 -0
- package/src/studio/app/api/tools/[name]/call/route.ts +41 -0
- package/src/studio/app/api/tools/route.ts +23 -0
- package/src/studio/app/api/widget-examples/route.ts +44 -0
- package/src/studio/app/auth/callback/page.tsx +160 -0
- package/src/studio/app/auth/page.tsx +543 -0
- package/src/studio/app/chat/page.tsx +530 -0
- package/src/studio/app/chat/page.tsx.backup +390 -0
- package/src/studio/app/globals.css +410 -0
- package/src/studio/app/health/page.tsx +177 -0
- package/src/studio/app/layout.tsx +48 -0
- package/src/studio/app/page.tsx +337 -0
- package/src/studio/app/page.tsx.backup +346 -0
- package/src/studio/app/ping/page.tsx +204 -0
- package/src/studio/app/prompts/page.tsx +228 -0
- package/src/studio/app/resources/page.tsx +313 -0
- package/src/studio/components/EnlargeModal.tsx +116 -0
- package/src/studio/components/Sidebar.tsx +133 -0
- package/src/studio/components/ToolCard.tsx +108 -0
- package/src/studio/components/WidgetRenderer.tsx +99 -0
- package/src/studio/lib/api.ts +207 -0
- package/src/studio/lib/llm-service.ts +361 -0
- package/src/studio/lib/mcp-client.ts +168 -0
- package/src/studio/lib/store.ts +192 -0
- package/src/studio/lib/theme-provider.tsx +50 -0
- package/src/studio/lib/types.ts +107 -0
- package/src/studio/lib/widget-loader.ts +90 -0
- package/src/studio/middleware.ts +27 -0
- package/src/studio/next.config.js +16 -0
- package/src/studio/package-lock.json +2696 -0
- package/src/studio/package.json +34 -0
- package/src/studio/postcss.config.mjs +10 -0
- package/src/studio/tailwind.config.ts +67 -0
- package/src/studio/tsconfig.json +41 -0
- 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,374 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import bcrypt from 'bcryptjs';
|
|
3
|
+
import { getDatabase } from './database.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Seed database with initial data
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function seedUsers(): void {
|
|
10
|
+
const db = getDatabase();
|
|
11
|
+
|
|
12
|
+
// Data from https://dummyjson.com/users
|
|
13
|
+
const users = [
|
|
14
|
+
{
|
|
15
|
+
id: 'user-emily',
|
|
16
|
+
email: 'emily.johnson@x.dummyjson.com',
|
|
17
|
+
password: 'password123',
|
|
18
|
+
name: 'Emily Johnson',
|
|
19
|
+
profile_picture: 'https://dummyjson.com/icon/emilys/128',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'user-michael',
|
|
23
|
+
email: 'michael.williams@x.dummyjson.com',
|
|
24
|
+
password: 'password123',
|
|
25
|
+
name: 'Michael Williams',
|
|
26
|
+
profile_picture: 'https://dummyjson.com/icon/michaelw/128',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'user-sophia',
|
|
30
|
+
email: 'sophia.brown@x.dummyjson.com',
|
|
31
|
+
password: 'password123',
|
|
32
|
+
name: 'Sophia Brown',
|
|
33
|
+
profile_picture: 'https://dummyjson.com/icon/sophiab/128',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'user-james',
|
|
37
|
+
email: 'james.davis@x.dummyjson.com',
|
|
38
|
+
password: 'password123',
|
|
39
|
+
name: 'James Davis',
|
|
40
|
+
profile_picture: 'https://dummyjson.com/icon/jamesd/128',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'user-emma',
|
|
44
|
+
email: 'emma.miller@x.dummyjson.com',
|
|
45
|
+
password: 'password123',
|
|
46
|
+
name: 'Emma Miller',
|
|
47
|
+
profile_picture: 'https://dummyjson.com/icon/emmaj/128',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const stmt = db.prepare(`
|
|
52
|
+
INSERT OR REPLACE INTO users (id, email, password_hash, name, profile_picture)
|
|
53
|
+
VALUES (?, ?, ?, ?, ?)
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
for (const user of users) {
|
|
57
|
+
const passwordHash = bcrypt.hashSync(user.password, 10);
|
|
58
|
+
stmt.run(user.id, user.email, passwordHash, user.name, user.profile_picture);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`✅ Seeded ${users.length} users (from DummyJSON)`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function seedProducts(): void {
|
|
65
|
+
const db = getDatabase();
|
|
66
|
+
|
|
67
|
+
// Data from https://dummyjson.com/products
|
|
68
|
+
const products = [
|
|
69
|
+
// Beauty Products
|
|
70
|
+
{
|
|
71
|
+
id: 'prod-1',
|
|
72
|
+
name: 'Essence Mascara Lash Princess',
|
|
73
|
+
description: 'The Essence Mascara Lash Princess is a popular mascara known for its volumizing and lengthening effects.',
|
|
74
|
+
price: 9.99,
|
|
75
|
+
category: 'Beauty',
|
|
76
|
+
stock: 99,
|
|
77
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/essence-mascara-lash-princess/thumbnail.webp',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'prod-2',
|
|
81
|
+
name: 'Eyeshadow Palette with Mirror',
|
|
82
|
+
description: 'The Eyeshadow Palette offers a versatile range of eyeshadow shades for creating stunning eye looks.',
|
|
83
|
+
price: 19.99,
|
|
84
|
+
category: 'Beauty',
|
|
85
|
+
stock: 34,
|
|
86
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/eyeshadow-palette-with-mirror/thumbnail.webp',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'prod-3',
|
|
90
|
+
name: 'Powder Canister',
|
|
91
|
+
description: 'The Powder Canister is a finely milled setting powder designed to set makeup and control shine.',
|
|
92
|
+
price: 14.99,
|
|
93
|
+
category: 'Beauty',
|
|
94
|
+
stock: 89,
|
|
95
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/powder-canister/thumbnail.webp',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'prod-4',
|
|
99
|
+
name: 'Red Lipstick',
|
|
100
|
+
description: 'The Red Lipstick is a classic and bold choice for adding a pop of color to your lips.',
|
|
101
|
+
price: 12.99,
|
|
102
|
+
category: 'Beauty',
|
|
103
|
+
stock: 91,
|
|
104
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/red-lipstick/thumbnail.webp',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'prod-5',
|
|
108
|
+
name: 'Red Nail Polish',
|
|
109
|
+
description: 'The Red Nail Polish offers a rich and glossy red hue for vibrant and polished nails.',
|
|
110
|
+
price: 8.99,
|
|
111
|
+
category: 'Beauty',
|
|
112
|
+
stock: 79,
|
|
113
|
+
image_url: 'https://cdn.dummyjson.com/product-images/beauty/red-nail-polish/thumbnail.webp',
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// Fragrances
|
|
117
|
+
{
|
|
118
|
+
id: 'prod-6',
|
|
119
|
+
name: 'Calvin Klein CK One',
|
|
120
|
+
description: 'CK One by Calvin Klein is a classic unisex fragrance, known for its fresh and clean scent.',
|
|
121
|
+
price: 49.99,
|
|
122
|
+
category: 'Fragrances',
|
|
123
|
+
stock: 17,
|
|
124
|
+
image_url: 'https://cdn.dummyjson.com/product-images/fragrances/calvin-klein-ck-one/thumbnail.webp',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: 'prod-7',
|
|
128
|
+
name: 'Chanel Coco Noir Eau De',
|
|
129
|
+
description: 'Coco Noir by Chanel is an elegant and mysterious fragrance, featuring notes of grapefruit and rose.',
|
|
130
|
+
price: 129.99,
|
|
131
|
+
category: 'Fragrances',
|
|
132
|
+
stock: 41,
|
|
133
|
+
image_url: 'https://cdn.dummyjson.com/product-images/fragrances/chanel-coco-noir-eau-de/thumbnail.webp',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'prod-8',
|
|
137
|
+
name: 'Dior J\'adore',
|
|
138
|
+
description: 'J\'adore by Dior is a luxurious and floral fragrance, known for its sophisticated blend of ylang-ylang.',
|
|
139
|
+
price: 89.99,
|
|
140
|
+
category: 'Fragrances',
|
|
141
|
+
stock: 91,
|
|
142
|
+
image_url: 'https://cdn.dummyjson.com/product-images/fragrances/dior-j-adore/thumbnail.webp',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: 'prod-9',
|
|
146
|
+
name: 'Dolce Shine Eau de',
|
|
147
|
+
description: 'Dolce Shine by Dolce & Gabbana is a vibrant and fruity fragrance, featuring notes of mango and jasmine.',
|
|
148
|
+
price: 69.99,
|
|
149
|
+
category: 'Fragrances',
|
|
150
|
+
stock: 3,
|
|
151
|
+
image_url: 'https://cdn.dummyjson.com/product-images/fragrances/dolce-shine-eau-de/thumbnail.webp',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'prod-10',
|
|
155
|
+
name: 'Gucci Bloom Eau de',
|
|
156
|
+
description: 'Gucci Bloom by Gucci is a floral and captivating fragrance, with notes of tuberose and jasmine.',
|
|
157
|
+
price: 79.99,
|
|
158
|
+
category: 'Fragrances',
|
|
159
|
+
stock: 93,
|
|
160
|
+
image_url: 'https://cdn.dummyjson.com/product-images/fragrances/gucci-bloom-eau-de/thumbnail.webp',
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// Furniture
|
|
164
|
+
{
|
|
165
|
+
id: 'prod-11',
|
|
166
|
+
name: 'Annibale Colombo Bed',
|
|
167
|
+
description: 'The Annibale Colombo Bed is a luxurious and elegant bed frame, crafted with high-quality materials.',
|
|
168
|
+
price: 1899.99,
|
|
169
|
+
category: 'Furniture',
|
|
170
|
+
stock: 47,
|
|
171
|
+
image_url: 'https://cdn.dummyjson.com/product-images/furniture/annibale-colombo-bed/thumbnail.webp',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'prod-12',
|
|
175
|
+
name: 'Annibale Colombo Sofa',
|
|
176
|
+
description: 'The Annibale Colombo Sofa is a sophisticated and comfortable seating option, featuring exquisite design.',
|
|
177
|
+
price: 2499.99,
|
|
178
|
+
category: 'Furniture',
|
|
179
|
+
stock: 16,
|
|
180
|
+
image_url: 'https://cdn.dummyjson.com/product-images/furniture/annibale-colombo-sofa/thumbnail.webp',
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: 'prod-13',
|
|
184
|
+
name: 'Bedside Table African Cherry',
|
|
185
|
+
description: 'The Bedside Table in African Cherry is a stylish and functional addition to your bedroom.',
|
|
186
|
+
price: 299.99,
|
|
187
|
+
category: 'Furniture',
|
|
188
|
+
stock: 16,
|
|
189
|
+
image_url: 'https://cdn.dummyjson.com/product-images/furniture/bedside-table-african-cherry/thumbnail.webp',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'prod-14',
|
|
193
|
+
name: 'Knoll Saarinen Executive Conference Chair',
|
|
194
|
+
description: 'The Knoll Saarinen Executive Conference Chair is a modern and ergonomic chair, perfect for your office.',
|
|
195
|
+
price: 499.99,
|
|
196
|
+
category: 'Furniture',
|
|
197
|
+
stock: 47,
|
|
198
|
+
image_url: 'https://cdn.dummyjson.com/product-images/furniture/knoll-saarinen-executive-conference-chair/thumbnail.webp',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: 'prod-15',
|
|
202
|
+
name: 'Wooden Bathroom Sink With Mirror',
|
|
203
|
+
description: 'The Wooden Bathroom Sink with Mirror is a unique and stylish addition to your bathroom.',
|
|
204
|
+
price: 799.99,
|
|
205
|
+
category: 'Furniture',
|
|
206
|
+
stock: 95,
|
|
207
|
+
image_url: 'https://cdn.dummyjson.com/product-images/furniture/wooden-bathroom-sink-with-mirror/thumbnail.webp',
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
// Groceries
|
|
211
|
+
{
|
|
212
|
+
id: 'prod-16',
|
|
213
|
+
name: 'Apple',
|
|
214
|
+
description: 'Fresh and crisp apples, perfect for snacking or incorporating into various recipes.',
|
|
215
|
+
price: 1.99,
|
|
216
|
+
category: 'Groceries',
|
|
217
|
+
stock: 9,
|
|
218
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/apple/thumbnail.webp',
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: 'prod-17',
|
|
222
|
+
name: 'Beef Steak',
|
|
223
|
+
description: 'High-quality beef steak, great for grilling or cooking to your preferred level of doneness.',
|
|
224
|
+
price: 12.99,
|
|
225
|
+
category: 'Groceries',
|
|
226
|
+
stock: 96,
|
|
227
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/beef-steak/thumbnail.webp',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
id: 'prod-18',
|
|
231
|
+
name: 'Cat Food',
|
|
232
|
+
description: 'Nutritious cat food formulated to meet the dietary needs of your feline friend.',
|
|
233
|
+
price: 8.99,
|
|
234
|
+
category: 'Groceries',
|
|
235
|
+
stock: 13,
|
|
236
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/cat-food/thumbnail.webp',
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: 'prod-19',
|
|
240
|
+
name: 'Chicken Meat',
|
|
241
|
+
description: 'Fresh and tender chicken meat, suitable for various culinary preparations.',
|
|
242
|
+
price: 9.99,
|
|
243
|
+
category: 'Groceries',
|
|
244
|
+
stock: 69,
|
|
245
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/chicken-meat/thumbnail.webp',
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
id: 'prod-20',
|
|
249
|
+
name: 'Cooking Oil',
|
|
250
|
+
description: 'Versatile cooking oil suitable for frying, sautéing, and various culinary applications.',
|
|
251
|
+
price: 4.99,
|
|
252
|
+
category: 'Groceries',
|
|
253
|
+
stock: 22,
|
|
254
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/cooking-oil/thumbnail.webp',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
id: 'prod-21',
|
|
258
|
+
name: 'Cucumber',
|
|
259
|
+
description: 'Crisp and hydrating cucumbers, ideal for salads, snacks, or as a refreshing side.',
|
|
260
|
+
price: 1.49,
|
|
261
|
+
category: 'Groceries',
|
|
262
|
+
stock: 22,
|
|
263
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/cucumber/thumbnail.webp',
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
id: 'prod-22',
|
|
267
|
+
name: 'Dog Food',
|
|
268
|
+
description: 'Specially formulated dog food designed to provide essential nutrients for your canine companion.',
|
|
269
|
+
price: 10.99,
|
|
270
|
+
category: 'Groceries',
|
|
271
|
+
stock: 40,
|
|
272
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/dog-food/thumbnail.webp',
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: 'prod-23',
|
|
276
|
+
name: 'Eggs',
|
|
277
|
+
description: 'Fresh eggs, a versatile ingredient for baking, cooking, or breakfast.',
|
|
278
|
+
price: 2.99,
|
|
279
|
+
category: 'Groceries',
|
|
280
|
+
stock: 10,
|
|
281
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/eggs/thumbnail.webp',
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
id: 'prod-24',
|
|
285
|
+
name: 'Fish Steak',
|
|
286
|
+
description: 'Quality fish steak, suitable for grilling, baking, or pan-searing.',
|
|
287
|
+
price: 14.99,
|
|
288
|
+
category: 'Groceries',
|
|
289
|
+
stock: 99,
|
|
290
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/fish-steak/thumbnail.webp',
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
id: 'prod-25',
|
|
294
|
+
name: 'Green Bell Pepper',
|
|
295
|
+
description: 'Fresh green bell pepper, perfect for adding color and flavor to your dishes.',
|
|
296
|
+
price: 1.29,
|
|
297
|
+
category: 'Groceries',
|
|
298
|
+
stock: 89,
|
|
299
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/green-bell-pepper/thumbnail.webp',
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 'prod-26',
|
|
303
|
+
name: 'Green Chili Pepper',
|
|
304
|
+
description: 'Spicy green chili pepper, ideal for adding heat to your favorite recipes.',
|
|
305
|
+
price: 0.99,
|
|
306
|
+
category: 'Groceries',
|
|
307
|
+
stock: 8,
|
|
308
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/green-chili-pepper/thumbnail.webp',
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
id: 'prod-27',
|
|
312
|
+
name: 'Honey Jar',
|
|
313
|
+
description: 'Pure and natural honey in a convenient jar, perfect for sweetening beverages or drizzling over food.',
|
|
314
|
+
price: 6.99,
|
|
315
|
+
category: 'Groceries',
|
|
316
|
+
stock: 34,
|
|
317
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/honey-jar/thumbnail.webp',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: 'prod-28',
|
|
321
|
+
name: 'Ice Cream',
|
|
322
|
+
description: 'Creamy and delicious ice cream, available in various flavors for a delightful treat.',
|
|
323
|
+
price: 5.49,
|
|
324
|
+
category: 'Groceries',
|
|
325
|
+
stock: 27,
|
|
326
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/ice-cream/thumbnail.webp',
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'prod-29',
|
|
330
|
+
name: 'Juice',
|
|
331
|
+
description: 'Refreshing fruit juice, packed with vitamins and great for staying hydrated.',
|
|
332
|
+
price: 3.99,
|
|
333
|
+
category: 'Groceries',
|
|
334
|
+
stock: 50,
|
|
335
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/juice/thumbnail.webp',
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
id: 'prod-30',
|
|
339
|
+
name: 'Kiwi',
|
|
340
|
+
description: 'Nutrient-rich kiwi, perfect for snacking or adding a tropical twist to your dishes.',
|
|
341
|
+
price: 2.49,
|
|
342
|
+
category: 'Groceries',
|
|
343
|
+
stock: 99,
|
|
344
|
+
image_url: 'https://cdn.dummyjson.com/product-images/groceries/kiwi/thumbnail.webp',
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
const stmt = db.prepare(`
|
|
349
|
+
INSERT OR REPLACE INTO products (id, name, description, price, category, stock, image_url)
|
|
350
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
351
|
+
`);
|
|
352
|
+
|
|
353
|
+
for (const product of products) {
|
|
354
|
+
stmt.run(
|
|
355
|
+
product.id,
|
|
356
|
+
product.name,
|
|
357
|
+
product.description,
|
|
358
|
+
product.price,
|
|
359
|
+
product.category,
|
|
360
|
+
product.stock,
|
|
361
|
+
product.image_url
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
console.log(`✅ Seeded ${products.length} products (from DummyJSON)`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function seedAll(): void {
|
|
369
|
+
console.log('🌱 Seeding database...');
|
|
370
|
+
seedUsers();
|
|
371
|
+
seedProducts();
|
|
372
|
+
console.log('✅ Database seeding complete!');
|
|
373
|
+
}
|
|
374
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as dotenv from 'dotenv';
|
|
2
|
+
import { initializeSchema, clearAllData } from './database.js';
|
|
3
|
+
import { seedAll } from './seed.js';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Database setup script
|
|
10
|
+
* Run with: npm run setup-db
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Load environment variables
|
|
14
|
+
dotenv.config();
|
|
15
|
+
|
|
16
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
17
|
+
console.log('║ ║');
|
|
18
|
+
console.log('║ E-COMMERCE MCP SERVER - DATABASE SETUP ║');
|
|
19
|
+
console.log('║ ║');
|
|
20
|
+
console.log('╚══════════════════════════════════════════════════════════════╝\n');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// 1. Initialize schema
|
|
24
|
+
console.log('📦 Initializing database schema...');
|
|
25
|
+
initializeSchema();
|
|
26
|
+
console.log('✅ Schema initialized\n');
|
|
27
|
+
|
|
28
|
+
// 2. Clear existing data (optional)
|
|
29
|
+
console.log('🗑️ Clearing existing data...');
|
|
30
|
+
clearAllData();
|
|
31
|
+
console.log('✅ Data cleared\n');
|
|
32
|
+
|
|
33
|
+
// 3. Seed data
|
|
34
|
+
seedAll();
|
|
35
|
+
console.log('');
|
|
36
|
+
|
|
37
|
+
// 4. Generate JWT secret if not exists
|
|
38
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
39
|
+
const envExamplePath = path.join(process.cwd(), '.env.example');
|
|
40
|
+
|
|
41
|
+
if (!fs.existsSync(envPath) && fs.existsSync(envExamplePath)) {
|
|
42
|
+
console.log('📝 Creating .env file...');
|
|
43
|
+
let envContent = fs.readFileSync(envExamplePath, 'utf-8');
|
|
44
|
+
|
|
45
|
+
// Generate JWT secret (64 random bytes encoded as base64url)
|
|
46
|
+
const jwtSecret = 'jwt_secret_' + crypto.randomBytes(32).toString('base64url');
|
|
47
|
+
envContent = envContent.replace('your-jwt-secret-here-change-this', jwtSecret);
|
|
48
|
+
|
|
49
|
+
fs.writeFileSync(envPath, envContent);
|
|
50
|
+
console.log('✅ .env file created with JWT secret\n');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 5. Print test credentials
|
|
54
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
55
|
+
console.log(' TEST CREDENTIALS ');
|
|
56
|
+
console.log('═══════════════════════════════════════════════════════════════\n');
|
|
57
|
+
|
|
58
|
+
console.log('🧪 Test Users (use these in the inspector):');
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log(' 👤 Alice Johnson');
|
|
61
|
+
console.log(' Email: alice@example.com');
|
|
62
|
+
console.log(' Password: password123');
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(' 👤 Bob Smith');
|
|
65
|
+
console.log(' Email: bob@example.com');
|
|
66
|
+
console.log(' Password: password123');
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(' 👤 Charlie Brown');
|
|
69
|
+
console.log(' Email: charlie@example.com');
|
|
70
|
+
console.log(' Password: password123');
|
|
71
|
+
console.log('');
|
|
72
|
+
|
|
73
|
+
console.log('═══════════════════════════════════════════════════════════════\n');
|
|
74
|
+
|
|
75
|
+
console.log('🎉 Database setup complete!\n');
|
|
76
|
+
console.log('Next steps:');
|
|
77
|
+
console.log(' 1. npm install');
|
|
78
|
+
console.log(' 2. npm run build');
|
|
79
|
+
console.log(' 3. npm run dev');
|
|
80
|
+
console.log(' 4. Test in inspector with the credentials above\n');
|
|
81
|
+
|
|
82
|
+
process.exit(0);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('❌ Setup failed:', error);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Injectable, OnEvent } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Analytics Service
|
|
5
|
+
*
|
|
6
|
+
* Tracks events for analytics
|
|
7
|
+
*/
|
|
8
|
+
@Injectable()
|
|
9
|
+
export class AnalyticsService {
|
|
10
|
+
private events: any[] = [];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Track order creation
|
|
14
|
+
*/
|
|
15
|
+
@OnEvent('order.created')
|
|
16
|
+
async trackOrderCreated(order: any): Promise<void> {
|
|
17
|
+
this.events.push({
|
|
18
|
+
type: 'order_created',
|
|
19
|
+
timestamp: new Date().toISOString(),
|
|
20
|
+
data: {
|
|
21
|
+
order_id: order.id,
|
|
22
|
+
total: order.total,
|
|
23
|
+
item_count: order.items?.length || 0,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
console.log(`📊 Tracked: Order Created #${order.id}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Track product viewed
|
|
31
|
+
*/
|
|
32
|
+
@OnEvent('product.viewed')
|
|
33
|
+
async trackProductViewed(product: any): Promise<void> {
|
|
34
|
+
this.events.push({
|
|
35
|
+
type: 'product_viewed',
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
data: {
|
|
38
|
+
product_id: product.id,
|
|
39
|
+
product_name: product.name,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
console.log(`📊 Tracked: Product Viewed - ${product.name}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get analytics data
|
|
47
|
+
*/
|
|
48
|
+
getAnalytics(): any[] {
|
|
49
|
+
return this.events;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Injectable, OnEvent } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Notification Service
|
|
5
|
+
*
|
|
6
|
+
* Listens to events and sends notifications
|
|
7
|
+
*/
|
|
8
|
+
@Injectable()
|
|
9
|
+
export class NotificationService {
|
|
10
|
+
/**
|
|
11
|
+
* Handle order created event
|
|
12
|
+
*/
|
|
13
|
+
@OnEvent('order.created')
|
|
14
|
+
async handleOrderCreated(order: any): Promise<void> {
|
|
15
|
+
console.log(`📧 Sending order confirmation email for order #${order.id}`);
|
|
16
|
+
// TODO: Implement actual email sending
|
|
17
|
+
console.log(` To: ${order.user_email}`);
|
|
18
|
+
console.log(` Subject: Order Confirmation #${order.id}`);
|
|
19
|
+
console.log(` Total: $${order.total}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Handle order shipped event
|
|
24
|
+
*/
|
|
25
|
+
@OnEvent('order.shipped')
|
|
26
|
+
async handleOrderShipped(order: any): Promise<void> {
|
|
27
|
+
console.log(`📦 Sending shipping notification for order #${order.id}`);
|
|
28
|
+
// TODO: Implement actual notification
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Handle user registered event
|
|
33
|
+
*/
|
|
34
|
+
@OnEvent('user.registered')
|
|
35
|
+
async handleUserRegistered(user: any): Promise<void> {
|
|
36
|
+
console.log(`👋 Sending welcome email to ${user.email}`);
|
|
37
|
+
// TODO: Implement actual welcome email
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ExceptionFilter, ExceptionFilterInterface, ExecutionContext } from 'nitrostack';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Global Exception Filter
|
|
5
|
+
*
|
|
6
|
+
* Handles all unhandled exceptions and formats error responses
|
|
7
|
+
*/
|
|
8
|
+
@ExceptionFilter()
|
|
9
|
+
export class GlobalExceptionFilter implements ExceptionFilterInterface {
|
|
10
|
+
catch(exception: any, context: ExecutionContext) {
|
|
11
|
+
context.logger.error('Unhandled exception', {
|
|
12
|
+
tool: context.toolName || 'unknown',
|
|
13
|
+
error: exception.message,
|
|
14
|
+
stack: exception.stack,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Format error response
|
|
18
|
+
return {
|
|
19
|
+
error: true,
|
|
20
|
+
message: exception.message || 'Internal server error',
|
|
21
|
+
code: exception.code || 'INTERNAL_ERROR',
|
|
22
|
+
timestamp: new Date().toISOString(),
|
|
23
|
+
requestId: context.requestId,
|
|
24
|
+
tool: context.toolName || 'unknown',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Guards
|
|
2
|
+
|
|
3
|
+
Guards are classes that implement the `Guard` interface and determine whether a tool can be executed.
|
|
4
|
+
|
|
5
|
+
## What are Guards?
|
|
6
|
+
|
|
7
|
+
Guards in NitroStack are similar to NestJS guards - they handle authorization logic before tool execution. Use the `@UseGuards()` decorator to apply guards to your tools.
|
|
8
|
+
|
|
9
|
+
## Available Guards
|
|
10
|
+
|
|
11
|
+
### JWTGuard
|
|
12
|
+
|
|
13
|
+
Validates JWT tokens and populates `context.auth` with user information.
|
|
14
|
+
|
|
15
|
+
**Usage:**
|
|
16
|
+
```typescript
|
|
17
|
+
import { JWTGuard } from '../guards/jwt.guard.js';
|
|
18
|
+
|
|
19
|
+
@Tool({ name: 'get_profile', ... })
|
|
20
|
+
@UseGuards(JWTGuard)
|
|
21
|
+
async getProfile(input: any, context: ExecutionContext) {
|
|
22
|
+
const userId = context.auth?.subject;
|
|
23
|
+
// User is already authenticated!
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Creating Custom Guards
|
|
28
|
+
|
|
29
|
+
Create a class that implements the `Guard` interface:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { Guard, ExecutionContext } from 'nitrostack';
|
|
33
|
+
|
|
34
|
+
export class RoleGuard implements Guard {
|
|
35
|
+
constructor(private requiredRole: string) {}
|
|
36
|
+
|
|
37
|
+
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
38
|
+
const userRole = context.auth?.role;
|
|
39
|
+
|
|
40
|
+
if (userRole !== this.requiredRole) {
|
|
41
|
+
throw new Error(`Required role: ${this.requiredRole}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Usage:**
|
|
50
|
+
```typescript
|
|
51
|
+
@UseGuards(JWTGuard, new RoleGuard('admin'))
|
|
52
|
+
async deleteUser(input: any, context: ExecutionContext) {
|
|
53
|
+
// Only admins can execute this
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Guard Execution Order
|
|
58
|
+
|
|
59
|
+
Guards are executed in the order they are specified:
|
|
60
|
+
```typescript
|
|
61
|
+
@UseGuards(JWTGuard, RoleGuard, PermissionGuard)
|
|
62
|
+
```
|
|
63
|
+
1. JWTGuard validates token
|
|
64
|
+
2. RoleGuard checks user role
|
|
65
|
+
3. PermissionGuard checks specific permissions
|
|
66
|
+
|
|
67
|
+
If any guard returns `false` or throws an error, execution stops.
|
|
68
|
+
|
|
69
|
+
## Best Practices
|
|
70
|
+
|
|
71
|
+
1. **Keep guards focused** - Each guard should have one responsibility
|
|
72
|
+
2. **Reuse guards** - Create guards that can be used across multiple tools
|
|
73
|
+
3. **Clear error messages** - Help users understand why access was denied
|
|
74
|
+
4. **Log important events** - Use `context.logger` for debugging
|
|
75
|
+
|