Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 40 additions & 21 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,33 +102,52 @@ const server = createServer(async (req, res) => {
}

if (method === 'GET' && path === '/api/orders') {
const spotId = parsedUrl.searchParams.get('spotId');
const userId = parsedUrl.searchParams.get('userId');
const spotId = parsedUrl.searchParams.get('spotId');
const userId = parsedUrl.searchParams.get('userId');

const orders = database.getOrders({ spotId, userId });
sendJson(res, 200, orders);
return;
const limitParam = parsedUrl.searchParams.get('limit');
const offsetParam = parsedUrl.searchParams.get('offset');

let limit = 10; // default page size
let offset = 0; // default start

// Validate pagination params if provided
if (limitParam !== null) {
limit = Number(limitParam);
if (!Number.isInteger(limit) || limit <= 0) {
sendJson(res, 400, { error: 'Invalid limit parameter' });
return;
}
}
if (method === 'GET' && path.startsWith('/api/orders/')) {
console.log("I AM INSIDE ORDER ID ROUTE");
const orderId = path.replace('/api/orders/', '');


const authHeader = req.headers.authorization;
if (!authHeader) {
sendJson(res, 401, { error: 'Unauthorized' });
return;

if (offsetParam !== null) {
offset = Number(offsetParam);
if (!Number.isInteger(offset) || offset < 0) {
sendJson(res, 400, { error: 'Invalid offset parameter' });
Comment on lines +123 to +126
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reject empty/whitespace offset as malformed.

Line 124 uses Number(offsetParam), so ?offset= and ?offset= are coerced to 0 and currently pass. That conflicts with the “malformed values return 400” behavior.

Suggested fix
   if (offsetParam !== null) {
-    offset = Number(offsetParam);
-    if (!Number.isInteger(offset) || offset < 0) {
+    if (!/^\d+$/.test(offsetParam)) {
+      sendJson(res, 400, { error: 'Invalid offset parameter' });
+      return;
+    }
+    offset = Number(offsetParam);
+    if (!Number.isInteger(offset) || offset < 0) {
       sendJson(res, 400, { error: 'Invalid offset parameter' });
       return;
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (offsetParam !== null) {
offset = Number(offsetParam);
if (!Number.isInteger(offset) || offset < 0) {
sendJson(res, 400, { error: 'Invalid offset parameter' });
if (offsetParam !== null) {
if (!/^\d+$/.test(offsetParam)) {
sendJson(res, 400, { error: 'Invalid offset parameter' });
return;
}
offset = Number(offsetParam);
if (!Number.isInteger(offset) || offset < 0) {
sendJson(res, 400, { error: 'Invalid offset parameter' });
return;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/server.js` around lines 123 - 126, The offset parsing currently
coerces empty or whitespace-only values to 0 because it calls
Number(offsetParam); update the validation in the block that reads offsetParam
(the code that sets offset = Number(offsetParam) and calls sendJson) to first
reject empty or whitespace-only strings by checking something like if (typeof
offsetParam === 'string' && offsetParam.trim() === '') then call sendJson(res,
400, { error: 'Invalid offset parameter' }) before converting to Number; keep
the existing integer and non-negative checks for offset after conversion.

return;
}
}

const orders = database.getOrders({});
const order = orders.find(o => o.id === orderId);
// Get full filtered result first
const allOrders = database.getOrders({ spotId, userId });

if (!order) {
sendJson(res, 404, { error: `Order not found: ${orderId}` });
return;
}
const total = allOrders.length;

// Apply pagination
const paginatedOrders = allOrders.slice(offset, offset + limit);

Comment on lines +131 to +138
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move pagination to the database layer to avoid full fetches.

Line 132 fetches all filtered orders, then Line 137 slices in memory. Per backend/db.js (getOrders, lines 163-330), this means loading and mapping every matched order (and items) before pagination, which defeats scalability and can block the request path under larger datasets.

Suggested direction
-  const allOrders = database.getOrders({ spotId, userId });
-  const total = allOrders.length;
-  const paginatedOrders = allOrders.slice(offset, offset + limit);
+  const { data: paginatedOrders, total } = database.getOrders({
+    spotId,
+    userId,
+    limit,
+    offset
+  });

Then update backend/db.js:getOrders to:

  • run COUNT(*) for total
  • run paged select with LIMIT ? OFFSET ?
  • fetch/map items only for paged order IDs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/server.js` around lines 131 - 138, The code currently calls
database.getOrders without pagination and then slices the full result in
server.js, which forces a full fetch and mapping; update database.getOrders (in
backend/db.js) to accept limit and offset, perform a COUNT(*) query to compute
total, run the paged SELECT with LIMIT ? OFFSET ? to fetch only the requested
orders, then fetch/map items only for the paged order IDs; change the server
call (database.getOrders) to pass limit and offset and consume the new return
shape (e.g., { total, orders }) so server.js uses the DB-provided total and
paged orders directly.

const hasMore = offset + limit < total;

sendJson(res, 200, {
data: paginatedOrders,
meta: {
total,
limit,
offset,
hasMore
}
});

sendJson(res, 200, order);
return;
}

Expand Down