nitrostack 1.0.55 → 1.0.56

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.
Files changed (222) hide show
  1. package/dist/cli/commands/init.d.ts.map +1 -1
  2. package/dist/cli/commands/init.js +14 -9
  3. package/dist/cli/commands/init.js.map +1 -1
  4. package/dist/widgets/hooks/index.d.ts +7 -0
  5. package/dist/widgets/hooks/index.d.ts.map +1 -0
  6. package/dist/widgets/hooks/index.js +7 -0
  7. package/dist/widgets/hooks/index.js.map +1 -0
  8. package/dist/widgets/hooks/use-display-mode.d.ts +11 -0
  9. package/dist/widgets/hooks/use-display-mode.d.ts.map +1 -0
  10. package/dist/widgets/hooks/use-display-mode.js +13 -0
  11. package/dist/widgets/hooks/use-display-mode.js.map +1 -0
  12. package/dist/widgets/hooks/use-max-height.d.ts +10 -0
  13. package/dist/widgets/hooks/use-max-height.d.ts.map +1 -0
  14. package/dist/widgets/hooks/use-max-height.js +13 -0
  15. package/dist/widgets/hooks/use-max-height.js.map +1 -0
  16. package/dist/widgets/hooks/use-openai-global.d.ts +12 -0
  17. package/dist/widgets/hooks/use-openai-global.d.ts.map +1 -0
  18. package/dist/widgets/hooks/use-openai-global.js +32 -0
  19. package/dist/widgets/hooks/use-openai-global.js.map +1 -0
  20. package/dist/widgets/hooks/use-theme.d.ts +10 -0
  21. package/dist/widgets/hooks/use-theme.d.ts.map +1 -0
  22. package/dist/widgets/hooks/use-theme.js +12 -0
  23. package/dist/widgets/hooks/use-theme.js.map +1 -0
  24. package/dist/widgets/hooks/use-widget-state.d.ts +18 -0
  25. package/dist/widgets/hooks/use-widget-state.d.ts.map +1 -0
  26. package/dist/widgets/hooks/use-widget-state.js +27 -0
  27. package/dist/widgets/hooks/use-widget-state.js.map +1 -0
  28. package/dist/widgets/hooks/useWidgetSDK.d.ts +47 -0
  29. package/dist/widgets/hooks/useWidgetSDK.d.ts.map +1 -0
  30. package/dist/widgets/hooks/useWidgetSDK.js +67 -0
  31. package/dist/widgets/hooks/useWidgetSDK.js.map +1 -0
  32. package/dist/widgets/index.d.ts +7 -1
  33. package/dist/widgets/index.d.ts.map +1 -1
  34. package/dist/widgets/index.js +11 -1
  35. package/dist/widgets/index.js.map +1 -1
  36. package/dist/widgets/runtime/WidgetLayout.d.ts +32 -0
  37. package/dist/widgets/runtime/WidgetLayout.d.ts.map +1 -0
  38. package/dist/widgets/runtime/WidgetLayout.js +143 -0
  39. package/dist/widgets/runtime/WidgetLayout.js.map +1 -0
  40. package/dist/widgets/runtime/widget-polyfill.d.ts +1 -0
  41. package/dist/widgets/runtime/widget-polyfill.d.ts.map +1 -0
  42. package/dist/widgets/runtime/widget-polyfill.js +28 -0
  43. package/dist/widgets/runtime/widget-polyfill.js.map +1 -0
  44. package/dist/widgets/sdk.d.ts +109 -0
  45. package/dist/widgets/sdk.d.ts.map +1 -0
  46. package/dist/widgets/sdk.js +221 -0
  47. package/dist/widgets/sdk.js.map +1 -0
  48. package/dist/widgets/types.d.ts +89 -0
  49. package/dist/widgets/types.d.ts.map +1 -0
  50. package/dist/widgets/types.js +8 -0
  51. package/dist/widgets/types.js.map +1 -0
  52. package/dist/widgets/utils/media-queries.d.ts +34 -0
  53. package/dist/widgets/utils/media-queries.d.ts.map +1 -0
  54. package/dist/widgets/utils/media-queries.js +42 -0
  55. package/dist/widgets/utils/media-queries.js.map +1 -0
  56. package/package.json +1 -1
  57. package/src/studio/app/chat/page.tsx +274 -137
  58. package/src/studio/app/globals.css +140 -64
  59. package/src/studio/branding.md +807 -0
  60. package/src/studio/components/WidgetRenderer.tsx +222 -16
  61. package/src/studio/lib/llm-service.ts +39 -39
  62. package/templates/typescript-oauth/{env.example → .env.example} +4 -10
  63. package/templates/typescript-oauth/README.md +226 -306
  64. package/templates/typescript-oauth/package-lock.json +4253 -0
  65. package/templates/typescript-oauth/package.json +10 -5
  66. package/templates/typescript-oauth/src/app.module.ts +39 -36
  67. package/templates/typescript-oauth/src/guards/oauth.guard.ts +0 -1
  68. package/templates/typescript-oauth/src/index.ts +22 -30
  69. package/templates/typescript-oauth/src/modules/flights/booking.tools.ts +323 -0
  70. package/templates/typescript-oauth/src/modules/flights/flights.module.ts +14 -0
  71. package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +231 -0
  72. package/templates/typescript-oauth/src/modules/flights/flights.resources.ts +215 -0
  73. package/templates/typescript-oauth/src/modules/flights/flights.tools.ts +457 -0
  74. package/templates/typescript-oauth/src/services/duffel.service.ts +285 -0
  75. package/templates/typescript-oauth/src/widgets/app/airport-search/page.tsx +270 -0
  76. package/templates/typescript-oauth/src/widgets/app/flight-details/page.tsx +261 -0
  77. package/templates/typescript-oauth/src/widgets/app/flight-search-results/page.tsx +378 -0
  78. package/templates/typescript-oauth/src/widgets/app/globals.css +167 -0
  79. package/templates/typescript-oauth/src/widgets/app/layout.tsx +6 -2
  80. package/templates/typescript-oauth/src/widgets/app/order-cancellation/page.tsx +207 -0
  81. package/templates/typescript-oauth/src/widgets/app/order-summary/page.tsx +245 -0
  82. package/templates/typescript-oauth/src/widgets/app/payment-confirmation/page.tsx +152 -0
  83. package/templates/typescript-oauth/src/widgets/app/seat-selection/page.tsx +486 -0
  84. package/templates/typescript-oauth/src/widgets/next-env.d.ts +5 -0
  85. package/templates/typescript-oauth/src/widgets/package-lock.json +155 -126
  86. package/templates/typescript-oauth/src/widgets/widget-manifest.json +374 -27
  87. package/templates/typescript-pizzaz/IMPLEMENTATION.md +98 -0
  88. package/templates/typescript-pizzaz/README.md +233 -0
  89. package/templates/typescript-pizzaz/package.json +31 -0
  90. package/templates/typescript-pizzaz/src/app.module.ts +28 -0
  91. package/templates/typescript-pizzaz/src/index.ts +30 -0
  92. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.data.ts +106 -0
  93. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.module.ts +11 -0
  94. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.service.ts +60 -0
  95. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.tools.ts +197 -0
  96. package/templates/typescript-pizzaz/src/widgets/app/layout.tsx +18 -0
  97. package/templates/typescript-pizzaz/src/widgets/app/pizza-list/page.tsx +272 -0
  98. package/templates/typescript-pizzaz/src/widgets/app/pizza-map/page.tsx +216 -0
  99. package/templates/typescript-pizzaz/src/widgets/app/pizza-shop/page.tsx +374 -0
  100. package/templates/typescript-pizzaz/src/widgets/components/CompactShopCard.tsx +144 -0
  101. package/templates/typescript-pizzaz/src/widgets/components/PizzaCard.tsx +191 -0
  102. package/templates/typescript-pizzaz/src/widgets/package.json +30 -0
  103. package/templates/typescript-pizzaz/src/widgets/widget-manifest.json +253 -0
  104. package/templates/typescript-pizzaz/tsconfig.json +30 -0
  105. package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +0 -1
  106. package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +102 -56
  107. package/templates/typescript-starter/src/widgets/app/layout.tsx +6 -2
  108. package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +0 -702
  109. package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +0 -1260
  110. package/templates/typescript-auth/README.md +0 -402
  111. package/templates/typescript-auth/env.example +0 -25
  112. package/templates/typescript-auth/package.json +0 -36
  113. package/templates/typescript-auth/src/app.module.ts +0 -103
  114. package/templates/typescript-auth/src/db/database.ts +0 -160
  115. package/templates/typescript-auth/src/db/seed.ts +0 -374
  116. package/templates/typescript-auth/src/db/setup.ts +0 -87
  117. package/templates/typescript-auth/src/events/analytics.service.ts +0 -52
  118. package/templates/typescript-auth/src/events/notification.service.ts +0 -40
  119. package/templates/typescript-auth/src/filters/global-exception.filter.ts +0 -28
  120. package/templates/typescript-auth/src/guards/README.md +0 -75
  121. package/templates/typescript-auth/src/guards/jwt.guard.ts +0 -105
  122. package/templates/typescript-auth/src/health/database.health.ts +0 -41
  123. package/templates/typescript-auth/src/index.ts +0 -29
  124. package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +0 -24
  125. package/templates/typescript-auth/src/middleware/logging.middleware.ts +0 -42
  126. package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +0 -16
  127. package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +0 -114
  128. package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +0 -40
  129. package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +0 -284
  130. package/templates/typescript-auth/src/modules/auth/auth.module.ts +0 -16
  131. package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +0 -147
  132. package/templates/typescript-auth/src/modules/auth/auth.resources.ts +0 -84
  133. package/templates/typescript-auth/src/modules/auth/auth.tools.ts +0 -139
  134. package/templates/typescript-auth/src/modules/cart/cart.module.ts +0 -16
  135. package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +0 -95
  136. package/templates/typescript-auth/src/modules/cart/cart.resources.ts +0 -44
  137. package/templates/typescript-auth/src/modules/cart/cart.tools.ts +0 -277
  138. package/templates/typescript-auth/src/modules/orders/orders.module.ts +0 -16
  139. package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +0 -88
  140. package/templates/typescript-auth/src/modules/orders/orders.resources.ts +0 -48
  141. package/templates/typescript-auth/src/modules/orders/orders.tools.ts +0 -303
  142. package/templates/typescript-auth/src/modules/products/products.module.ts +0 -16
  143. package/templates/typescript-auth/src/modules/products/products.prompts.ts +0 -146
  144. package/templates/typescript-auth/src/modules/products/products.resources.ts +0 -98
  145. package/templates/typescript-auth/src/modules/products/products.tools.ts +0 -266
  146. package/templates/typescript-auth/src/pipes/validation.pipe.ts +0 -42
  147. package/templates/typescript-auth/src/services/database.service.ts +0 -90
  148. package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +0 -122
  149. package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +0 -116
  150. package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +0 -105
  151. package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +0 -139
  152. package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +0 -153
  153. package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +0 -86
  154. package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +0 -116
  155. package/templates/typescript-auth/src/widgets/app/categories/page.tsx +0 -134
  156. package/templates/typescript-auth/src/widgets/app/layout.tsx +0 -21
  157. package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +0 -129
  158. package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +0 -231
  159. package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +0 -225
  160. package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +0 -218
  161. package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +0 -121
  162. package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +0 -198
  163. package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +0 -187
  164. package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +0 -165
  165. package/templates/typescript-auth/src/widgets/next.config.js +0 -38
  166. package/templates/typescript-auth/src/widgets/package.json +0 -18
  167. package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +0 -169
  168. package/templates/typescript-auth/src/widgets/tsconfig.json +0 -28
  169. package/templates/typescript-auth/src/widgets/types/tool-data.ts +0 -141
  170. package/templates/typescript-auth/src/widgets/widget-manifest.json +0 -464
  171. package/templates/typescript-auth/tsconfig.json +0 -27
  172. package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +0 -701
  173. package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +0 -1260
  174. package/templates/typescript-auth-api-key/README.md +0 -485
  175. package/templates/typescript-auth-api-key/env.example +0 -17
  176. package/templates/typescript-auth-api-key/package.json +0 -21
  177. package/templates/typescript-auth-api-key/src/app.module.ts +0 -38
  178. package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +0 -47
  179. package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +0 -157
  180. package/templates/typescript-auth-api-key/src/index.ts +0 -47
  181. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +0 -12
  182. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +0 -73
  183. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +0 -60
  184. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +0 -71
  185. package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +0 -18
  186. package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +0 -155
  187. package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +0 -123
  188. package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +0 -133
  189. package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +0 -134
  190. package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +0 -14
  191. package/templates/typescript-auth-api-key/src/widgets/package.json +0 -24
  192. package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +0 -48
  193. package/templates/typescript-auth-api-key/tsconfig.json +0 -23
  194. package/templates/typescript-oauth/OAUTH_SETUP.md +0 -592
  195. package/templates/typescript-oauth/src/modules/demo/demo.module.ts +0 -16
  196. package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +0 -190
  197. package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +0 -133
  198. package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +0 -134
  199. package/templates/typescript-oauth/src/widgets/out/404.html +0 -1
  200. package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_buildManifest.js +0 -1
  201. package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_ssgManifest.js +0 -1
  202. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/117-eb57c7ef86f964a4.js +0 -2
  203. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/_not-found/page-dcb83ba3e4d0aafd.js +0 -1
  204. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-operations/page-b8913a740073ea8a.js +0 -1
  205. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-result/page-ddaaab2fce95dea2.js +0 -1
  206. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/layout-cbd3ebdc4ecc5247.js +0 -1
  207. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/fd9d1056-749e5812300142af.js +0 -1
  208. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
  209. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-76df43fcef3db344.js +0 -1
  210. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-app-f9c40224d04023c5.js +0 -1
  211. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
  212. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
  213. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  214. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/webpack-100b9e646d9c912e.js +0 -1
  215. package/templates/typescript-oauth/src/widgets/out/calculator-operations.html +0 -1
  216. package/templates/typescript-oauth/src/widgets/out/calculator-operations.txt +0 -7
  217. package/templates/typescript-oauth/src/widgets/out/calculator-result.html +0 -1
  218. package/templates/typescript-oauth/src/widgets/out/calculator-result.txt +0 -7
  219. package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +0 -133
  220. /package/templates/{typescript-auth-api-key → typescript-oauth}/src/health/system.health.ts +0 -0
  221. /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/next.config.js +0 -0
  222. /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/tsconfig.json +0 -0
