@@ -180,69 +180,53 @@ async getList(
180180 },
181181 res : Response ,
182182) {
183- try {
184- const Model = this .app .getModel (' ModelName' );
185- const { name, status } = req .appInfo .query ;
186- const { skip, limit, page } = req .appInfo .pagination ;
187-
188- const query: any = {};
189- if (name ) {
190- query .name = new RegExp (name , ' i' );
191- }
192- if (status ) {
193- query .status = status ;
194- }
195-
196- const [items, total] = await Promise .all ([
197- Model .find (query ).skip (skip ).limit (limit ),
198- Model .countDocuments (query ),
199- ]);
200-
201- const publicItems = await Promise .all (
202- items .map (async (item : any ) => await item .getPublic ())
203- );
183+ const Model = this .app .getModel (' ModelName' );
184+ const { name, status } = req .appInfo .query ;
185+ const { skip, limit, page } = req .appInfo .pagination ;
204186
205- return res .status (200 ).json ({
206- data: publicItems ,
207- total ,
208- page ,
209- limit ,
210- });
211- } catch (error ) {
212- console .error (' Error fetching items:' , error );
213- return res .status (500 ).json ({
214- message: req .appInfo ?.i18n ?.t (' common.serverError' ) || ' Server error' ,
215- data: null ,
216- });
187+ const query: any = {};
188+ if (name ) {
189+ query .name = new RegExp (name , ' i' );
190+ }
191+ if (status ) {
192+ query .status = status ;
217193 }
194+
195+ const [items, total] = await Promise .all ([
196+ Model .find (query ).skip (skip ).limit (limit ),
197+ Model .countDocuments (query ),
198+ ]);
199+
200+ const publicItems = await Promise .all (
201+ items .map (async (item : any ) => await item .getPublic ())
202+ );
203+
204+ return res .status (200 ).json ({
205+ data: publicItems ,
206+ total ,
207+ page ,
208+ limit ,
209+ });
218210}
219211```
220212
221213### GET by Slug Handler
222214``` typescript
223215async getBySlug (req : FrameworkRequest , res : Response ) {
224- try {
225- const Model = this .app .getModel (' ModelName' );
226- const { slug } = req .params ;
227-
228- const item = await Model .findOne ({ slug });
229- if (! item ) {
230- return res .status (404 ).json ({
231- message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
232- data: null ,
233- });
234- }
216+ const Model = this .app .getModel (' ModelName' );
217+ const { slug } = req .params ;
235218
236- return res .status (200 ).json ({
237- data: await item .getPublic (),
238- });
239- } catch (error ) {
240- console .error (' Error fetching item:' , error );
241- return res .status (500 ).json ({
242- message: req .appInfo ?.i18n ?.t (' common.serverError' ) || ' Server error' ,
219+ const item = await Model .findOne ({ slug });
220+ if (! item ) {
221+ return res .status (404 ).json ({
222+ message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
243223 data: null ,
244224 });
245225 }
226+
227+ return res .status (200 ).json ({
228+ data: await item .getPublic (),
229+ });
246230}
247231```
248232
@@ -260,70 +244,62 @@ async create(
260244 },
261245 res : Response ,
262246) {
263- try {
264- const Model = this .app .getModel (' ModelName' );
265- const { name, description, image } = req .appInfo .request ;
247+ const Model = this .app .getModel (' ModelName' );
248+ const { name, description, image } = req .appInfo .request ;
249+
250+ // Validation
251+ const existingItem = await Model .findOne ({ name: name [0 ] });
252+ if (existingItem ) {
253+ return res .status (409 ).json ({
254+ message: req .appInfo .i18n ?.t (' model.nameExistsMessage' , { name: name [0 ] }) ||
255+ ` Item with name "${name [0 ]}" already exists ` ,
256+ errors: {
257+ name: req .appInfo .i18n ?.t (' model.nameExists' ) || ' Name already exists' ,
258+ },
259+ data: null ,
260+ });
261+ }
266262
267- // Validation
268- const existingItem = await Model .findOne ({ name: name [0 ] });
269- if (existingItem ) {
270- return res .status (409 ).json ({
271- message: req .appInfo .i18n ?.t (' model.nameExistsMessage' , { name: name [0 ] }) ||
272- ` Item with name "${name [0 ]}" already exists ` ,
263+ // Handle file upload if needed
264+ let imageId = null ;
265+ if (image ?.[0 ]) {
266+ const FileModel = this .app .getModel (' File' );
267+
268+ if (! image [0 ].mimetype ?.includes (' image' )) {
269+ return res .status (400 ).json ({
273270 errors: {
274- name : req .appInfo .i18n ?.t (' model.nameExists ' ) || ' Name already exists ' ,
271+ image : req .appInfo .i18n ?.t (' validation.fileNotImage ' ) || ' File must be an image ' ,
275272 },
276273 data: null ,
277274 });
278275 }
279276
280- // Handle file upload if needed
281- let imageId = null ;
282- if (image ?.[0 ]) {
283- const FileModel = this .app .getModel (' File' );
284-
285- if (! image [0 ].mimetype ?.includes (' image' )) {
286- return res .status (400 ).json ({
287- errors: {
288- image: req .appInfo .i18n ?.t (' validation.fileNotImage' ) || ' File must be an image' ,
289- },
290- data: null ,
291- });
292- }
293-
294- const fileMongo = await FileModel .uploadFile (
295- image [0 ].filepath ,
296- image [0 ].originalFilename ,
297- image [0 ].mimetype ,
298- ' folder-name' ,
299- );
300-
301- if (! fileMongo ) {
302- return res .status (500 ).json ({
303- message: req .appInfo .i18n ?.t (' common.fileUploadFailed' ) || ' File upload failed' ,
304- data: null ,
305- });
306- }
307-
308- imageId = fileMongo ._id ;
309- }
277+ const fileMongo = await FileModel .uploadFile (
278+ image [0 ].filepath ,
279+ image [0 ].originalFilename ,
280+ image [0 ].mimetype ,
281+ ' folder-name' ,
282+ );
310283
311- const newItem = await Model .create ({
312- name: name [0 ],
313- description: description ?.[0 ],
314- image: imageId ,
315- });
284+ if (! fileMongo ) {
285+ return res .status (500 ).json ({
286+ message: req .appInfo .i18n ?.t (' common.fileUploadFailed' ) || ' File upload failed' ,
287+ data: null ,
288+ });
289+ }
316290
317- return res .status (201 ).json ({
318- data: await newItem .getPublic (),
319- });
320- } catch (error ) {
321- console .error (' Error creating item:' , error );
322- return res .status (500 ).json ({
323- message: req .appInfo ?.i18n ?.t (' common.serverError' ) || ' Server error' ,
324- data: null ,
325- });
291+ imageId = fileMongo ._id ;
326292 }
293+
294+ const newItem = await Model .create ({
295+ name: name [0 ],
296+ description: description ?.[0 ],
297+ image: imageId ,
298+ });
299+
300+ return res .status (201 ).json ({
301+ data: await newItem .getPublic (),
302+ });
327303}
328304```
329305
@@ -341,98 +317,82 @@ async update(
341317 },
342318 res : Response ,
343319) {
344- try {
345- const Model = this .app .getModel (' ModelName' );
346- const { slug } = req .params ;
347- const { name, description, image } = req .appInfo .request ;
348-
349- const item = await Model .findOne ({ slug });
350- if (! item ) {
351- return res .status (404 ).json ({
352- message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
353- data: null ,
354- });
355- }
320+ const Model = this .app .getModel (' ModelName' );
321+ const { slug } = req .params ;
322+ const { name, description, image } = req .appInfo .request ;
323+
324+ const item = await Model .findOne ({ slug });
325+ if (! item ) {
326+ return res .status (404 ).json ({
327+ message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
328+ data: null ,
329+ });
330+ }
356331
357- // Check for duplicate name if updating
358- if (name ?.[0 ] && name [0 ] !== item .name ) {
359- const existingItem = await Model .findOne ({
360- name: name [0 ],
361- slug: { $ne: slug },
362- });
332+ // Check for duplicate name if updating
333+ if (name ?.[0 ] && name [0 ] !== item .name ) {
334+ const existingItem = await Model .findOne ({
335+ name: name [0 ],
336+ slug: { $ne: slug },
337+ });
363338
364- if (existingItem ) {
365- return res .status (409 ).json ({
366- message: req .appInfo .i18n ?.t (' model.nameExistsMessage' , { name: name [0 ] }) ||
367- ` Item with name "${name [0 ]}" already exists ` ,
368- errors: {
369- name: req .appInfo .i18n ?.t (' model.nameExists' ) || ' Name already exists' ,
370- },
371- data: null ,
372- });
373- }
339+ if (existingItem ) {
340+ return res .status (409 ).json ({
341+ message: req .appInfo .i18n ?.t (' model.nameExistsMessage' , { name: name [0 ] }) ||
342+ ` Item with name "${name [0 ]}" already exists ` ,
343+ errors: {
344+ name: req .appInfo .i18n ?.t (' model.nameExists' ) || ' Name already exists' ,
345+ },
346+ data: null ,
347+ });
374348 }
349+ }
375350
376- // Update fields
377- const updateData: any = {};
378- if (name ?.[0 ]) {
379- updateData .name = name [0 ];
380- }
381- if (description ?.[0 ]) {
382- updateData .description = description [0 ];
383- }
351+ // Update fields
352+ const updateData: any = {};
353+ if (name ?.[0 ]) {
354+ updateData .name = name [0 ];
355+ }
356+ if (description ?.[0 ]) {
357+ updateData .description = description [0 ];
358+ }
384359
385- // Handle image upload if provided
386- if (image ?.[0 ]) {
387- // ... file upload logic similar to create
388- }
360+ // Handle image upload if provided
361+ if (image ?.[0 ]) {
362+ // ... file upload logic similar to create
363+ }
389364
390- const updatedItem = await Model .findOneAndUpdate (
391- { slug },
392- updateData ,
393- { new: true }
394- );
365+ const updatedItem = await Model .findOneAndUpdate (
366+ { slug },
367+ updateData ,
368+ { new: true }
369+ );
395370
396- return res .status (200 ).json ({
397- data: await updatedItem .getPublic (),
398- });
399- } catch (error ) {
400- console .error (' Error updating item:' , error );
401- return res .status (500 ).json ({
402- message: req .appInfo ?.i18n ?.t (' common.serverError' ) || ' Server error' ,
403- data: null ,
404- });
405- }
371+ return res .status (200 ).json ({
372+ data: await updatedItem .getPublic (),
373+ });
406374}
407375```
408376
409377### DELETE Handler
410378``` typescript
411379async delete (req : FrameworkRequest , res : Response ) {
412- try {
413- const Model = this .app .getModel (' ModelName' );
414- const { slug } = req .params ;
415-
416- const item = await Model .findOne ({ slug });
417- if (! item ) {
418- return res .status (404 ).json ({
419- message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
420- data: null ,
421- });
422- }
423-
424- await Model .findOneAndDelete ({ slug });
380+ const Model = this .app .getModel (' ModelName' );
381+ const { slug } = req .params ;
425382
426- return res .status (200 ).json ({
427- data: null ,
428- });
429- } catch (error ) {
430- console .error (' Error deleting item:' , error );
431- return res .status (500 ).json ({
432- message: req .appInfo ?.i18n ?.t (' common.serverError' ) || ' Server error' ,
383+ const item = await Model .findOne ({ slug });
384+ if (! item ) {
385+ return res .status (404 ).json ({
386+ message: req .appInfo ?.i18n ?.t (' model.notFound' ) || ' Item not found' ,
433387 data: null ,
434388 });
435389 }
390+
391+ await Model .findOneAndDelete ({ slug });
392+
393+ return res .status (200 ).json ({
394+ data: null ,
395+ });
436396}
437397```
438398
@@ -444,7 +404,9 @@ async delete(req: FrameworkRequest, res: Response) {
444404- Include internationalization support
445405
446406### 2. Error Handling
447- - Always wrap handlers in try-catch blocks
407+ - Framework handles errors automatically (see ` .clinerules/07-ErrorHandling.md ` )
408+ - Do NOT wrap main handler logic in try-catch blocks
409+ - Only use try-catch for specific non-critical operations (external APIs, logging, etc.)
448410- Use appropriate HTTP status codes
449411- Provide meaningful error messages
450412- Use field-specific errors in the ` errors ` object
0 commit comments