Skip to content

Commit 799b34f

Browse files
wrapping devices in a pagable wrapper
1 parent b647139 commit 799b34f

2 files changed

Lines changed: 107 additions & 10 deletions

File tree

src/devices/devices.controller.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ export class DevicesController {
6363
Returns all devices for the authenticated user.`,
6464
})
6565
findAll(@Req() req) {
66-
return this.devicesService.findAll(req.user, req.headers.authorization);
66+
const parsedSkip = parseInt(req.query.skip, 10);
67+
const parsedTake = parseInt(req.query.take, 10);
68+
const skip = Number.isNaN(parsedSkip) ? 0 : parsedSkip;
69+
const take = Number.isNaN(parsedTake) ? undefined : parsedTake;
70+
return this.devicesService.findAll(req.user, req.headers.authorization, skip, take);
6771
}
6872

6973
@Get('latest-primary-data')

src/devices/devices.service.ts

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,65 @@ import {
88
import { SupabaseService } from '../supabase/supabase.service';
99
import type { TableRow } from '../types/supabase';
1010

11+
export interface PagedDevicesResponse<T> {
12+
total: number;
13+
skip: number;
14+
take: number;
15+
data: T[];
16+
}
17+
1118
@Injectable()
1219
export class DevicesService {
1320

1421
constructor(private readonly supabaseService: SupabaseService) { }
1522

16-
async findAll(jwtPayload: any, authHeader: string): Promise<TableRow<'cw_devices'>[]> {
23+
async findAll(
24+
jwtPayload: any,
25+
authHeader: string,
26+
skip: number = 0,
27+
take?: number,
28+
): Promise<PagedDevicesResponse<TableRow<'cw_devices'>>> {
1729
const accessToken = this.getAccessToken(authHeader);
1830
const client = this.supabaseService.getClient(accessToken);
1931
const userId = this.getUserId(jwtPayload);
2032

21-
const { data, error } = await client
33+
const { count, error: countError } = await client
34+
.from('cw_devices')
35+
.select('*', { count: 'exact', head: true })
36+
.eq('user_id', userId);
37+
38+
if (countError) {
39+
throw new InternalServerErrorException('Failed to fetch devices');
40+
}
41+
42+
const resolvedTake = typeof take === 'number' ? take : (count ?? 0);
43+
44+
let devicesQuery = client
2245
.from('cw_devices')
2346
.select('*')
2447
.eq('user_id', userId)
2548
.order('name', { ascending: true });
2649

50+
if (resolvedTake > 0) {
51+
devicesQuery = devicesQuery
52+
.range(skip, skip + resolvedTake - 1)
53+
.limit(resolvedTake);
54+
}
55+
56+
const { data, error } = await devicesQuery;
57+
2758
if (error) {
2859
throw new InternalServerErrorException('Failed to fetch devices');
2960
}
3061

31-
return data ?? [];
62+
const responseTake = typeof take === 'number' ? take : (count ?? data?.length ?? 0);
63+
64+
return {
65+
total: count ?? 0,
66+
skip,
67+
take: responseTake,
68+
data: data ?? [],
69+
};
3270
}
3371

3472
async findOne(
@@ -62,7 +100,13 @@ export class DevicesService {
62100
return data;
63101
}
64102

65-
public async findData(jwtPayload: any, devEui: string, skip: number = 0, take: number = 144, authHeader: string) {
103+
public async findData(
104+
jwtPayload: any,
105+
devEui: string,
106+
skip: number = 0,
107+
take: number = 144,
108+
authHeader: string,
109+
): Promise<PagedDevicesResponse<any>> {
66110
const accessToken = this.getAccessToken(authHeader);
67111
const client = this.supabaseService.getClient(accessToken);
68112
const userId = this.getUserId(jwtPayload);
@@ -100,6 +144,15 @@ export class DevicesService {
100144
throw new NotFoundException('Device type not found');
101145
}
102146

147+
const { count, error: countError } = await client
148+
.from(deviceType.data_table_v2)
149+
.select('*', { count: 'exact', head: true })
150+
.eq('dev_eui', normalizedDevEui);
151+
152+
if (countError) {
153+
throw new InternalServerErrorException('Failed to fetch Data');
154+
}
155+
103156
const { data: latestData, error: dataError } = await client
104157
.from(deviceType.data_table_v2)
105158
.select('*')
@@ -116,7 +169,12 @@ export class DevicesService {
116169
throw new NotFoundException('Data not found');
117170
}
118171

119-
return latestData;
172+
return {
173+
total: count ?? 0,
174+
skip,
175+
take,
176+
data: latestData,
177+
};
120178
}
121179

122180
public async findDataWithinRange(
@@ -127,7 +185,7 @@ export class DevicesService {
127185
end: Date | string = new Date().toISOString(),
128186
skip: number = 0,
129187
take: number = 144,
130-
) {
188+
): Promise<PagedDevicesResponse<any>> {
131189
const accessToken = this.getAccessToken(authHeader);
132190
const client = this.supabaseService.getClient(accessToken);
133191
const userId = this.getUserId(jwtPayload);
@@ -168,6 +226,17 @@ export class DevicesService {
168226
const startDate = new Date(start);
169227
const endDate = new Date(end);
170228

229+
const { count, error: countError } = await client
230+
.from(deviceType.data_table_v2)
231+
.select('*', { count: 'exact', head: true })
232+
.eq('dev_eui', normalizedDevEui)
233+
.gte('created_at', startDate.toISOString())
234+
.lte('created_at', endDate.toISOString());
235+
236+
if (countError) {
237+
throw new InternalServerErrorException('Failed to fetch Data');
238+
}
239+
171240
const { data: latestData, error: dataError } = await client
172241
.from(deviceType.data_table_v2)
173242
.select('*')
@@ -185,14 +254,33 @@ export class DevicesService {
185254
throw new NotFoundException('Data not found');
186255
}
187256

188-
return latestData;
257+
return {
258+
total: count ?? 0,
259+
skip,
260+
take,
261+
data: latestData,
262+
};
189263
}
190264

191-
public async findAllLatestData(jwtPayload: any, skip: number = 0, take: number = 10, authHeader: string) {
265+
public async findAllLatestData(
266+
jwtPayload: any,
267+
skip: number = 0,
268+
take: number = 10,
269+
authHeader: string,
270+
): Promise<PagedDevicesResponse<any>> {
192271
const accessToken = this.getAccessToken(authHeader);
193272
const client = this.supabaseService.getClient(accessToken);
194273
const userId = this.getUserId(jwtPayload);
195274

275+
const { count, error: countError } = await client
276+
.from('cw_devices')
277+
.select('*', { count: 'exact', head: true })
278+
.eq('user_id', userId);
279+
280+
if (countError) {
281+
throw new InternalServerErrorException('Failed to fetch device');
282+
}
283+
196284
const { data: device, error: deviceError } = await client
197285
.from('cw_devices')
198286
.select('*, cw_device_type(*), cw_locations(name)')
@@ -243,7 +331,12 @@ export class DevicesService {
243331
})
244332
);
245333

246-
return devicesWithLatestData;
334+
return {
335+
total: count ?? 0,
336+
skip,
337+
take,
338+
data: devicesWithLatestData,
339+
};
247340
}
248341

249342
public async findLatestData(jwtPayload: any, devEui: string, authHeader: string, primaryAndSecondaryOnly = false) {

0 commit comments

Comments
 (0)