nitrostack 1.0.32 → 1.0.34
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/dist/cli/build-widgets.mjs +165 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +33 -7
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/core/component.d.ts +7 -1
- package/dist/core/component.d.ts.map +1 -1
- package/dist/core/component.js +49 -4
- package/dist/core/component.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +9 -3
- package/dist/core/server.js.map +1 -1
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +16 -1
- package/dist/core/tool.js.map +1 -1
- package/dist/core/transports/streamable-http.d.ts.map +1 -1
- package/dist/core/transports/streamable-http.js +5 -23
- package/dist/core/transports/streamable-http.js.map +1 -1
- package/dist/ui-next/index.d.ts +1 -0
- package/dist/ui-next/index.d.ts.map +1 -1
- package/dist/ui-next/index.js +126 -125
- package/dist/ui-next/index.js.map +1 -1
- package/package.json +4 -3
- package/src/studio/components/WidgetRenderer.tsx +24 -15
- package/templates/typescript-auth/src/modules/products/products.tools.ts +29 -29
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ToolDecorator as Tool,
|
|
3
|
-
Widget,
|
|
4
|
-
z,
|
|
1
|
+
import {
|
|
2
|
+
ToolDecorator as Tool,
|
|
3
|
+
Widget,
|
|
4
|
+
z,
|
|
5
5
|
ExecutionContext,
|
|
6
6
|
Injectable,
|
|
7
7
|
UseMiddleware,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from 'nitrostack';
|
|
14
14
|
import { DatabaseService } from '../../services/database.service.js';
|
|
15
15
|
import { LoggingMiddleware } from '../../middleware/logging.middleware.js';
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
import { ValidationPipe } from '../../pipes/validation.pipe.js';
|
|
18
18
|
import { GlobalExceptionFilter } from '../../filters/global-exception.filter.js';
|
|
19
19
|
|
|
@@ -31,7 +31,7 @@ import { GlobalExceptionFilter } from '../../filters/global-exception.filter.js'
|
|
|
31
31
|
*/
|
|
32
32
|
@Injectable()
|
|
33
33
|
export class ProductsTools {
|
|
34
|
-
constructor(private database: DatabaseService) {}
|
|
34
|
+
constructor(private database: DatabaseService) { }
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Browse products - No authentication required
|
|
@@ -102,7 +102,7 @@ export class ProductsTools {
|
|
|
102
102
|
})
|
|
103
103
|
@Widget('products-grid')
|
|
104
104
|
@UseMiddleware(LoggingMiddleware)
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
@UsePipes(ValidationPipe)
|
|
107
107
|
@UseFilters(GlobalExceptionFilter)
|
|
108
108
|
@Cache({ ttl: 60, key: (input) => `products:${input.category}:${input.search}:${input.page}` })
|
|
@@ -112,50 +112,50 @@ export class ProductsTools {
|
|
|
112
112
|
const page = input.page || 1;
|
|
113
113
|
const limit = input.limit || 10;
|
|
114
114
|
const search = input.search || '';
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
const offset = (page - 1) * limit;
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
let query = 'SELECT * FROM products WHERE 1=1';
|
|
119
119
|
const params: any[] = [];
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
// Filter by category
|
|
122
122
|
if (category && category !== 'All') {
|
|
123
123
|
query += ' AND category = ?';
|
|
124
124
|
params.push(category);
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
// Search by name
|
|
128
128
|
if (search) {
|
|
129
129
|
query += ' AND name LIKE ?';
|
|
130
130
|
params.push(`%${search}%`);
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
// Add pagination
|
|
134
134
|
query += ' ORDER BY name LIMIT ? OFFSET ?';
|
|
135
135
|
params.push(limit, offset);
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
const products = this.database.query(query, params);
|
|
138
|
-
|
|
138
|
+
|
|
139
139
|
// Get total count
|
|
140
140
|
let countQuery = 'SELECT COUNT(*) as count FROM products WHERE 1=1';
|
|
141
141
|
const countParams: any[] = [];
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
if (category && category !== 'All') {
|
|
144
144
|
countQuery += ' AND category = ?';
|
|
145
145
|
countParams.push(category);
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
if (search) {
|
|
149
149
|
countQuery += ' AND name LIKE ?';
|
|
150
150
|
countParams.push(`%${search}%`);
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
const result = this.database.queryOne<{ count: number }>(countQuery, countParams);
|
|
154
154
|
const count = result?.count || 0;
|
|
155
155
|
const totalPages = Math.ceil(count / limit);
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
context.logger.info(`Browsing products: category=${category}, search=${search}, page=${page}, found=${products.length} products`);
|
|
158
|
-
|
|
158
|
+
|
|
159
159
|
return {
|
|
160
160
|
products,
|
|
161
161
|
pagination: {
|
|
@@ -199,27 +199,27 @@ export class ProductsTools {
|
|
|
199
199
|
})
|
|
200
200
|
@Widget('product-card')
|
|
201
201
|
@UseMiddleware(LoggingMiddleware)
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
@UsePipes(ValidationPipe)
|
|
204
204
|
@UseFilters(GlobalExceptionFilter)
|
|
205
205
|
@Cache({ ttl: 300, key: (input) => `product:${input.product_id}` }) // Cache for 5 minutes
|
|
206
206
|
@RateLimit({ requests: 100, window: '1m' }) // 100 requests per minute
|
|
207
207
|
async getProductDetails(input: any, context: ExecutionContext) {
|
|
208
208
|
const product = this.database.queryOne(`SELECT * FROM products WHERE id = ?`, [input.product_id]);
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
if (!product) {
|
|
211
211
|
throw new Error(`Product with ID ${input.product_id} not found`);
|
|
212
212
|
}
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
context.logger.info(`Retrieved details for product: ${(product as any).name}`);
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
return {
|
|
217
217
|
product,
|
|
218
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!`
|
|
219
|
+
stockMessage: (product as any).stock > 10
|
|
220
|
+
? 'Available'
|
|
221
|
+
: (product as any).stock > 0
|
|
222
|
+
? `Only ${(product as any).stock} left!`
|
|
223
223
|
: 'Currently unavailable',
|
|
224
224
|
};
|
|
225
225
|
}
|
|
@@ -246,7 +246,7 @@ export class ProductsTools {
|
|
|
246
246
|
})
|
|
247
247
|
@Widget('categories')
|
|
248
248
|
@UseMiddleware(LoggingMiddleware)
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
@Cache({ ttl: 300 }) // Cache for 5 minutes
|
|
251
251
|
async getCategories(input: any, context: ExecutionContext) {
|
|
252
252
|
const categories = this.database.query(`
|
|
@@ -255,7 +255,7 @@ export class ProductsTools {
|
|
|
255
255
|
GROUP BY category
|
|
256
256
|
ORDER BY category
|
|
257
257
|
`);
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
return {
|
|
260
260
|
categories: categories.map((c: any) => ({
|
|
261
261
|
name: c.category,
|