From 4e31b71a56b1a9755dca598b0929a25cec81b270 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:49:53 -0600 Subject: [PATCH 01/19] Update DeviceStatusFirebaseController with improved route and API operation documentation --- .../controllers/devices-status.controller.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/common/src/firebase/devices-status/controllers/devices-status.controller.ts b/libs/common/src/firebase/devices-status/controllers/devices-status.controller.ts index 4a3458d..5a79b1c 100644 --- a/libs/common/src/firebase/devices-status/controllers/devices-status.controller.ts +++ b/libs/common/src/firebase/devices-status/controllers/devices-status.controller.ts @@ -1,13 +1,14 @@ import { Controller, Post, Param } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { AddDeviceStatusDto } from '../dtos/add.devices-status.dto'; import { DeviceStatusFirebaseService } from '../services/devices-status.service'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Device Status Firebase Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'device-status-firebase', + path: ControllerRoute.DEVICE_STATUS_FIREBASE.ROUTE, }) export class DeviceStatusFirebaseController { constructor( @@ -16,6 +17,13 @@ export class DeviceStatusFirebaseController { @ApiBearerAuth() @Post(':deviceTuyaUuid') + @ApiOperation({ + summary: + ControllerRoute.DEVICE_STATUS_FIREBASE.ACTIONS.ADD_DEVICE_STATUS_SUMMARY, + description: + ControllerRoute.DEVICE_STATUS_FIREBASE.ACTIONS + .ADD_DEVICE_STATUS_DESCRIPTION, + }) async addDeviceStatus( @Param('deviceTuyaUuid') deviceTuyaUuid: string, ): Promise { From f1da846bb5e9311e1829419eb1e4642ce82c63be Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:02 -0600 Subject: [PATCH 02/19] Enhance Swagger Documentation in UserAuthController --- src/auth/controllers/user-auth.controller.ts | 41 +++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/auth/controllers/user-auth.controller.ts b/src/auth/controllers/user-auth.controller.ts index e7074da..616f4ad 100644 --- a/src/auth/controllers/user-auth.controller.ts +++ b/src/auth/controllers/user-auth.controller.ts @@ -10,7 +10,7 @@ import { } from '@nestjs/common'; import { UserAuthService } from '../services/user-auth.service'; import { UserSignUpDto } from '../dtos/user-auth.dto'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { ResponseMessage } from '../../../libs/common/src/response/response.decorator'; import { UserLoginDto } from '../dtos/user-login.dto'; import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos'; @@ -18,17 +18,22 @@ import { RefreshTokenGuard } from '@app/common/guards/jwt-refresh.auth.guard'; import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; import { OtpType } from '@app/common/constants/otp-type.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'authentication', + path: ControllerRoute.AUTHENTICATION.ROUTE, }) -@ApiTags('Auth') +@ApiTags('Authentication Module') export class UserAuthController { constructor(private readonly userAuthService: UserAuthService) {} @ResponseMessage('User Registered Successfully') @Post('user/signup') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.SIGN_UP_SUMMARY, + description: ControllerRoute.AUTHENTICATION.ACTIONS.SIGN_UP_DESCRIPTION, + }) async signUp(@Body() userSignUpDto: UserSignUpDto) { const signupUser = await this.userAuthService.signUp(userSignUpDto); return { @@ -41,8 +46,12 @@ export class UserAuthController { }; } - @ResponseMessage('user logged in successfully') + @ResponseMessage('User Logged in Successfully') @Post('user/login') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.LOGIN_SUMMARY, + description: ControllerRoute.AUTHENTICATION.ACTIONS.LOGIN_DESCRIPTION, + }) async userLogin(@Body() data: UserLoginDto) { const accessToken = await this.userAuthService.userLogin(data); return { @@ -53,6 +62,10 @@ export class UserAuthController { } @Post('user/send-otp') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.SEND_OTP_SUMMARY, + description: ControllerRoute.AUTHENTICATION.ACTIONS.SEND_OTP_DESCRIPTION, + }) async sendOtp(@Body() otpDto: UserOtpDto) { const otpCode = await this.userAuthService.generateOTP(otpDto); return { @@ -60,11 +73,15 @@ export class UserAuthController { data: { ...otpCode, }, - message: 'Otp Send Successfully', + message: 'Otp Sent Successfully', }; } @Post('user/verify-otp') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.VERIFY_OTP_SUMMARY, + description: ControllerRoute.AUTHENTICATION.ACTIONS.VERIFY_OTP_DESCRIPTION, + }) async verifyOtp(@Body() verifyOtpDto: VerifyOtpDto) { await this.userAuthService.verifyOTP(verifyOtpDto); return { @@ -75,6 +92,11 @@ export class UserAuthController { } @Post('user/forget-password') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.FORGET_PASSWORD_SUMMARY, + description: + ControllerRoute.AUTHENTICATION.ACTIONS.FORGET_PASSWORD_DESCRIPTION, + }) async forgetPassword(@Body() forgetPasswordDto: ForgetPasswordDto) { const otpResult = await this.userAuthService.verifyOTP( { @@ -102,6 +124,10 @@ export class UserAuthController { @ApiBearerAuth() @UseGuards(SuperAdminRoleGuard) @Get('user') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.USER_LIST_SUMMARY, + description: ControllerRoute.AUTHENTICATION.ACTIONS.USER_LIST_DESCRIPTION, + }) async userList() { const userList = await this.userAuthService.userList(); return { @@ -114,6 +140,11 @@ export class UserAuthController { @ApiBearerAuth() @UseGuards(RefreshTokenGuard) @Get('refresh-token') + @ApiOperation({ + summary: ControllerRoute.AUTHENTICATION.ACTIONS.REFRESH_TOKEN_SUMMARY, + description: + ControllerRoute.AUTHENTICATION.ACTIONS.REFRESH_TOKEN_DESCRIPTION, + }) async refreshToken(@Req() req) { const refreshToken = await this.userAuthService.refreshToken( req.user.uuid, From c1b8e63c5e74fd8f95235a2937704745fb9007bd Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:13 -0600 Subject: [PATCH 03/19] Add `ApiOperation` decorators to AutomationController endpoints --- .../controllers/automation.controller.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/automation/controllers/automation.controller.ts b/src/automation/controllers/automation.controller.ts index 49a5012..8d9d1ab 100644 --- a/src/automation/controllers/automation.controller.ts +++ b/src/automation/controllers/automation.controller.ts @@ -10,7 +10,7 @@ import { Put, UseGuards, } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AddAutomationDto, UpdateAutomationDto, @@ -19,11 +19,12 @@ import { import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; import { AutomationParamDto, SpaceParamDto } from '../dtos'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Automation Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'automation', + path: ControllerRoute.AUTOMATION.ROUTE, }) export class AutomationController { constructor(private readonly automationService: AutomationService) {} @@ -31,6 +32,10 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post() + @ApiOperation({ + summary: ControllerRoute.AUTOMATION.ACTIONS.ADD_AUTOMATION_SUMMARY, + description: ControllerRoute.AUTOMATION.ACTIONS.ADD_AUTOMATION_DESCRIPTION, + }) async addAutomation(@Body() addAutomationDto: AddAutomationDto) { const automation = await this.automationService.addAutomation(addAutomationDto); @@ -45,6 +50,11 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':spaceUuid') + @ApiOperation({ + summary: ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_BY_SPACE_SUMMARY, + description: + ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_BY_SPACE_DESCRIPTION, + }) async getAutomationBySpace(@Param() param: SpaceParamDto) { const automation = await this.automationService.getAutomationBySpace( param.spaceUuid, @@ -55,6 +65,11 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('details/:automationUuid') + @ApiOperation({ + summary: ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_DETAILS_SUMMARY, + description: + ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_DETAILS_DESCRIPTION, + }) async getAutomationDetails(@Param() param: AutomationParamDto) { const automation = await this.automationService.getAutomationDetails( param.automationUuid, @@ -65,6 +80,11 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Delete(':automationUuid') + @ApiOperation({ + summary: ControllerRoute.AUTOMATION.ACTIONS.DELETE_AUTOMATION_SUMMARY, + description: + ControllerRoute.AUTOMATION.ACTIONS.DELETE_AUTOMATION_DESCRIPTION, + }) async deleteAutomation(@Param() param: AutomationParamDto) { await this.automationService.deleteAutomation(param); return { @@ -76,6 +96,11 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put(':automationUuid') + @ApiOperation({ + summary: ControllerRoute.AUTOMATION.ACTIONS.UPDATE_AUTOMATION_SUMMARY, + description: + ControllerRoute.AUTOMATION.ACTIONS.UPDATE_AUTOMATION_DESCRIPTION, + }) async updateAutomation( @Body() updateAutomationDto: UpdateAutomationDto, @Param() param: AutomationParamDto, @@ -95,6 +120,12 @@ export class AutomationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('status/:automationUuid') + @ApiOperation({ + summary: + ControllerRoute.AUTOMATION.ACTIONS.UPDATE_AUTOMATION_STATUS_SUMMARY, + description: + ControllerRoute.AUTOMATION.ACTIONS.UPDATE_AUTOMATION_STATUS_DESCRIPTION, + }) async updateAutomationStatus( @Body() updateAutomationStatusDto: UpdateAutomationStatusDto, @Param() param: AutomationParamDto, From c2374e7155d8370c64fb31c02c6edf85af41405d Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:22 -0600 Subject: [PATCH 04/19] Add `@ApiOperation` decorators to DeviceController endpoints --- src/device/controllers/device.controller.ts | 91 ++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/src/device/controllers/device.controller.ts b/src/device/controllers/device.controller.ts index 28392aa..905212f 100644 --- a/src/device/controllers/device.controller.ts +++ b/src/device/controllers/device.controller.ts @@ -11,7 +11,7 @@ import { Req, Put, } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AddDeviceDto, AddSceneToFourSceneDeviceDto, @@ -32,17 +32,22 @@ import { CheckDeviceGuard } from 'src/guards/device.guard'; import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; import { CheckFourAndSixSceneDeviceTypeGuard } from 'src/guards/scene.device.type.guard'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Device Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'device', + path: ControllerRoute.DEVICE.ROUTE, }) export class DeviceController { constructor(private readonly deviceService: DeviceService) {} @ApiBearerAuth() @UseGuards(SuperAdminRoleGuard, CheckDeviceGuard) @Post() + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.ADD_DEVICE_TO_USER_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.ADD_DEVICE_TO_USER_DESCRIPTION, + }) async addDeviceUser(@Body() addDeviceDto: AddDeviceDto) { const device = await this.deviceService.addDeviceUser(addDeviceDto); @@ -56,6 +61,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('user/:userUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_BY_USER_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_BY_USER_DESCRIPTION, + }) async getDevicesByUser(@Param('userUuid') userUuid: string) { return await this.deviceService.getDevicesByUser(userUuid); } @@ -63,12 +72,22 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('space/:spaceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_BY_SPACE_UUID_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_BY_SPACE_UUID_DESCRIPTION, + }) async getDevicesByUnitId(@Param('spaceUuid') spaceUuid: string) { return await this.deviceService.getDevicesBySpaceUuid(spaceUuid); } @ApiBearerAuth() @UseGuards(JwtAuthGuard, CheckRoomGuard) @Put('space') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_IN_ROOM_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_IN_ROOM_DESCRIPTION, + }) async updateDeviceInRoom( @Body() updateDeviceInSpaceDto: UpdateDeviceInSpaceDto, ) { @@ -87,6 +106,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_DETAILS_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_DETAILS_DESCRIPTION, + }) async getDeviceDetailsByDeviceId( @Param('deviceUuid') deviceUuid: string, @Req() req: any, @@ -100,6 +123,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put(':deviceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_DESCRIPTION, + }) async updateDevice( @Param('deviceUuid') deviceUuid: string, @Body() updateDeviceDto: UpdateDeviceDto, @@ -120,6 +147,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceUuid/functions') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_INSTRUCTION_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_INSTRUCTION_DESCRIPTION, + }) async getDeviceInstructionByDeviceId( @Param('deviceUuid') deviceUuid: string, ) { @@ -128,6 +160,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceUuid/functions/status') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_STATUS_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_STATUS_DESCRIPTION, + }) async getDevicesInstructionStatus(@Param('deviceUuid') deviceUuid: string) { return await this.deviceService.getDevicesInstructionStatus(deviceUuid); } @@ -135,6 +171,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post(':deviceUuid/control') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.CONTROL_DEVICE_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.CONTROL_DEVICE_DESCRIPTION, + }) async controlDevice( @Body() controlDeviceDto: ControlDeviceDto, @Param('deviceUuid') deviceUuid: string, @@ -144,6 +184,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post(':deviceUuid/firmware/:firmwareVersion') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_FIRMWARE_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.UPDATE_DEVICE_FIRMWARE_DESCRIPTION, + }) async updateDeviceFirmware( @Param('deviceUuid') deviceUuid: string, @Param('firmwareVersion') firmwareVersion: number, @@ -156,12 +201,21 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('gateway/:gatewayUuid/devices') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_IN_GATEWAY_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.GET_DEVICES_IN_GATEWAY_DESCRIPTION, + }) async getDevicesInGateway(@Param('gatewayUuid') gatewayUuid: string) { return await this.deviceService.getDevicesInGateway(gatewayUuid); } @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get() + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_DESCRIPTION, + }) async getAllDevices() { return await this.deviceService.getAllDevices(); } @@ -169,6 +223,10 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('report-logs/:deviceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_LOGS_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.GET_DEVICE_LOGS_DESCRIPTION, + }) async getBuildingChildByUuid( @Param('deviceUuid') deviceUuid: string, @Query() query: GetDeviceLogsDto, @@ -178,6 +236,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('control/batch') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.BATCH_CONTROL_DEVICES_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.BATCH_CONTROL_DEVICES_DESCRIPTION, + }) async batchControlDevices( @Body() batchControlDevicesDto: BatchControlDevicesDto, ) { @@ -186,6 +249,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('status/batch') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.BATCH_STATUS_DEVICES_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.BATCH_STATUS_DEVICES_DESCRIPTION, + }) async batchStatusDevices( @Query() batchStatusDevicesDto: BatchStatusDevicesDto, ) { @@ -194,6 +262,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('factory/reset/:deviceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.BATCH_FACTORY_RESET_DEVICES_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.BATCH_FACTORY_RESET_DEVICES_DESCRIPTION, + }) async batchFactoryResetDevices( @Body() batchFactoryResetDevicesDto: BatchFactoryResetDevicesDto, ) { @@ -204,6 +277,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':powerClampUuid/power-clamp/status') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_POWER_CLAMP_STATUS_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.GET_POWER_CLAMP_STATUS_DESCRIPTION, + }) async getPowerClampInstructionStatus( @Param('powerClampUuid') powerClampUuid: string, ) { @@ -213,6 +291,10 @@ export class DeviceController { } @ApiBearerAuth() @UseGuards(JwtAuthGuard, CheckFourAndSixSceneDeviceTypeGuard) + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.ADD_SCENE_TO_DEVICE_SUMMARY, + description: ControllerRoute.DEVICE.ACTIONS.ADD_SCENE_TO_DEVICE_DESCRIPTION, + }) @Post(':deviceUuid/scenes') async addSceneToSceneDevice( @Param('deviceUuid') deviceUuid: string, @@ -233,6 +315,11 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard, CheckFourAndSixSceneDeviceTypeGuard) @Get(':deviceUuid/scenes') + @ApiOperation({ + summary: ControllerRoute.DEVICE.ACTIONS.GET_SCENES_BY_DEVICE_SUMMARY, + description: + ControllerRoute.DEVICE.ACTIONS.GET_SCENES_BY_DEVICE_DESCRIPTION, + }) async getScenesBySceneDevice( @Param('deviceUuid') deviceUuid: string, @Query() getSceneFourSceneDeviceDto: GetSceneFourSceneDeviceDto, From 0414e106d13199a754fce6924dfaacfa491db975 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:31 -0600 Subject: [PATCH 05/19] Add API operation descriptions to device messages controller --- .../controllers/device-messages.controller.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/device-messages/controllers/device-messages.controller.ts b/src/device-messages/controllers/device-messages.controller.ts index 6f942b4..d41d477 100644 --- a/src/device-messages/controllers/device-messages.controller.ts +++ b/src/device-messages/controllers/device-messages.controller.ts @@ -8,17 +8,18 @@ import { Post, UseGuards, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { DeviceMessagesSubscriptionService } from '../services/device-messages.service'; import { DeviceMessagesAddDto } from '../dtos/device-messages.dto'; import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Device Messages Status Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'device-messages/subscription', + path: ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ROUTE, }) export class DeviceMessagesSubscriptionController { constructor( @@ -28,6 +29,14 @@ export class DeviceMessagesSubscriptionController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post() + @ApiOperation({ + summary: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .ADD_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY, + description: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .ADD_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION, + }) async addDeviceMessagesSubscription( @Body() deviceMessagesAddDto: DeviceMessagesAddDto, ) { @@ -45,6 +54,14 @@ export class DeviceMessagesSubscriptionController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceUuid/user/:userUuid') + @ApiOperation({ + summary: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .GET_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY, + description: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .GET_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION, + }) async getDeviceMessagesSubscription( @Param('deviceUuid') deviceUuid: string, @Param('userUuid') userUuid: string, @@ -60,9 +77,18 @@ export class DeviceMessagesSubscriptionController { data: deviceDetails, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Delete() + @ApiOperation({ + summary: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .DELETE_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY, + description: + ControllerRoute.DEVICE_MESSAGES_SUBSCRIPTION.ACTIONS + .DELETE_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION, + }) async deleteDeviceMessagesSubscription( @Body() deviceMessagesAddDto: DeviceMessagesAddDto, ) { From 059d248d44e3c780bfcbf7a04769f69cf9b0cd06 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:42 -0600 Subject: [PATCH 06/19] Add API operation descriptions to DoorLockController --- .../controllers/door.lock.controller.ts | 93 +++++++++++++++++-- 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/src/door-lock/controllers/door.lock.controller.ts b/src/door-lock/controllers/door.lock.controller.ts index 3e6f459..a965ecb 100644 --- a/src/door-lock/controllers/door.lock.controller.ts +++ b/src/door-lock/controllers/door.lock.controller.ts @@ -10,23 +10,31 @@ import { UseGuards, Put, } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AddDoorLockOnlineDto } from '../dtos/add.online-temp.dto'; import { AddDoorLockOfflineTempMultipleTimeDto } from '../dtos/add.offline-temp.dto'; import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { UpdateDoorLockOfflineTempDto } from '../dtos/update.offline-temp.dto'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Door Lock Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'door-lock', + path: ControllerRoute.DOOR_LOCK.ROUTE, }) export class DoorLockController { constructor(private readonly doorLockService: DoorLockService) {} @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/online/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS.ADD_ONLINE_TEMPORARY_PASSWORD_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .ADD_ONLINE_TEMPORARY_PASSWORD_DESCRIPTION, + }) async addOnlineTemporaryPassword( @Body() addDoorLockDto: AddDoorLockOnlineDto, @Param('doorLockUuid') doorLockUuid: string, @@ -40,15 +48,24 @@ export class DoorLockController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'online temporary password added successfully', + message: 'Online temporary password added successfully', data: { id: temporaryPassword.id, }, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/offline/one-time/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .ADD_OFFLINE_ONE_TIME_TEMPORARY_PASSWORD_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .ADD_OFFLINE_ONE_TIME_TEMPORARY_PASSWORD_DESCRIPTION, + }) async addOfflineOneTimeTemporaryPassword( @Param('doorLockUuid') doorLockUuid: string, ) { @@ -60,13 +77,22 @@ export class DoorLockController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'offline temporary password added successfully', + message: 'Offline one-time temporary password added successfully', data: temporaryPassword, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/offline/multiple-time/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .ADD_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORD_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .ADD_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORD_DESCRIPTION, + }) async addOfflineMultipleTimeTemporaryPassword( @Body() addDoorLockOfflineTempMultipleTimeDto: AddDoorLockOfflineTempMultipleTimeDto, @@ -81,13 +107,21 @@ export class DoorLockController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'offline temporary password added successfully', + message: 'Offline multiple-time temporary password added successfully', data: temporaryPassword, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('temporary-password/online/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS.GET_ONLINE_TEMPORARY_PASSWORDS_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .GET_ONLINE_TEMPORARY_PASSWORDS_DESCRIPTION, + }) async getOnlineTemporaryPasswords( @Param('doorLockUuid') doorLockUuid: string, ) { @@ -95,9 +129,18 @@ export class DoorLockController { doorLockUuid, ); } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Delete('temporary-password/online/:doorLockUuid/:passwordId') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .DELETE_ONLINE_TEMPORARY_PASSWORD_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .DELETE_ONLINE_TEMPORARY_PASSWORD_DESCRIPTION, + }) async deleteDoorLockPassword( @Param('doorLockUuid') doorLockUuid: string, @Param('passwordId') passwordId: string, @@ -105,12 +148,21 @@ export class DoorLockController { await this.doorLockService.deleteDoorLockPassword(doorLockUuid, passwordId); return { statusCode: HttpStatus.OK, - message: 'Temporary Password deleted Successfully', + message: 'Temporary password deleted successfully', }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('temporary-password/offline/one-time/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .GET_OFFLINE_ONE_TIME_TEMPORARY_PASSWORDS_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .GET_OFFLINE_ONE_TIME_TEMPORARY_PASSWORDS_DESCRIPTION, + }) async getOfflineOneTimeTemporaryPasswords( @Param('doorLockUuid') doorLockUuid: string, ) { @@ -118,9 +170,18 @@ export class DoorLockController { doorLockUuid, ); } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('temporary-password/offline/multiple-time/:doorLockUuid') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .GET_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORDS_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .GET_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORDS_DESCRIPTION, + }) async getOfflineMultipleTimeTemporaryPasswords( @Param('doorLockUuid') doorLockUuid: string, ) { @@ -132,9 +193,16 @@ export class DoorLockController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('temporary-password/:doorLockUuid/offline/:passwordId') + @ApiOperation({ + summary: + ControllerRoute.DOOR_LOCK.ACTIONS + .UPDATE_OFFLINE_TEMPORARY_PASSWORD_SUMMARY, + description: + ControllerRoute.DOOR_LOCK.ACTIONS + .UPDATE_OFFLINE_TEMPORARY_PASSWORD_DESCRIPTION, + }) async updateOfflineTemporaryPassword( - @Body() - updateDoorLockOfflineTempDto: UpdateDoorLockOfflineTempDto, + @Body() updateDoorLockOfflineTempDto: UpdateDoorLockOfflineTempDto, @Param('doorLockUuid') doorLockUuid: string, @Param('passwordId') passwordId: string, ) { @@ -148,20 +216,25 @@ export class DoorLockController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'offline temporary password updated successfully', + message: 'Offline temporary password updated successfully', data: temporaryPassword, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('open/:doorLockUuid') + @ApiOperation({ + summary: ControllerRoute.DOOR_LOCK.ACTIONS.OPEN_DOOR_LOCK_SUMMARY, + description: ControllerRoute.DOOR_LOCK.ACTIONS.OPEN_DOOR_LOCK_DESCRIPTION, + }) async openDoorLock(@Param('doorLockUuid') doorLockUuid: string) { await this.doorLockService.openDoorLock(doorLockUuid); return { statusCode: HttpStatus.CREATED, success: true, - message: 'door lock opened successfully', + message: 'Door lock opened successfully', }; } } From 19c7233836fae131a5274437c6a530e9d4167203 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:50:52 -0600 Subject: [PATCH 07/19] Refactor GroupController to use static route constants and add API operation descriptions --- src/group/controllers/group.controller.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/group/controllers/group.controller.ts b/src/group/controllers/group.controller.ts index 3098da0..a5d7cd7 100644 --- a/src/group/controllers/group.controller.ts +++ b/src/group/controllers/group.controller.ts @@ -1,13 +1,14 @@ import { GroupService } from '../services/group.service'; import { Controller, Get, UseGuards, Param, Req } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; // Assuming this is where the routes are defined @ApiTags('Group Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'group', + path: ControllerRoute.GROUP.ROUTE, // use the static route constant }) export class GroupController { constructor(private readonly groupService: GroupService) {} @@ -15,6 +16,11 @@ export class GroupController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':spaceUuid') + @ApiOperation({ + summary: ControllerRoute.GROUP.ACTIONS.GET_GROUPS_BY_SPACE_UUID_SUMMARY, + description: + ControllerRoute.GROUP.ACTIONS.GET_GROUPS_BY_SPACE_UUID_DESCRIPTION, + }) async getGroupsBySpaceUuid(@Param('spaceUuid') spaceUuid: string) { return await this.groupService.getGroupsBySpaceUuid(spaceUuid); } @@ -22,6 +28,12 @@ export class GroupController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':spaceUuid/devices/:groupName') + @ApiOperation({ + summary: + ControllerRoute.GROUP.ACTIONS.GET_UNIT_DEVICES_BY_GROUP_NAME_SUMMARY, + description: + ControllerRoute.GROUP.ACTIONS.GET_UNIT_DEVICES_BY_GROUP_NAME_DESCRIPTION, + }) async getUnitDevicesByGroupName( @Param('spaceUuid') spaceUuid: string, @Param('groupName') groupName: string, From 6bb0feec6147ec0cb1c269420aa9c479e11b6c39 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:00 -0600 Subject: [PATCH 08/19] Update RoleController to use static route constants and add API operation descriptions --- src/role/controllers/role.controller.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/role/controllers/role.controller.ts b/src/role/controllers/role.controller.ts index f08adb4..a53cd1c 100644 --- a/src/role/controllers/role.controller.ts +++ b/src/role/controllers/role.controller.ts @@ -6,22 +6,28 @@ import { Post, UseGuards, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { RoleService } from '../services/role.service'; import { AddUserRoleDto } from '../dtos'; import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; // Assuming this is where the routes are defined @ApiTags('Role Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'role', + path: ControllerRoute.ROLE.ROUTE, // use the static route constant }) export class RoleController { constructor(private readonly roleService: RoleService) {} + @ApiBearerAuth() @UseGuards(SuperAdminRoleGuard) @Get('types') + @ApiOperation({ + summary: ControllerRoute.ROLE.ACTIONS.FETCH_ROLE_TYPES_SUMMARY, + description: ControllerRoute.ROLE.ACTIONS.FETCH_ROLE_TYPES_DESCRIPTION, + }) async fetchRoleTypes() { const roleTypes = await this.roleService.fetchRoleTypes(); return { @@ -30,9 +36,14 @@ export class RoleController { data: roleTypes, }; } + @ApiBearerAuth() @UseGuards(SuperAdminRoleGuard) @Post() + @ApiOperation({ + summary: ControllerRoute.ROLE.ACTIONS.ADD_USER_ROLE_SUMMARY, + description: ControllerRoute.ROLE.ACTIONS.ADD_USER_ROLE_DESCRIPTION, + }) async addUserRoleType(@Body() addUserRoleDto: AddUserRoleDto) { await this.roleService.addUserRoleType(addUserRoleDto); return { From a5ebecb952ad98ed57d941b36cce9becd8e2946a Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:10 -0600 Subject: [PATCH 09/19] Add `ApiOperation` decorators and update route paths in `ScheduleController` --- .../controllers/schedule.controller.ts | 45 ++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/schedule/controllers/schedule.controller.ts b/src/schedule/controllers/schedule.controller.ts index 82676bf..d4c7a91 100644 --- a/src/schedule/controllers/schedule.controller.ts +++ b/src/schedule/controllers/schedule.controller.ts @@ -11,7 +11,7 @@ import { Delete, Query, } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AddScheduleDto, EnableScheduleDto, @@ -21,17 +21,24 @@ import { import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Schedule Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'schedule', + path: ControllerRoute.SCHEDULE.ROUTE, }) export class ScheduleController { constructor(private readonly scheduleService: ScheduleService) {} + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post(':deviceUuid') + @ApiOperation({ + summary: ControllerRoute.SCHEDULE.ACTIONS.ADD_DEVICE_SCHEDULE_SUMMARY, + description: + ControllerRoute.SCHEDULE.ACTIONS.ADD_DEVICE_SCHEDULE_DESCRIPTION, + }) async addDeviceSchedule( @Param('deviceUuid') deviceUuid: string, @Body() addScheduleDto: AddScheduleDto, @@ -44,13 +51,21 @@ export class ScheduleController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'schedule added successfully', + message: 'Schedule added successfully', data: schedule, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceUuid') + @ApiOperation({ + summary: + ControllerRoute.SCHEDULE.ACTIONS.GET_DEVICE_SCHEDULE_BY_CATEGORY_SUMMARY, + description: + ControllerRoute.SCHEDULE.ACTIONS + .GET_DEVICE_SCHEDULE_BY_CATEGORY_DESCRIPTION, + }) async getDeviceScheduleByCategory( @Param('deviceUuid') deviceUuid: string, @Query() query: GetScheduleDeviceDto, @@ -60,9 +75,15 @@ export class ScheduleController { query.category, ); } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Delete(':deviceUuid/:scheduleId') + @ApiOperation({ + summary: ControllerRoute.SCHEDULE.ACTIONS.DELETE_DEVICE_SCHEDULE_SUMMARY, + description: + ControllerRoute.SCHEDULE.ACTIONS.DELETE_DEVICE_SCHEDULE_DESCRIPTION, + }) async deleteDeviceSchedule( @Param('deviceUuid') deviceUuid: string, @Param('scheduleId') scheduleId: string, @@ -71,12 +92,18 @@ export class ScheduleController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'schedule deleted successfully', + message: 'Schedule deleted successfully', }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('enable/:deviceUuid') + @ApiOperation({ + summary: ControllerRoute.SCHEDULE.ACTIONS.ENABLE_DEVICE_SCHEDULE_SUMMARY, + description: + ControllerRoute.SCHEDULE.ACTIONS.ENABLE_DEVICE_SCHEDULE_DESCRIPTION, + }) async enableDeviceSchedule( @Param('deviceUuid') deviceUuid: string, @Body() enableScheduleDto: EnableScheduleDto, @@ -88,12 +115,18 @@ export class ScheduleController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'schedule updated successfully', + message: 'Schedule updated successfully', }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put(':deviceUuid') + @ApiOperation({ + summary: ControllerRoute.SCHEDULE.ACTIONS.UPDATE_DEVICE_SCHEDULE_SUMMARY, + description: + ControllerRoute.SCHEDULE.ACTIONS.UPDATE_DEVICE_SCHEDULE_DESCRIPTION, + }) async updateDeviceSchedule( @Param('deviceUuid') deviceUuid: string, @Body() updateScheduleDto: UpdateScheduleDto, @@ -106,7 +139,7 @@ export class ScheduleController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'schedule updated successfully', + message: 'Schedule updated successfully', data: schedule, }; } From e47cb82e337dc5caeb4e04894d4215a80581956f Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:17 -0600 Subject: [PATCH 10/19] Update TimeZoneController with ApiOperation and dynamic route --- src/timezone/controllers/timezone.controller.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/timezone/controllers/timezone.controller.ts b/src/timezone/controllers/timezone.controller.ts index bc46381..756bdbb 100644 --- a/src/timezone/controllers/timezone.controller.ts +++ b/src/timezone/controllers/timezone.controller.ts @@ -1,13 +1,14 @@ import { Controller, Get, UseGuards } from '@nestjs/common'; import { TimeZoneService } from '../services/timezone.service'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('TimeZone Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'timezone', + path: ControllerRoute.TIMEZONE.ROUTE, }) export class TimeZoneController { constructor(private readonly timeZoneService: TimeZoneService) {} @@ -15,6 +16,11 @@ export class TimeZoneController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get() + @ApiOperation({ + summary: ControllerRoute.TIMEZONE.ACTIONS.GET_ALL_TIME_ZONES_SUMMARY, + description: + ControllerRoute.TIMEZONE.ACTIONS.GET_ALL_TIME_ZONES_DESCRIPTION, + }) async getAllTimeZones() { return await this.timeZoneService.getAllTimeZones(); } From 977cc6fb070027e121ee5a8313d6caf61bc30f98 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:30 -0600 Subject: [PATCH 11/19] Add API operation descriptions to user device permission controller --- .../user-device-permission.controller.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/user-device-permission/controllers/user-device-permission.controller.ts b/src/user-device-permission/controllers/user-device-permission.controller.ts index 5ff5284..7d33b7f 100644 --- a/src/user-device-permission/controllers/user-device-permission.controller.ts +++ b/src/user-device-permission/controllers/user-device-permission.controller.ts @@ -9,17 +9,18 @@ import { Put, UseGuards, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiTags, ApiOperation } from '@nestjs/swagger'; import { UserDevicePermissionService } from '../services/user-device-permission.service'; import { UserDevicePermissionAddDto } from '../dtos/user-device-permission.add.dto'; import { UserDevicePermissionEditDto } from '../dtos/user-device-permission.edit.dto'; import { AdminRoleGuard } from 'src/guards/admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Device Permission Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'device-permission', + path: ControllerRoute.DEVICE_PERMISSION.ROUTE, }) export class UserDevicePermissionController { constructor( @@ -29,6 +30,11 @@ export class UserDevicePermissionController { @ApiBearerAuth() @UseGuards(AdminRoleGuard) @Post() + @ApiOperation({ + summary: ControllerRoute.DEVICE_PERMISSION.ACTIONS.ADD_PERMISSION_SUMMARY, + description: + ControllerRoute.DEVICE_PERMISSION.ACTIONS.ADD_PERMISSION_DESCRIPTION, + }) async addDevicePermission( @Body() userDevicePermissionDto: UserDevicePermissionAddDto, ) { @@ -45,6 +51,11 @@ export class UserDevicePermissionController { @ApiBearerAuth() @UseGuards(AdminRoleGuard) @Put(':devicePermissionUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE_PERMISSION.ACTIONS.EDIT_PERMISSION_SUMMARY, + description: + ControllerRoute.DEVICE_PERMISSION.ACTIONS.EDIT_PERMISSION_DESCRIPTION, + }) async editDevicePermission( @Param('devicePermissionUuid') devicePermissionUuid: string, @Body() userDevicePermissionEditDto: UserDevicePermissionEditDto, @@ -62,6 +73,11 @@ export class UserDevicePermissionController { @ApiBearerAuth() @UseGuards(AdminRoleGuard) @Get(':deviceUuid') + @ApiOperation({ + summary: ControllerRoute.DEVICE_PERMISSION.ACTIONS.FETCH_PERMISSION_SUMMARY, + description: + ControllerRoute.DEVICE_PERMISSION.ACTIONS.FETCH_PERMISSION_DESCRIPTION, + }) async fetchDevicePermission(@Param('deviceUuid') deviceUuid: string) { const deviceDetails = await this.userDevicePermissionService.fetchUserPermission(deviceUuid); @@ -71,9 +87,16 @@ export class UserDevicePermissionController { data: deviceDetails, }; } + @ApiBearerAuth() @UseGuards(AdminRoleGuard) @Delete(':devicePermissionUuid') + @ApiOperation({ + summary: + ControllerRoute.DEVICE_PERMISSION.ACTIONS.DELETE_PERMISSION_SUMMARY, + description: + ControllerRoute.DEVICE_PERMISSION.ACTIONS.DELETE_PERMISSION_DESCRIPTION, + }) async deleteDevicePermission( @Param('devicePermissionUuid') devicePermissionUuid: string, ) { From b904c1a338bb9e4b4b7bc306148c69884315787d Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:37 -0600 Subject: [PATCH 12/19] Add `ApiOperation` decorators and update controller path --- .../user-notification.controller.ts | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/user-notification/controllers/user-notification.controller.ts b/src/user-notification/controllers/user-notification.controller.ts index 8fe8586..8e57122 100644 --- a/src/user-notification/controllers/user-notification.controller.ts +++ b/src/user-notification/controllers/user-notification.controller.ts @@ -8,7 +8,7 @@ import { Put, UseGuards, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiTags, ApiOperation } from '@nestjs/swagger'; import { UserNotificationService } from '../services/user-notification.service'; import { UserNotificationAddDto, @@ -17,11 +17,12 @@ import { import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('User Notification Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'user-notification/subscription', + path: ControllerRoute.USER_NOTIFICATION.ROUTE, }) export class UserNotificationController { constructor( @@ -31,6 +32,11 @@ export class UserNotificationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post() + @ApiOperation({ + summary: ControllerRoute.USER_NOTIFICATION.ACTIONS.ADD_SUBSCRIPTION_SUMMARY, + description: + ControllerRoute.USER_NOTIFICATION.ACTIONS.ADD_SUBSCRIPTION_DESCRIPTION, + }) async addUserSubscription( @Body() userNotificationAddDto: UserNotificationAddDto, ) { @@ -47,6 +53,12 @@ export class UserNotificationController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':userUuid') + @ApiOperation({ + summary: + ControllerRoute.USER_NOTIFICATION.ACTIONS.FETCH_SUBSCRIPTIONS_SUMMARY, + description: + ControllerRoute.USER_NOTIFICATION.ACTIONS.FETCH_SUBSCRIPTIONS_DESCRIPTION, + }) async fetchUserSubscriptions(@Param('userUuid') userUuid: string) { const userDetails = await this.userNotificationService.fetchUserSubscriptions(userUuid); @@ -56,9 +68,16 @@ export class UserNotificationController { data: { ...userDetails }, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put() + @ApiOperation({ + summary: + ControllerRoute.USER_NOTIFICATION.ACTIONS.UPDATE_SUBSCRIPTION_SUMMARY, + description: + ControllerRoute.USER_NOTIFICATION.ACTIONS.UPDATE_SUBSCRIPTION_DESCRIPTION, + }) async updateUserSubscription( @Body() userNotificationUpdateDto: UserNotificationUpdateDto, ) { From fbbabc0644da379b895e08b9ad5e541c800d7eee Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:51:49 -0600 Subject: [PATCH 13/19] Add API operation metadata to verifyCodeAndAddUserSpace endpoint --- src/users/controllers/user-space.controller.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/users/controllers/user-space.controller.ts b/src/users/controllers/user-space.controller.ts index df36a5a..aed945a 100644 --- a/src/users/controllers/user-space.controller.ts +++ b/src/users/controllers/user-space.controller.ts @@ -40,6 +40,13 @@ export class UserSpaceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('/verify-code') + @ApiOperation({ + summary: + ControllerRoute.USER_SPACE.ACTIONS.VERIFY_CODE_AND_ADD_USER_SPACE_SUMMARY, + description: + ControllerRoute.USER_SPACE.ACTIONS + .VERIFY_CODE_AND_ADD_USER_SPACE_DESCRIPTION, + }) async verifyCodeAndAddUserSpace( @Body() dto: AddUserSpaceUsingCodeDto, @Param() params: UserParamDto, From 25e331f59e699d29312a143b467fd1e74714e179 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:52:00 -0600 Subject: [PATCH 14/19] Add API operation descriptions and update route paths --- src/users/controllers/user.controller.ts | 49 +++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/users/controllers/user.controller.ts b/src/users/controllers/user.controller.ts index 503f47c..6f0eded 100644 --- a/src/users/controllers/user.controller.ts +++ b/src/users/controllers/user.controller.ts @@ -9,7 +9,7 @@ import { UseGuards, } from '@nestjs/common'; import { UserService } from '../services/user.service'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard'; import { UpdateNameDto, @@ -20,11 +20,12 @@ import { import { CheckProfilePictureGuard } from 'src/guards/profile.picture.guard'; import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('User Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'user', + path: ControllerRoute.USER.ROUTE, }) export class UserController { constructor(private readonly userService: UserService) {} @@ -32,12 +33,22 @@ export class UserController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':userUuid') + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.GET_USER_DETAILS_SUMMARY, + description: ControllerRoute.USER.ACTIONS.GET_USER_DETAILS_DESCRIPTION, + }) async getUserDetailsByUserUuid(@Param('userUuid') userUuid: string) { return await this.userService.getUserDetailsByUserUuid(userUuid); } + @ApiBearerAuth() @UseGuards(JwtAuthGuard, CheckProfilePictureGuard) @Put('/profile-picture/:userUuid') + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.UPDATE_PROFILE_PICTURE_SUMMARY, + description: + ControllerRoute.USER.ACTIONS.UPDATE_PROFILE_PICTURE_DESCRIPTION, + }) async updateProfilePictureByUserUuid( @Param('userUuid') userUuid: string, @Body() updateProfilePictureDataDto: UpdateProfilePictureDataDto, @@ -49,13 +60,18 @@ export class UserController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'profile picture updated successfully', + message: 'Profile picture updated successfully', data: userData, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('/region/:userUuid') + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.UPDATE_REGION_SUMMARY, + description: ControllerRoute.USER.ACTIONS.UPDATE_REGION_DESCRIPTION, + }) async updateRegionByUserUuid( @Param('userUuid') userUuid: string, @Body() updateRegionDataDto: UpdateRegionDataDto, @@ -67,14 +83,19 @@ export class UserController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'region updated successfully', + message: 'Region updated successfully', data: userData, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('/timezone/:userUuid') - async updateNameByUserUuid( + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.UPDATE_TIMEZONE_SUMMARY, + description: ControllerRoute.USER.ACTIONS.UPDATE_TIMEZONE_DESCRIPTION, + }) + async updateTimezoneByUserUuid( @Param('userUuid') userUuid: string, @Body() updateTimezoneDataDto: UpdateTimezoneDataDto, ) { @@ -85,14 +106,19 @@ export class UserController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'timezone updated successfully', + message: 'Timezone updated successfully', data: userData, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Put('/name/:userUuid') - async updateTimezoneByUserUuid( + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.UPDATE_NAME_SUMMARY, + description: ControllerRoute.USER.ACTIONS.UPDATE_NAME_DESCRIPTION, + }) + async updateNameByUserUuid( @Param('userUuid') userUuid: string, @Body() updateNameDto: UpdateNameDto, ) { @@ -103,13 +129,18 @@ export class UserController { return { statusCode: HttpStatus.CREATED, success: true, - message: 'name updated successfully', + message: 'Name updated successfully', data: userData, }; } + @ApiBearerAuth() @UseGuards(SuperAdminRoleGuard) @Delete('/:userUuid') + @ApiOperation({ + summary: ControllerRoute.USER.ACTIONS.DELETE_USER_SUMMARY, + description: ControllerRoute.USER.ACTIONS.DELETE_USER_DESCRIPTION, + }) async userDelete(@Param('userUuid') userUuid: string) { await this.userService.deleteUser(userUuid); return { @@ -117,7 +148,7 @@ export class UserController { data: { userUuid, }, - message: 'User Deleted Successfully', + message: 'User deleted successfully', }; } } From 2069b92e6d7332fb7d78201362de9811f1d352ff Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:52:11 -0600 Subject: [PATCH 15/19] Add `ApiOperation` decorators to visitor password controller endpoints --- .../visitor-password.controller.ts | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/vistor-password/controllers/visitor-password.controller.ts b/src/vistor-password/controllers/visitor-password.controller.ts index 894b759..55276be 100644 --- a/src/vistor-password/controllers/visitor-password.controller.ts +++ b/src/vistor-password/controllers/visitor-password.controller.ts @@ -8,7 +8,7 @@ import { Get, Req, } from '@nestjs/common'; -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AddDoorLockOfflineMultipleDto, AddDoorLockOfflineOneTimeDto, @@ -17,19 +17,29 @@ import { } from '../dtos/temp-pass.dto'; import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; @ApiTags('Visitor Password Module') @Controller({ version: EnableDisableStatusEnum.ENABLED, - path: 'visitor-password', + path: ControllerRoute.VISITOR_PASSWORD.ROUTE, }) export class VisitorPasswordController { constructor( private readonly visitorPasswordService: VisitorPasswordService, ) {} + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/online/multiple-time') + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_ONLINE_TEMP_PASSWORD_MULTIPLE_TIME_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_ONLINE_TEMP_PASSWORD_MULTIPLE_TIME_DESCRIPTION, + }) async addOnlineTemporaryPasswordMultipleTime( @Body() addDoorLockOnlineMultipleDto: AddDoorLockOnlineMultipleDto, @Req() req: any, @@ -46,9 +56,18 @@ export class VisitorPasswordController { data: temporaryPasswords, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/online/one-time') + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_ONLINE_TEMP_PASSWORD_ONE_TIME_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_ONLINE_TEMP_PASSWORD_ONE_TIME_DESCRIPTION, + }) async addOnlineTemporaryPassword( @Body() addDoorLockOnlineOneTimeDto: AddDoorLockOnlineOneTimeDto, @Req() req: any, @@ -65,9 +84,18 @@ export class VisitorPasswordController { data: temporaryPasswords, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/offline/one-time') + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_OFFLINE_TEMP_PASSWORD_ONE_TIME_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_OFFLINE_TEMP_PASSWORD_ONE_TIME_DESCRIPTION, + }) async addOfflineOneTimeTemporaryPassword( @Body() addDoorLockOfflineOneTimeDto: AddDoorLockOfflineOneTimeDto, @Req() req: any, @@ -84,9 +112,18 @@ export class VisitorPasswordController { data: temporaryPassword, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('temporary-password/offline/multiple-time') + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_OFFLINE_TEMP_PASSWORD_MULTIPLE_TIME_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS + .ADD_OFFLINE_TEMP_PASSWORD_MULTIPLE_TIME_DESCRIPTION, + }) async addOfflineMultipleTimeTemporaryPassword( @Body() addDoorLockOfflineMultipleDto: AddDoorLockOfflineMultipleDto, @@ -104,15 +141,29 @@ export class VisitorPasswordController { data: temporaryPassword, }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get() + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS.GET_VISITOR_PASSWORD_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS.GET_VISITOR_PASSWORD_DESCRIPTION, + }) async GetVisitorPassword() { return await this.visitorPasswordService.getPasswords(); } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('/devices') + @ApiOperation({ + summary: + ControllerRoute.VISITOR_PASSWORD.ACTIONS.GET_VISITOR_DEVICES_SUMMARY, + description: + ControllerRoute.VISITOR_PASSWORD.ACTIONS.GET_VISITOR_DEVICES_DESCRIPTION, + }) async GetVisitorDevices() { return await this.visitorPasswordService.getAllPassDevices(); } From 360371e910b5738b94a3dbe87f409865d7deb766 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:53:20 -0600 Subject: [PATCH 16/19] Add comprehensive endpoint descriptions for various controller routes --- libs/common/src/constants/controller-route.ts | 437 ++++++++++++++++++ 1 file changed, 437 insertions(+) diff --git a/libs/common/src/constants/controller-route.ts b/libs/common/src/constants/controller-route.ts index fdf0435..0f13f5c 100644 --- a/libs/common/src/constants/controller-route.ts +++ b/libs/common/src/constants/controller-route.ts @@ -77,6 +77,10 @@ export class ControllerRoute { 'Retrieve list of spaces a user belongs to'; public static readonly GET_USER_SPACES_DESCRIPTION = 'This endpoint retrieves all the spaces that a user is associated with, based on the user ID. It fetches the user spaces by querying the UserSpaceEntity to find the spaces where the user has an association.'; + public static readonly VERIFY_CODE_AND_ADD_USER_SPACE_SUMMARY = + 'Verify code and add user space'; + public static readonly VERIFY_CODE_AND_ADD_USER_SPACE_DESCRIPTION = + 'This endpoint verifies a provided code and associates the user with a space. It checks the validity of the code and, if valid, links the user to the corresponding space in the system.'; }; }; @@ -244,4 +248,437 @@ export class ControllerRoute { 'Fetches a list of all products along with their associated device details'; }; }; + static USER = class { + public static readonly ROUTE = '/user'; + + static ACTIONS = class { + public static readonly GET_USER_DETAILS_SUMMARY = + 'Retrieve user details by user UUID'; + public static readonly GET_USER_DETAILS_DESCRIPTION = + 'This endpoint retrieves detailed information for a specific user based on their UUID.'; + + public static readonly UPDATE_PROFILE_PICTURE_SUMMARY = + 'Update profile picture by user UUID'; + public static readonly UPDATE_PROFILE_PICTURE_DESCRIPTION = + 'This endpoint updates the profile picture for a user identified by their UUID.'; + + public static readonly UPDATE_REGION_SUMMARY = + 'Update region by user UUID'; + public static readonly UPDATE_REGION_DESCRIPTION = + 'This endpoint updates the region information for a user identified by their UUID.'; + + public static readonly UPDATE_TIMEZONE_SUMMARY = + 'Update timezone by user UUID'; + public static readonly UPDATE_TIMEZONE_DESCRIPTION = + 'This endpoint updates the timezone information for a user identified by their UUID.'; + + public static readonly UPDATE_NAME_SUMMARY = 'Update name by user UUID'; + public static readonly UPDATE_NAME_DESCRIPTION = + 'This endpoint updates the name for a user identified by their UUID.'; + + public static readonly DELETE_USER_SUMMARY = 'Delete user by UUID'; + public static readonly DELETE_USER_DESCRIPTION = + 'This endpoint deletes a user identified by their UUID. Accessible only by users with the Super Admin role.'; + }; + }; + static AUTHENTICATION = class { + public static readonly ROUTE = 'authentication'; + + static ACTIONS = class { + public static readonly SIGN_UP_SUMMARY = + 'Sign up a new user and return a JWT token'; + public static readonly SIGN_UP_DESCRIPTION = + 'This endpoint is used to register a new user by providing the user details. A JWT token will be generated and returned upon successful registration.'; + + public static readonly LOGIN_SUMMARY = + 'Login a user and return an access token'; + public static readonly LOGIN_DESCRIPTION = + 'This endpoint allows an existing user to log in using their credentials. Upon successful login, an access token will be returned.'; + + public static readonly SEND_OTP_SUMMARY = + 'Generate and send OTP to the user'; + public static readonly SEND_OTP_DESCRIPTION = + 'This endpoint generates and sends an OTP to the user for verification, such as for password reset or account verification.'; + + public static readonly VERIFY_OTP_SUMMARY = + 'Verify the OTP entered by the user'; + public static readonly VERIFY_OTP_DESCRIPTION = + 'This endpoint verifies the OTP entered by the user. If the OTP is valid, the process continues (e.g., password reset).'; + + public static readonly FORGET_PASSWORD_SUMMARY = + 'Reset the user password after OTP verification'; + public static readonly FORGET_PASSWORD_DESCRIPTION = + 'This endpoint allows users who have forgotten their password to reset it. After verifying the OTP, the user can set a new password.'; + + public static readonly USER_LIST_SUMMARY = 'Fetch the list of all users'; + public static readonly USER_LIST_DESCRIPTION = + 'This endpoint retrieves a list of all users in the system. Access is restricted to super admins only.'; + + public static readonly REFRESH_TOKEN_SUMMARY = + 'Refresh the user session token'; + public static readonly REFRESH_TOKEN_DESCRIPTION = + 'This endpoint allows a user to refresh their session token. The user must provide a valid refresh token to get a new session token.'; + }; + }; + static ROLE = class { + public static readonly ROUTE = 'role'; + + static ACTIONS = class { + public static readonly FETCH_ROLE_TYPES_SUMMARY = + 'Fetch available role types'; + public static readonly FETCH_ROLE_TYPES_DESCRIPTION = + 'This endpoint retrieves all available role types in the system.'; + + public static readonly ADD_USER_ROLE_SUMMARY = 'Add a new user role'; + public static readonly ADD_USER_ROLE_DESCRIPTION = + 'This endpoint adds a new user role to the system based on the provided role data.'; + }; + }; + static GROUP = class { + public static readonly ROUTE = 'group'; + + static ACTIONS = class { + public static readonly GET_GROUPS_BY_SPACE_UUID_SUMMARY = + 'Get groups by space UUID'; + public static readonly GET_GROUPS_BY_SPACE_UUID_DESCRIPTION = + 'This endpoint retrieves all groups for a specific space, identified by the space UUID.'; + + public static readonly GET_UNIT_DEVICES_BY_GROUP_NAME_SUMMARY = + 'Get devices by group name in a space'; + public static readonly GET_UNIT_DEVICES_BY_GROUP_NAME_DESCRIPTION = + 'This endpoint retrieves all devices in a specified group within a space, based on the group name and space UUID.'; + }; + }; + static DEVICE = class { + public static readonly ROUTE = 'device'; + + static ACTIONS = class { + public static readonly ADD_DEVICE_TO_USER_SUMMARY = 'Add device to user'; + public static readonly ADD_DEVICE_TO_USER_DESCRIPTION = + 'This endpoint adds a device to a user in the system.'; + + public static readonly GET_DEVICES_BY_USER_SUMMARY = + 'Get devices by user UUID'; + public static readonly GET_DEVICES_BY_USER_DESCRIPTION = + 'This endpoint retrieves all devices associated with a specific user.'; + + public static readonly GET_DEVICES_BY_SPACE_UUID_SUMMARY = + 'Get devices by space UUID'; + public static readonly GET_DEVICES_BY_SPACE_UUID_DESCRIPTION = + 'This endpoint retrieves all devices associated with a specific space UUID.'; + + public static readonly UPDATE_DEVICE_IN_ROOM_SUMMARY = + 'Update device in Space'; + public static readonly UPDATE_DEVICE_IN_ROOM_DESCRIPTION = + 'This endpoint updates the device in a specific space with new details.'; + + public static readonly GET_DEVICE_DETAILS_SUMMARY = 'Get device details'; + public static readonly GET_DEVICE_DETAILS_DESCRIPTION = + 'This endpoint retrieves details of a specific device by its UUID.'; + + public static readonly UPDATE_DEVICE_SUMMARY = 'Update device'; + public static readonly UPDATE_DEVICE_DESCRIPTION = + 'This endpoint updates the details of a device by its UUID.'; + + public static readonly GET_DEVICE_INSTRUCTION_SUMMARY = + 'Get device instruction'; + public static readonly GET_DEVICE_INSTRUCTION_DESCRIPTION = + 'This endpoint retrieves the instruction details for a specific device.'; + + public static readonly GET_DEVICE_STATUS_SUMMARY = 'Get device status'; + public static readonly GET_DEVICE_STATUS_DESCRIPTION = + 'This endpoint retrieves the current status of a specific device.'; + + public static readonly CONTROL_DEVICE_SUMMARY = 'Control device'; + public static readonly CONTROL_DEVICE_DESCRIPTION = + 'This endpoint allows control operations (like power on/off) on a specific device.'; + + public static readonly UPDATE_DEVICE_FIRMWARE_SUMMARY = + 'Update device firmware'; + public static readonly UPDATE_DEVICE_FIRMWARE_DESCRIPTION = + 'This endpoint updates the firmware of a specific device to the provided version.'; + + public static readonly GET_DEVICES_IN_GATEWAY_SUMMARY = + 'Get devices in gateway'; + public static readonly GET_DEVICES_IN_GATEWAY_DESCRIPTION = + 'This endpoint retrieves all devices associated with a specific gateway.'; + + public static readonly GET_ALL_DEVICES_SUMMARY = 'Get all devices'; + public static readonly GET_ALL_DEVICES_DESCRIPTION = + 'This endpoint retrieves all devices in the system.'; + + public static readonly GET_DEVICE_LOGS_SUMMARY = 'Get device logs'; + public static readonly GET_DEVICE_LOGS_DESCRIPTION = + 'This endpoint retrieves the logs for a specific device based on device UUID.'; + + public static readonly BATCH_CONTROL_DEVICES_SUMMARY = + 'Batch control devices'; + public static readonly BATCH_CONTROL_DEVICES_DESCRIPTION = + 'This endpoint controls a batch of devices with the specified actions.'; + + public static readonly BATCH_STATUS_DEVICES_SUMMARY = + 'Batch status devices'; + public static readonly BATCH_STATUS_DEVICES_DESCRIPTION = + 'This endpoint retrieves the status of a batch of devices.'; + + public static readonly BATCH_FACTORY_RESET_DEVICES_SUMMARY = + 'Batch factory reset devices'; + public static readonly BATCH_FACTORY_RESET_DEVICES_DESCRIPTION = + 'This endpoint performs a factory reset on a batch of devices.'; + + public static readonly GET_POWER_CLAMP_STATUS_SUMMARY = + 'Get power clamp status'; + public static readonly GET_POWER_CLAMP_STATUS_DESCRIPTION = + 'This endpoint retrieves the status of a specific power clamp device.'; + + public static readonly ADD_SCENE_TO_DEVICE_SUMMARY = + 'Add scene to device (4 Scene and 6 Scene devices only)'; + public static readonly ADD_SCENE_TO_DEVICE_DESCRIPTION = + 'This endpoint adds a scene to a specific switch device.'; + + public static readonly GET_SCENES_BY_DEVICE_SUMMARY = + 'Get scenes by device (4 Scene and 6 Scene devices only)'; + public static readonly GET_SCENES_BY_DEVICE_DESCRIPTION = + 'This endpoint retrieves all scenes associated with a specific switch device.'; + }; + }; + + static DEVICE_PERMISSION = class { + public static readonly ROUTE = 'device-permission'; + + static ACTIONS = class { + public static readonly ADD_PERMISSION_SUMMARY = + 'Add user permission for device'; + public static readonly ADD_PERMISSION_DESCRIPTION = + 'This endpoint adds a user permission for a specific device. Accessible only by users with the Super Admin role.'; + + public static readonly EDIT_PERMISSION_SUMMARY = + 'Edit user permission for device'; + public static readonly EDIT_PERMISSION_DESCRIPTION = + 'This endpoint updates a user permission for a specific device. Accessible only by users with the Super Admin role.'; + + public static readonly FETCH_PERMISSION_SUMMARY = + 'Fetch user permission for device'; + public static readonly FETCH_PERMISSION_DESCRIPTION = + 'This endpoint retrieves the user permission for a specific device. Accessible only by users with the Super Admin role.'; + + public static readonly DELETE_PERMISSION_SUMMARY = + 'Delete user permission for device'; + public static readonly DELETE_PERMISSION_DESCRIPTION = + 'This endpoint deletes the user permission for a specific device. Accessible only by users with the Super Admin role.'; + }; + }; + + static USER_NOTIFICATION = class { + public static readonly ROUTE = 'user-notification/subscription'; + + static ACTIONS = class { + public static readonly ADD_SUBSCRIPTION_SUMMARY = + 'Add user notification subscription'; + public static readonly ADD_SUBSCRIPTION_DESCRIPTION = + 'This endpoint adds a subscription for user notifications.'; + + public static readonly FETCH_SUBSCRIPTIONS_SUMMARY = + 'Fetch user notification subscriptions'; + public static readonly FETCH_SUBSCRIPTIONS_DESCRIPTION = + 'This endpoint retrieves the subscriptions of a specific user based on their UUID.'; + + public static readonly UPDATE_SUBSCRIPTION_SUMMARY = + 'Update user notification subscription'; + public static readonly UPDATE_SUBSCRIPTION_DESCRIPTION = + 'This endpoint updates the notification subscription details for a user.'; + }; + }; + + static AUTOMATION = class { + public static readonly ROUTE = 'automation'; + + static ACTIONS = class { + public static readonly ADD_AUTOMATION_SUMMARY = 'Add automation'; + public static readonly ADD_AUTOMATION_DESCRIPTION = + 'This endpoint creates a new automation based on the provided details.'; + + public static readonly GET_AUTOMATION_BY_SPACE_SUMMARY = + 'Get automation by space'; + public static readonly GET_AUTOMATION_BY_SPACE_DESCRIPTION = + 'This endpoint retrieves the automations associated with a particular space.'; + + public static readonly GET_AUTOMATION_DETAILS_SUMMARY = + 'Get automation details'; + public static readonly GET_AUTOMATION_DETAILS_DESCRIPTION = + 'This endpoint retrieves detailed information about a specific automation.'; + + public static readonly DELETE_AUTOMATION_SUMMARY = 'Delete automation'; + public static readonly DELETE_AUTOMATION_DESCRIPTION = + 'This endpoint deletes an automation identified by its UUID.'; + + public static readonly UPDATE_AUTOMATION_SUMMARY = 'Update automation'; + public static readonly UPDATE_AUTOMATION_DESCRIPTION = + 'This endpoint updates the details of an existing automation.'; + + public static readonly UPDATE_AUTOMATION_STATUS_SUMMARY = + 'Update automation status'; + public static readonly UPDATE_AUTOMATION_STATUS_DESCRIPTION = + 'This endpoint updates the status of an automation identified by its UUID (enabled/disabled).'; + }; + }; + + static DOOR_LOCK = class { + public static readonly ROUTE = 'door-lock'; + + static ACTIONS = class { + public static readonly ADD_ONLINE_TEMPORARY_PASSWORD_SUMMARY = + 'Add online temporary password'; + public static readonly ADD_ONLINE_TEMPORARY_PASSWORD_DESCRIPTION = + 'This endpoint allows you to add an online temporary password to a door lock.'; + + public static readonly ADD_OFFLINE_ONE_TIME_TEMPORARY_PASSWORD_SUMMARY = + 'Add offline one-time temporary password'; + public static readonly ADD_OFFLINE_ONE_TIME_TEMPORARY_PASSWORD_DESCRIPTION = + 'This endpoint allows you to add an offline one-time temporary password to a door lock.'; + + public static readonly ADD_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORD_SUMMARY = + 'Add offline multiple-time temporary password'; + public static readonly ADD_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORD_DESCRIPTION = + 'This endpoint allows you to add an offline multiple-time temporary password to a door lock.'; + + public static readonly GET_ONLINE_TEMPORARY_PASSWORDS_SUMMARY = + 'Get online temporary passwords'; + public static readonly GET_ONLINE_TEMPORARY_PASSWORDS_DESCRIPTION = + 'This endpoint retrieves the list of online temporary passwords for a door lock.'; + + public static readonly DELETE_ONLINE_TEMPORARY_PASSWORD_SUMMARY = + 'Delete online temporary password'; + public static readonly DELETE_ONLINE_TEMPORARY_PASSWORD_DESCRIPTION = + 'This endpoint deletes an online temporary password for a door lock.'; + + public static readonly GET_OFFLINE_ONE_TIME_TEMPORARY_PASSWORDS_SUMMARY = + 'Get offline one-time temporary passwords'; + public static readonly GET_OFFLINE_ONE_TIME_TEMPORARY_PASSWORDS_DESCRIPTION = + 'This endpoint retrieves the list of offline one-time temporary passwords for a door lock.'; + + public static readonly GET_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORDS_SUMMARY = + 'Get offline multiple-time temporary passwords'; + public static readonly GET_OFFLINE_MULTIPLE_TIME_TEMPORARY_PASSWORDS_DESCRIPTION = + 'This endpoint retrieves the list of offline multiple-time temporary passwords for a door lock.'; + + public static readonly UPDATE_OFFLINE_TEMPORARY_PASSWORD_SUMMARY = + 'Update offline temporary password'; + public static readonly UPDATE_OFFLINE_TEMPORARY_PASSWORD_DESCRIPTION = + 'This endpoint updates an offline temporary password for a door lock.'; + + public static readonly OPEN_DOOR_LOCK_SUMMARY = 'Open door lock'; + public static readonly OPEN_DOOR_LOCK_DESCRIPTION = + 'This endpoint allows you to open a door lock.'; + }; + }; + static TIMEZONE = class { + public static readonly ROUTE = 'timezone'; + + static ACTIONS = class { + public static readonly GET_ALL_TIME_ZONES_SUMMARY = 'Get all time zones'; + public static readonly GET_ALL_TIME_ZONES_DESCRIPTION = + 'This endpoint retrieves all available time zones.'; + }; + }; + static VISITOR_PASSWORD = class { + public static readonly ROUTE = 'visitor-password'; + + static ACTIONS = class { + public static readonly ADD_ONLINE_TEMP_PASSWORD_MULTIPLE_TIME_SUMMARY = + 'Add online temporary passwords (multiple-time)'; + public static readonly ADD_ONLINE_TEMP_PASSWORD_MULTIPLE_TIME_DESCRIPTION = + 'This endpoint adds multiple online temporary passwords for door locks.'; + + public static readonly ADD_ONLINE_TEMP_PASSWORD_ONE_TIME_SUMMARY = + 'Add online temporary password (one-time)'; + public static readonly ADD_ONLINE_TEMP_PASSWORD_ONE_TIME_DESCRIPTION = + 'This endpoint adds a one-time online temporary password for a door lock.'; + + public static readonly ADD_OFFLINE_TEMP_PASSWORD_ONE_TIME_SUMMARY = + 'Add offline temporary password (one-time)'; + public static readonly ADD_OFFLINE_TEMP_PASSWORD_ONE_TIME_DESCRIPTION = + 'This endpoint adds a one-time offline temporary password for a door lock.'; + + public static readonly ADD_OFFLINE_TEMP_PASSWORD_MULTIPLE_TIME_SUMMARY = + 'Add offline temporary passwords (multiple-time)'; + public static readonly ADD_OFFLINE_TEMP_PASSWORD_MULTIPLE_TIME_DESCRIPTION = + 'This endpoint adds multiple offline temporary passwords for door locks.'; + + public static readonly GET_VISITOR_PASSWORD_SUMMARY = + 'Get visitor passwords'; + public static readonly GET_VISITOR_PASSWORD_DESCRIPTION = + 'This endpoint retrieves all visitor passwords.'; + + public static readonly GET_VISITOR_DEVICES_SUMMARY = + 'Get visitor devices'; + public static readonly GET_VISITOR_DEVICES_DESCRIPTION = + 'This endpoint retrieves all devices associated with visitor passwords.'; + }; + }; + static SCHEDULE = class { + public static readonly ROUTE = 'schedule'; + + static ACTIONS = class { + public static readonly ADD_DEVICE_SCHEDULE_SUMMARY = + 'Add device schedule'; + public static readonly ADD_DEVICE_SCHEDULE_DESCRIPTION = + 'This endpoint allows you to add a schedule for a specific device.'; + + public static readonly GET_DEVICE_SCHEDULE_BY_CATEGORY_SUMMARY = + 'Get device schedule by category'; + public static readonly GET_DEVICE_SCHEDULE_BY_CATEGORY_DESCRIPTION = + 'This endpoint retrieves the schedule for a specific device based on the given category.'; + + public static readonly DELETE_DEVICE_SCHEDULE_SUMMARY = + 'Delete device schedule'; + public static readonly DELETE_DEVICE_SCHEDULE_DESCRIPTION = + 'This endpoint deletes a specific schedule for a device.'; + + public static readonly ENABLE_DEVICE_SCHEDULE_SUMMARY = + 'Enable device schedule'; + public static readonly ENABLE_DEVICE_SCHEDULE_DESCRIPTION = + 'This endpoint enables a device schedule for a specific device.'; + + public static readonly UPDATE_DEVICE_SCHEDULE_SUMMARY = + 'Update device schedule'; + public static readonly UPDATE_DEVICE_SCHEDULE_DESCRIPTION = + 'This endpoint updates the schedule for a specific device.'; + }; + }; + static DEVICE_STATUS_FIREBASE = class { + public static readonly ROUTE = 'device-status-firebase'; + + static ACTIONS = class { + public static readonly ADD_DEVICE_STATUS_SUMMARY = + 'Add device status to Firebase'; + public static readonly ADD_DEVICE_STATUS_DESCRIPTION = + 'This endpoint adds a device status in Firebase based on the provided device UUID.'; + + public static readonly GET_DEVICE_STATUS_SUMMARY = + 'Get device status from Firebase'; + public static readonly GET_DEVICE_STATUS_DESCRIPTION = + 'This endpoint retrieves a device status from Firebase using the device UUID.'; + }; + }; + static DEVICE_MESSAGES_SUBSCRIPTION = class { + public static readonly ROUTE = 'device-messages/subscription'; + + static ACTIONS = class { + public static readonly ADD_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY = + 'Add device messages subscription'; + public static readonly ADD_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION = + 'This endpoint adds a subscription for device messages.'; + + public static readonly GET_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY = + 'Get device messages subscription'; + public static readonly GET_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION = + 'This endpoint fetches a user’s subscription for a specific device.'; + + public static readonly DELETE_DEVICE_MESSAGES_SUBSCRIPTION_SUMMARY = + 'Delete device messages subscription'; + public static readonly DELETE_DEVICE_MESSAGES_SUBSCRIPTION_DESCRIPTION = + 'This endpoint deletes a user’s subscription for device messages.'; + }; + }; } From 4d0c91db19225be4d0f66ca92a5d896411d1c69d Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:58:44 -0600 Subject: [PATCH 17/19] fix delete scene issue --- src/scene/services/scene.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scene/services/scene.service.ts b/src/scene/services/scene.service.ts index 9c5791b..33bc44e 100644 --- a/src/scene/services/scene.service.ts +++ b/src/scene/services/scene.service.ts @@ -459,6 +459,7 @@ export class SceneService { const space = await this.getSpaceByUuid(scene.spaceUuid); await this.delete(scene.sceneTuyaUuid, space.spaceTuyaUuid); + await this.sceneRepository.delete({ uuid: sceneUuid }); return new SuccessResponseDto({ message: `Scene with ID ${sceneUuid} deleted successfully`, }); From 6b66bf2b20d232bfc749d5bf20fa592f32532a79 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:09:21 -0600 Subject: [PATCH 18/19] fix automation get endpoint remove return Auto_ --- libs/common/src/constants/automation.enum.ts | 3 ++- src/automation/services/automation.service.ts | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libs/common/src/constants/automation.enum.ts b/libs/common/src/constants/automation.enum.ts index e9bb6a8..8370cf9 100644 --- a/libs/common/src/constants/automation.enum.ts +++ b/libs/common/src/constants/automation.enum.ts @@ -1,4 +1,3 @@ -// automation.enum.ts export enum ActionExecutorEnum { DEVICE_ISSUE = 'device_issue', DELAY = 'delay', @@ -17,3 +16,5 @@ export const AUTOMATION_CONFIG = { COMPARATOR: '==', SCENE_STATUS_VALUE: 'scene', }; +export const AUTOMATION_TYPE = 'automation'; +export const AUTO_PREFIX = 'Auto_'; diff --git a/src/automation/services/automation.service.ts b/src/automation/services/automation.service.ts index 27d1b6a..9c805f3 100644 --- a/src/automation/services/automation.service.ts +++ b/src/automation/services/automation.service.ts @@ -26,6 +26,8 @@ import { import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { ActionExecutorEnum, + AUTO_PREFIX, + AUTOMATION_TYPE, EntityTypeEnum, } from '@app/common/constants/automation.enum'; import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service'; @@ -154,14 +156,16 @@ export class AutomationService { throw new HttpException(response.msg, HttpStatus.BAD_REQUEST); } - return response.result.list.map((item) => { - return { - id: item.id, - name: item.name, - status: item.status, - type: 'automation', - }; - }); + return response.result.list + .filter((item) => item.name && !item.name.startsWith(AUTO_PREFIX)) + .map((item) => { + return { + id: item.id, + name: item.name, + status: item.status, + type: AUTOMATION_TYPE, + }; + }); } catch (err) { if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException From 99bacbe2020dee8681709e67f743501e3d792104 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:47:47 -0600 Subject: [PATCH 19/19] finished skip any error from tuya device --- src/device/services/device.service.ts | 29 ++++++++++++------- src/space/services/space-device.service.ts | 17 +++++++---- .../subspace/subspace-device.service.ts | 16 ++++++---- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index eeca08c..0253430 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -172,31 +172,40 @@ export class DeviceService { 'permission.permissionType', ], }); - const devicesData = await Promise.all( - devices.map(async (device) => { + const safeFetchDeviceDetails = async (device: any) => { + try { + const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya( + device.deviceTuyaUuid, + ); + return { - haveRoom: device.spaceDevice ? true : false, + haveRoom: !!device.spaceDevice, productUuid: device.productDevice.uuid, productType: device.productDevice.prodType, permissionType: device.permission[0].permissionType.type, - ...(await this.getDeviceDetailsByDeviceIdTuya( - device.deviceTuyaUuid, - )), + ...tuyaDetails, uuid: device.uuid, } as GetDeviceDetailsInterface; - }), + } catch (error) { + console.warn( + `Skipping device with deviceTuyaUuid: ${device.deviceTuyaUuid} due to error.`, + ); + return null; + } + }; + const devicesData = await Promise.all( + devices.map(safeFetchDeviceDetails), ); - return devicesData; + return devicesData.filter(Boolean); // Remove null or undefined entries } catch (error) { - // Handle the error here + console.error('Error fetching devices by user:', error); throw new HttpException( 'User does not have any devices', HttpStatus.NOT_FOUND, ); } } - async getDevicesBySpaceId( getDeviceBySpaceUuidDto: GetDeviceBySpaceUuidDto, userUuid: string, diff --git a/src/space/services/space-device.service.ts b/src/space/services/space-device.service.ts index df79a5e..4dc24ba 100644 --- a/src/space/services/space-device.service.ts +++ b/src/space/services/space-device.service.ts @@ -26,8 +26,8 @@ export class SpaceDeviceService { spaceUuid, ); - const detailedDevices = await Promise.all( - space.devices.map(async (device) => { + const safeFetch = async (device: any) => { + try { const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya( device.deviceTuyaUuid, ); @@ -41,11 +41,18 @@ export class SpaceDeviceService { updatedAt: device.updatedAt, ...tuyaDetails, }; - }), - ); + } catch (error) { + console.warn( + `Skipping device with deviceTuyaUuid: ${device.deviceTuyaUuid} due to error.`, + ); + return null; + } + }; + + const detailedDevices = await Promise.all(space.devices.map(safeFetch)); return new SuccessResponseDto({ - data: detailedDevices, + data: detailedDevices.filter(Boolean), // Remove null or undefined values message: 'Successfully retrieved list of devices', }); } catch (error) { diff --git a/src/space/services/subspace/subspace-device.service.ts b/src/space/services/subspace/subspace-device.service.ts index 1dac1ee..74f6610 100644 --- a/src/space/services/subspace/subspace-device.service.ts +++ b/src/space/services/subspace/subspace-device.service.ts @@ -33,8 +33,8 @@ export class SubspaceDeviceService { const subspace = await this.findSubspaceWithDevices(subSpaceUuid); - const detailedDevices = await Promise.all( - subspace.devices.map(async (device) => { + const safeFetch = async (device: any) => { + try { const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya( device.deviceTuyaUuid, ); @@ -49,11 +49,17 @@ export class SubspaceDeviceService { updatedAt: device.updatedAt, ...tuyaDetails, }; - }), - ); + } catch (error) { + console.warn( + `Skipping device with deviceTuyaUuid: ${device.deviceTuyaUuid} due to error.`, + ); + return null; + } + }; + const detailedDevices = await Promise.all(subspace.devices.map(safeFetch)); return new SuccessResponseDto({ - data: detailedDevices, + data: detailedDevices.filter(Boolean), // Remove nulls message: 'Successfully retrieved list of devices', }); }