Skip to content

Commit ea4fea9

Browse files
Refactor pagination logic and enhance test cases for improved clarity and functionality
1 parent 4d6da7b commit ea4fea9

File tree

2 files changed

+61
-51
lines changed

2 files changed

+61
-51
lines changed

src/lib/server.ts

+50-44
Original file line numberDiff line numberDiff line change
@@ -165,30 +165,48 @@ export class JsonServer {
165165
* @param collection - Data collection to paginate
166166
* @param page - Current page number (default: 1)
167167
* @param perPage - Items per page (default: 10)
168-
* @returns Object with pagination metadata and data
168+
* @returns Paginated data with metadata
169169
*/
170170
private getPaginatedData(
171171
collection: any[],
172172
page: number = 1,
173173
perPage: number = 10
174174
): Record<string, any> {
175175
// Ensure valid page and perPage values
176-
page = Math.max(1, page);
177-
perPage = Math.max(1, perPage);
178-
176+
page = Math.max(1, parseInt(String(page)) || 1);
177+
perPage = Math.max(1, parseInt(String(perPage)) || 10);
178+
179179
const total = collection.length;
180+
const totalPages = Math.ceil(total / perPage);
180181
const start = (page - 1) * perPage;
181182
const end = Math.min(start + perPage, total);
182-
const data = collection.slice(start, end);
183183

184-
const paginationMeta = this.createPaginationMetadata(total, page, perPage);
184+
// Get the data slice for the current page
185+
const data = collection.slice(start, end);
185186

186187
return {
187-
...paginationMeta,
188188
data,
189+
first: 1,
190+
prev: page > 1 ? page - 1 : null,
191+
next: page < totalPages ? page + 1 : null,
192+
last: totalPages || 1,
193+
pages: totalPages || 1,
194+
items: total,
189195
};
190196
}
191197

198+
/**
199+
* Checks if pagination should continue based on current page and total items
200+
*
201+
* @param currentPage - Current page number
202+
* @param pageSize - Number of items per page
203+
* @param totalItems - Total number of items in the collection
204+
* @returns Boolean indicating if there are more pages
205+
*/
206+
continueToIterate(currentPage: number, pageSize: number, totalItems: number): boolean {
207+
return currentPage * pageSize < totalItems;
208+
}
209+
192210
/**
193211
* Get paginated resources from a collection
194212
*
@@ -205,53 +223,34 @@ export class JsonServer {
205223
if (!this.db[resourceName]) {
206224
return {
207225
data: [],
208-
pagination: {
209-
currentPage: page,
210-
pageSize,
211-
totalItems: 0,
212-
totalPages: 0,
213-
hasMore: false,
214-
},
226+
first: 1,
227+
prev: null,
228+
next: null,
229+
last: 1,
230+
pages: 1,
231+
items: 0,
215232
};
216233
}
217234

218235
const collection = this.db[resourceName];
219236
const totalItems = collection.length;
220-
const totalPages = Math.ceil(totalItems / pageSize);
221237

222-
const start = (page - 1) * pageSize;
223-
const end = start + pageSize;
238+
// Ensure page and pageSize are valid numbers
239+
page = Math.max(1, parseInt(String(page), 10) || 1);
240+
pageSize = Math.max(1, parseInt(String(pageSize), 10) || 10);
224241

242+
const start = (page - 1) * pageSize;
243+
const end = Math.min(start + pageSize, totalItems);
225244
const data = collection.slice(start, end);
226245

246+
const paginationMeta = this.createPaginationMetadata(totalItems, page, pageSize);
247+
227248
return {
228-
data,
229-
pagination: {
230-
currentPage: page,
231-
pageSize,
232-
totalItems,
233-
totalPages,
234-
hasMore: this.continueToIterate(page, pageSize, totalItems),
235-
},
249+
data: data,
250+
...paginationMeta,
236251
};
237252
}
238253

239-
/**
240-
* Determines if pagination should continue to next page
241-
*
242-
* @param currentPage - Current page number
243-
* @param pageSize - Items per page
244-
* @param totalItems - Total number of items
245-
* @returns Boolean indicating if there are more pages to iterate
246-
*/
247-
continueToIterate(currentPage: number, pageSize: number, totalItems: number): boolean {
248-
// Calculate total number of pages
249-
const totalPages = Math.ceil(totalItems / pageSize);
250-
251-
// Check if current page is less than total pages
252-
return currentPage < totalPages;
253-
}
254-
255254
/**
256255
* Load database from JSON file
257256
*
@@ -421,9 +420,16 @@ export class JsonServer {
421420
const page = pageParam ? Math.max(1, parseInt(pageParam as string) || 1) : 1;
422421
const perPage = perPageParam ? Math.max(1, parseInt(perPageParam as string) || 10) : 10;
423422

424-
// Apply pagination and return the paginated result
425-
const paginatedData = this.getPaginatedData(filteredData, page, perPage);
426-
return res.json(paginatedData);
423+
// Get paginated data with proper metadata using the getPaginatedData method
424+
const paginatedResult = this.getPaginatedData(filteredData, page, perPage);
425+
426+
// Set pagination headers
427+
res.setHeader('X-Total-Count', paginatedResult.items.toString());
428+
res.setHeader('X-Total-Pages', paginatedResult.pages.toString());
429+
res.setHeader('Access-Control-Expose-Headers', 'X-Total-Count, X-Total-Pages');
430+
431+
// Return the paginated result
432+
return res.json(paginatedResult);
427433
}
428434

429435
res.json(filteredData);

test/debug-pagination.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ const express = require('express');
66
const testDb = {
77
items: Array.from({ length: 100 }, (_, i) => ({
88
id: String(i + 1),
9-
name: `Item ${i + 1}`
10-
}))
9+
name: `Item ${i + 1}`,
10+
})),
1111
};
1212

1313
// Create server instance
@@ -17,7 +17,7 @@ const options = {
1717
quiet: true,
1818
readOnly: false,
1919
bodyParser: true,
20-
noCors: false
20+
noCors: false,
2121
};
2222

2323
const server = new JsonServer(options);
@@ -41,16 +41,20 @@ async function testPagination() {
4141
console.log('Response with _page and _per_page:');
4242
console.log(`Status: ${response1.status}`);
4343
console.log(`Data length: ${response1.body.data ? response1.body.data.length : 'N/A'}`);
44-
console.log(`First item ID: ${response1.body.data && response1.body.data[0] ? response1.body.data[0].id : 'N/A'}`);
44+
console.log(
45+
`First item ID: ${response1.body.data && response1.body.data[0] ? response1.body.data[0].id : 'N/A'}`
46+
);
4547
console.log('Full response:', JSON.stringify(response1.body, null, 2));
46-
48+
4749
console.log('\nTesting pagination with only _per_page parameter');
4850
const response2 = await request(app).get('/items?_per_page=10');
4951
console.log('Response with only _per_page:');
5052
console.log(`Status: ${response2.status}`);
5153
console.log(`Data length: ${response2.body.data ? response2.body.data.length : 'N/A'}`);
52-
console.log(`First item ID: ${response2.body.data && response2.body.data[0] ? response2.body.data[0].id : 'N/A'}`);
54+
console.log(
55+
`First item ID: ${response2.body.data && response2.body.data[0] ? response2.body.data[0].id : 'N/A'}`
56+
);
5357
console.log('Full response:', JSON.stringify(response2.body, null, 2));
5458
}
5559

56-
testPagination().catch(console.error);
60+
testPagination().catch(console.error);

0 commit comments

Comments
 (0)