import express from "express" ;
import { z } from "zod" ;
const listQuery = z. object ({
limit: z.coerce. number (). int (). min ( 1 ). max ( 100 ). default ( 20 ),
cursor: z. string (). optional (),
status: z. enum ([ "pending" , "shipped" ]). optional (),
customerId: z. string (). uuid (). optional (),
});
type Order = { id : string ; customerId : string ; status : string ; createdAt : Date };
function encodeCursor ( id : string ) : string {
return Buffer. from ( JSON . stringify ({ id }), "utf8" ). toString ( "base64url" );
}
function decodeCursor ( cursor : string ) : { id : string } {
return JSON . parse (Buffer. from (cursor, "base64url" ). toString ( "utf8" ));
}
async function listOrders ( opts : {
limit : number ;
cursor ?: string ;
status ?: string ;
customerId ?: string ;
}) : Promise <{ rows : Order []; nextCursor ?: string }> {
// Stand-in em memória simplificado para SQL: WHERE (id > cursorId) ORDER BY id LIMIT n+1
const all : Order [] = [
{ id: "ord_1" , customerId: "c1" , status: "pending" , createdAt: new Date () },
{ id: "ord_2" , customerId: "c1" , status: "shipped" , createdAt: new Date () },
{ id: "ord_3" , customerId: "c2" , status: "pending" , createdAt: new Date () },
];
let filtered = all;
if (opts.status) filtered = filtered. filter (( o ) => o.status === opts.status);
if (opts.customerId) filtered = filtered. filter (( o ) => o.customerId === opts.customerId);
if (opts.cursor) {
const { id } = decodeCursor (opts.cursor);
filtered = filtered. filter (( o ) => o.id > id);
}
filtered. sort (( a , b ) => a.id. localeCompare (b.id));
const slice = filtered. slice ( 0 , opts.limit + 1 );
const hasMore = slice. length > opts.limit;
const rows = hasMore ? slice. slice ( 0 , opts.limit) : slice;
const nextCursor = hasMore ? encodeCursor (rows[rows. length - 1 ] ! .id) : undefined ;
return { rows, nextCursor };
}
const app = express ();
app. get ( "/v1/orders" , async ( req , res ) => {
const parsed = listQuery. safeParse (req.query);
if ( ! parsed.success) {
return res. status ( 400 ). json ({ error: { code: "VALIDATION_ERROR" } });
}
const { rows , nextCursor } = await listOrders (parsed.data);
res. setHeader ( "RateLimit-Limit" , "1000" );
res. setHeader ( "RateLimit-Remaining" , String ( 999 ));
res. json ({
data: rows,
meta: { limit: parsed.data.limit, nextCursor, hasMore: Boolean (nextCursor) },
});
});