@@ -1,266 +0,0 @@
1
- import {
2
- ToolDecorator as Tool,
3
- Widget,
4
- z,
5
- ExecutionContext,
6
- Injectable,
7
- UseMiddleware,
8
- UseInterceptors,
9
- UsePipes,
10
- UseFilters,
11
- Cache,
12
- RateLimit,
13
- } from 'nitrostack';
14
- import { DatabaseService } from '../../services/database.service.js';
15
- import { LoggingMiddleware } from '../../middleware/logging.middleware.js';
16
- import { TransformInterceptor } from '../../interceptors/transform.interceptor.js';
17
- import { ValidationPipe } from '../../pipes/validation.pipe.js';
18
- import { GlobalExceptionFilter } from '../../filters/global-exception.filter.js';
19
-
20
- /**
21
- * Products Tools
22
- *
23
- * Demonstrates all V3.1 features:
24
- * - Dependency Injection (@Injectable)
25
- * - Middleware (@UseMiddleware)
26
- * - Interceptors (@UseInterceptors)
27
- * - Pipes (@UsePipes)
28
- * - Exception Filters (@UseFilters)
29
- * - Caching (@Cache)
30
- * - Rate Limiting (@RateLimit)
31
- */
32
- @Injectable()
33
- export class ProductsTools {
34
- constructor(private database: DatabaseService) {}
35
-
36
- /**
37
- * Browse products - No authentication required
38
- * Demonstrates: Middleware, Interceptors, Pipes, Caching
39
- */
40
- @Tool({
41
- name: 'browse_products',
42
- description: 'Browse available products. Can filter by category, search by name, and paginate results. Returns products with their IDs which can be used with other tools like add_to_cart.',
43
- inputSchema: z.object({
44
- category: z.enum(['Electronics', 'Clothing', 'Home', 'Books', 'Sports', 'All']).default('All').describe('Filter by product category'),
45
- search: z.string().optional().describe('Search products by name (e.g., "apple" will find products containing "apple")'),
46
- page: z.number().min(1).default(1).describe('Page number for pagination'),
47
- limit: z.number().min(1).max(50).default(10).describe('Number of products per page'),
48
- }),
49
- examples: {
50
- request: {
51
- category: 'Beauty',
52
- page: 1,
53
- limit: 4
54
- },
55
- response: {
56
- products: [
57
- {
58
- id: 'prod-1',
59
- name: 'Essence Mascara Lash Princess',
60
- description: 'The Essence Mascara Lash Princess is a popular mascara known for its volumizing and lengthening effects.',
61
- price: 9.99,
62
- category: 'Beauty',
63
- stock: 99,
64
- image_url: 'https://cdn.dummyjson.com/product-images/beauty/essence-mascara-lash-princess/thumbnail.webp'
65
- },
66
- {
67
- id: 'prod-2',
68
- name: 'Eyeshadow Palette with Mirror',
69
- description: 'The Eyeshadow Palette offers a versatile range of eyeshadow shades for creating stunning eye looks.',
70
- price: 19.99,
71
- category: 'Beauty',
72
- stock: 34,
73
- image_url: 'https://cdn.dummyjson.com/product-images/beauty/eyeshadow-palette-with-mirror/thumbnail.webp'
74
- },
75
- {
76
- id: 'prod-3',
77
- name: 'Powder Canister',
78
- description: 'The Powder Canister is a finely milled setting powder designed to set makeup and control shine.',
79
- price: 14.99,
80
- category: 'Beauty',
81
- stock: 89,
82
- image_url: 'https://cdn.dummyjson.com/product-images/beauty/powder-canister/thumbnail.webp'
83
- },
84
- {
85
- id: 'prod-4',
86
- name: 'Red Lipstick',
87
- description: 'The Red Lipstick is a classic and bold choice for adding a pop of color to your lips.',
88
- price: 12.99,
89
- category: 'Beauty',
90
- stock: 91,
91
- image_url: 'https://cdn.dummyjson.com/product-images/beauty/red-lipstick/thumbnail.webp'
92
- }
93
- ],
94
- pagination: {
95
- page: 1,
96
- limit: 4,
97
- totalPages: 2,
98
- totalResults: 5
99
- }
100
- }
101
- }
102
- })
103
- @Widget('products-grid')
104
- @UseMiddleware(LoggingMiddleware)
105
- @UseInterceptors(TransformInterceptor)
106
- @UsePipes(ValidationPipe)
107
- @UseFilters(GlobalExceptionFilter)
108
- @Cache({ ttl: 60, key: (input) => `products:${input.category}:${input.search}:${input.page}` })
109
- async browseProducts(input: any, context: ExecutionContext) {
110
- // Apply defaults if not provided
111
- const category = input.category || 'All';
112
- const page = input.page || 1;
113
- const limit = input.limit || 10;
114
- const search = input.search || '';
115
-
116
- const offset = (page - 1) * limit;
117
-
118
- let query = 'SELECT * FROM products WHERE 1=1';
119
- const params: any[] = [];
120
-
121
- // Filter by category
122
- if (category && category !== 'All') {
123
- query += ' AND category = ?';
124
- params.push(category);
125
- }
126
-
127
- // Search by name
128
- if (search) {
129
- query += ' AND name LIKE ?';
130
- params.push(`%${search}%`);
131
- }
132
-
133
- // Add pagination
134
- query += ' ORDER BY name LIMIT ? OFFSET ?';
135
- params.push(limit, offset);
136
-
137
- const products = this.database.query(query, params);
138
-
139
- // Get total count
140
- let countQuery = 'SELECT COUNT(*) as count FROM products WHERE 1=1';
141
- const countParams: any[] = [];
142
-
143
- if (category && category !== 'All') {
144
- countQuery += ' AND category = ?';
145
- countParams.push(category);
146
- }
147
-
148
- if (search) {
149
- countQuery += ' AND name LIKE ?';
150
- countParams.push(`%${search}%`);
151
- }
152
-
153
- const result = this.database.queryOne<{ count: number }>(countQuery, countParams);
154
- const count = result?.count || 0;
155
- const totalPages = Math.ceil(count / limit);
156
-
157
- context.logger.info(`Browsing products: category=${category}, search=${search}, page=${page}, found=${products.length} products`);
158
-
159
- return {
160
- products,
161
- pagination: {
162
- page,
163
- limit,
164
- total: count,
165
- totalPages,
166
- hasMore: page < totalPages,
167
- },
168
- };
169
- }
170
-
171
- /**
172
- * Get product details - No authentication required
173
- * Demonstrates: All features + Rate Limiting
174
- */
175
- @Tool({
176
- name: 'get_product_details',
177
- description: 'Get detailed information about a specific product by ID. Use this if you need more details about a product from browse_products results.',
178
- inputSchema: z.object({
179
- product_id: z.string().describe('The ID of the product to retrieve (e.g., "prod-3" from browse_products results)'),
180
- }),
181
- examples: {
182
- request: {
183
- product_id: 'prod-1'
184
- },
185
- response: {
186
- product: {
187
- id: 'prod-1',
188
- name: 'Essence Mascara Lash Princess',
189
- description: 'The Essence Mascara Lash Princess is a popular mascara known for its volumizing and lengthening effects.',
190
- price: 9.99,
191
- category: 'Beauty',
192
- stock: 99,
193
- image_url: 'https://cdn.dummyjson.com/product-images/beauty/essence-mascara-lash-princess/thumbnail.webp'
194
- },
195
- availability: 'In Stock',
196
- stockMessage: 'Available'
197
- }
198
- }
199
- })
200
- @Widget('product-card')
201
- @UseMiddleware(LoggingMiddleware)
202
- @UseInterceptors(TransformInterceptor)
203
- @UsePipes(ValidationPipe)
204
- @UseFilters(GlobalExceptionFilter)
205
- @Cache({ ttl: 300, key: (input) => `product:${input.product_id}` }) // Cache for 5 minutes
206
- @RateLimit({ requests: 100, window: '1m' }) // 100 requests per minute
207
- async getProductDetails(input: any, context: ExecutionContext) {
208
- const product = this.database.queryOne(`SELECT * FROM products WHERE id = ?`, [input.product_id]);
209
-
210
- if (!product) {
211
- throw new Error(`Product with ID ${input.product_id} not found`);
212
- }
213
-
214
- context.logger.info(`Retrieved details for product: ${(product as any).name}`);
215
-
216
- return {
217
- product,
218
- availability: (product as any).stock > 0 ? 'In Stock' : 'Out of Stock',
219
- stockMessage: (product as any).stock > 10
220
- ? 'Available'
221
- : (product as any).stock > 0
222
- ? `Only ${(product as any).stock} left!`
223
- : 'Currently unavailable',
224
- };
225
- }
226
-
227
- /**
228
- * Get product categories - No authentication required
229
- * Demonstrates: Simple caching
230
- */
231
- @Tool({
232
- name: 'get_categories',
233
- description: 'Get all available product categories.',
234
- inputSchema: z.object({}),
235
- examples: {
236
- request: {},
237
- response: {
238
- categories: [
239
- { name: 'Beauty', productCount: 5 },
240
- { name: 'Fragrances', productCount: 5 },
241
- { name: 'Furniture', productCount: 5 },
242
- { name: 'Groceries', productCount: 5 }
243
- ]
244
- }
245
- }
246
- })
247
- @Widget('categories')
248
- @UseMiddleware(LoggingMiddleware)
249
- @UseInterceptors(TransformInterceptor)
250
- @Cache({ ttl: 300 }) // Cache for 5 minutes
251
- async getCategories(input: any, context: ExecutionContext) {
252
- const categories = this.database.query(`
253
- SELECT DISTINCT category, COUNT(*) as count
254
- FROM products
255
- GROUP BY category
256
- ORDER BY category
257
- `);
258
-
259
- return {
260
- categories: categories.map((c: any) => ({
261
- name: c.category,
262
- productCount: c.count,
263
- })),
264
- };
265
- }
266
- }
@@ -1,42 +0,0 @@
1
- import { Pipe, PipeInterface, ArgumentMetadata } from 'nitrostack';
2
-
3
- /**
4
- * Validation Pipe
5
- *
6
- * Validates and sanitizes input data
7
- */
8
- @Pipe()
9
- export class ValidationPipe implements PipeInterface {
10
- transform(value: any, metadata: ArgumentMetadata) {
11
- if (!value || typeof value !== 'object') {
12
- throw new Error('Input must be an object');
13
- }
14
-
15
- // Sanitize strings
16
- const sanitized = this.sanitizeObject(value);
17
-
18
- return sanitized;
19
- }
20
-
21
- private sanitizeObject(obj: any): any {
22
- if (typeof obj !== 'object' || obj === null) {
23
- return obj;
24
- }
25
-
26
- const sanitized: any = Array.isArray(obj) ? [] : {};
27
-
28
- for (const key in obj) {
29
- if (typeof obj[key] === 'string') {
30
- // Trim and sanitize strings
31
- sanitized[key] = obj[key].trim();
32
- } else if (typeof obj[key] === 'object') {
33
- sanitized[key] = this.sanitizeObject(obj[key]);
34
- } else {
35
- sanitized[key] = obj[key];
36
- }
37
- }
38
-
39
- return sanitized;
40
- }
41
- }
42
-
@@ -1,90 +0,0 @@
1
- import { Injectable } from 'nitrostack';
2
- import Database from 'better-sqlite3';
3
- import { getDatabase } from '../db/database.js';
4
-
5
- /**
6
- * Database Service
7
- *
8
- * Provides database access with dependency injection
9
- */
10
- @Injectable()
11
- export class DatabaseService {
12
- private db: Database.Database;
13
-
14
- constructor() {
15
- this.db = getDatabase();
16
- }
17
-
18
- /**
19
- * Execute a query
20
- */
21
- query<T = any>(sql: string, params: any[] = []): T[] {
22
- const stmt = this.db.prepare(sql);
23
- // better-sqlite3 expects individual parameters, not an array
24
- if (params.length === 0) {
25
- return stmt.all() as T[];
26
- }
27
- return stmt.all(...params) as T[];
28
- }
29
-
30
- /**
31
- * Execute a query and get first result
32
- */
33
- queryOne<T = any>(sql: string, params: any[] = []): T | null {
34
- const stmt = this.db.prepare(sql);
35
- // better-sqlite3 expects individual parameters, not an array
36
- if (params.length === 0) {
37
- return (stmt.get() as T) || null;
38
- }
39
- return (stmt.get(...params) as T) || null;
40
- }
41
-
42
- /**
43
- * Insert a record
44
- */
45
- insert(table: string, data: Record<string, any>): { lastInsertRowid: number } {
46
- const keys = Object.keys(data);
47
- const values = Object.values(data);
48
- const placeholders = keys.map(() => '?').join(', ');
49
-
50
- const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;
51
- const stmt = this.db.prepare(sql);
52
- return stmt.run(...values) as any;
53
- }
54
-
55
- /**
56
- * Update a record
57
- */
58
- update(table: string, data: Record<string, any>, where: Record<string, any>): { changes: number } {
59
- const setClause = Object.keys(data).map(k => `${k} = ?`).join(', ');
60
- const whereClause = Object.keys(where).map(k => `${k} = ?`).join(' AND ');
61
-
62
- const sql = `UPDATE ${table} SET ${setClause} WHERE ${whereClause}`;
63
- const stmt = this.db.prepare(sql);
64
- return stmt.run(...Object.values(data), ...Object.values(where)) as any;
65
- }
66
-
67
- /**
68
- * Delete a record
69
- */
70
- delete(table: string, where: Record<string, any>): { changes: number } {
71
- const whereClause = Object.keys(where).map(k => `${k} = ?`).join(' AND ');
72
-
73
- const sql = `DELETE FROM ${table} WHERE ${whereClause}`;
74
- const stmt = this.db.prepare(sql);
75
- return stmt.run(...Object.values(where)) as any;
76
- }
77
-
78
- /**
79
- * Check database connectivity
80
- */
81
- async ping(): Promise<boolean> {
82
- try {
83
- this.db.prepare('SELECT 1').get();
84
- return true;
85
- } catch {
86
- return false;
87
- }
88
- }
89
- }
90
-
@@ -1,122 +0,0 @@
1
- 'use client';
2
-
3
- import { withToolData } from 'nitrostack/widgets';
4
- import * as styles from '../../styles/ecommerce';
5
-
6
- interface AddToCartData {
7
- message: string;
8
- product_id?: string;
9
- product_name?: string;
10
- price?: number;
11
- quantity?: number;
12
- image_url?: string;
13
- cartItemCount?: number;
14
- }
15
-
16
- function AddToCartWidget({ data }: { data: AddToCartData }) {
17
- const { message, product_name, price, quantity, image_url, cartItemCount } = data;
18
-
19
- return (
20
- <div style={styles.containerStyle}>
21
- <div style={{
22
- ...styles.cardStyle,
23
- maxWidth: '500px',
24
- margin: '0 auto',
25
- }}>
26
- <div style={{
27
- textAlign: 'center',
28
- marginBottom: styles.spacing.xl,
29
- }}>
30
- <div style={{
31
- width: '60px',
32
- height: '60px',
33
- margin: '0 auto 16px',
34
- borderRadius: styles.borderRadius.full,
35
- background: styles.colors.success,
36
- display: 'flex',
37
- alignItems: 'center',
38
- justifyContent: 'center',
39
- fontSize: '28px',
40
- }}>
41
-
42
- </div>
43
- <h2 style={{
44
- fontSize: styles.typography.fontSize.xl,
45
- fontWeight: styles.typography.fontWeight.bold,
46
- color: styles.colors.gray[900],
47
- marginBottom: styles.spacing.sm,
48
- }}>
49
- {message}
50
- </h2>
51
- <p style={{
52
- fontSize: styles.typography.fontSize.base,
53
- color: styles.colors.gray[600],
54
- }}>
55
- You now have {cartItemCount || 1} {cartItemCount === 1 ? 'item' : 'items'} in your cart
56
- </p>
57
- </div>
58
-
59
- {product_name && (
60
- <div style={{
61
- display: 'flex',
62
- gap: styles.spacing.md,
63
- padding: styles.spacing.lg,
64
- background: styles.colors.gray[50],
65
- borderRadius: styles.borderRadius.md,
66
- }}>
67
- {image_url && (
68
- <div style={{
69
- width: '80px',
70
- height: '80px',
71
- flexShrink: 0,
72
- borderRadius: styles.borderRadius.md,
73
- overflow: 'hidden',
74
- background: styles.colors.white,
75
- }}>
76
- <img
77
- src={image_url}
78
- alt={product_name}
79
- style={{
80
- width: '100%',
81
- height: '100%',
82
- objectFit: 'cover',
83
- }}
84
- />
85
- </div>
86
- )}
87
-
88
- <div style={{ flex: 1 }}>
89
- <div style={{
90
- fontSize: styles.typography.fontSize.base,
91
- fontWeight: styles.typography.fontWeight.semibold,
92
- color: styles.colors.gray[900],
93
- marginBottom: styles.spacing.xs,
94
- }}>
95
- {product_name}
96
- </div>
97
- <div style={{
98
- display: 'flex',
99
- alignItems: 'center',
100
- gap: styles.spacing.md,
101
- }}>
102
- {price && (
103
- <div style={styles.priceStyle}>
104
- ${price.toFixed(2)}
105
- </div>
106
- )}
107
- {quantity && (
108
- <div style={styles.badgeStyle}>
109
- Qty: {quantity}
110
- </div>
111
- )}
112
- </div>
113
- </div>
114
- </div>
115
- )}
116
- </div>
117
- </div>
118
- );
119
- }
120
-
121
- export default withToolData<AddToCartData>(AddToCartWidget);
122
-
@@ -1,116 +0,0 @@
1
- 'use client';
2
-
3
- import { withToolData } from 'nitrostack/widgets';
4
- import * as styles from '../../styles/ecommerce';
5
-
6
- interface AddressAddedData {
7
- message: string;
8
- addressId: string;
9
- isDefault?: boolean;
10
- }
11
-
12
- function AddressAddedWidget({ data }: { data: AddressAddedData }) {
13
- const { message, addressId, isDefault } = data;
14
-
15
- if (!addressId) {
16
- return (
17
- <div style={styles.containerStyle}>
18
- <div style={styles.emptyStateStyle}>
19
- <p style={styles.metaTextStyle}>Loading...</p>
20
- </div>
21
- </div>
22
- );
23
- }
24
-
25
- return (
26
- <div style={styles.containerStyle}>
27
- <div style={{
28
- ...styles.cardStyle,
29
- maxWidth: '500px',
30
- margin: '0 auto',
31
- }}>
32
- <div style={{
33
- textAlign: 'center',
34
- marginBottom: styles.spacing.xl,
35
- }}>
36
- <div style={{
37
- width: '60px',
38
- height: '60px',
39
- margin: '0 auto 16px',
40
- borderRadius: styles.borderRadius.full,
41
- background: styles.colors.success,
42
- display: 'flex',
43
- alignItems: 'center',
44
- justifyContent: 'center',
45
- fontSize: '28px',
46
- }}>
47
-
48
- </div>
49
- <h2 style={{
50
- fontSize: styles.typography.fontSize.xl,
51
- fontWeight: styles.typography.fontWeight.bold,
52
- color: styles.colors.gray[900],
53
- marginBottom: styles.spacing.sm,
54
- }}>
55
- {message}
56
- </h2>
57
- </div>
58
-
59
- <div style={{
60
- background: styles.colors.gray[50],
61
- borderRadius: styles.borderRadius.md,
62
- padding: styles.spacing.lg,
63
- marginBottom: styles.spacing.md,
64
- }}>
65
- <div style={{
66
- fontSize: styles.typography.fontSize.sm,
67
- color: styles.colors.gray[500],
68
- marginBottom: styles.spacing.xs,
69
- textTransform: 'uppercase',
70
- letterSpacing: '0.5px',
71
- fontWeight: styles.typography.fontWeight.semibold,
72
- }}>
73
- Address Reference
74
- </div>
75
- <div style={{
76
- fontSize: styles.typography.fontSize.sm,
77
- fontWeight: styles.typography.fontWeight.medium,
78
- color: styles.colors.gray[900],
79
- fontFamily: 'monospace',
80
- wordBreak: 'break-all',
81
- }}>
82
- {addressId}
83
- </div>
84
- </div>
85
-
86
- {isDefault && (
87
- <div style={{
88
- textAlign: 'center',
89
- padding: styles.spacing.md,
90
- background: `linear-gradient(135deg, ${styles.colors.primary} 0%, ${styles.colors.primaryHover} 100%)`,
91
- color: styles.colors.black,
92
- borderRadius: styles.borderRadius.md,
93
- fontWeight: styles.typography.fontWeight.bold,
94
- fontSize: styles.typography.fontSize.sm,
95
- }}>
96
- ⭐ Default Shipping Address
97
- </div>
98
- )}
99
-
100
- <div style={{
101
- marginTop: styles.spacing.md,
102
- padding: styles.spacing.md,
103
- background: `${styles.colors.success}15`,
104
- borderRadius: styles.borderRadius.md,
105
- fontSize: styles.typography.fontSize.sm,
106
- color: styles.colors.gray[700],
107
- textAlign: 'center',
108
- }}>
109
- 📦 Ready for deliveries
110
- </div>
111
- </div>
112
- </div>
113
- );
114
- }
115
-
116
- export default withToolData<AddressAddedData>(AddressAddedWidget);