feat(pagination): add generic typed pagination with ordering to all list endpoints
- add PaginationQueryDto<TOrderBy> generic with orderBy and orderDir fields - add SessionOrderBy, EnvironmentOrderBy, ScenarioOrderBy type aliases - update session, environment, scenario services and controllers to use typed pagination - update MCP list_sessions, list_environments, list_scenarios tools to expose orderBy/orderDir - update tests for all list endpoints to cover page, limit, ordering, and invalid param rejection
This commit is contained in:
+28
-10
@@ -55,9 +55,17 @@ export class McpService {
|
||||
|
||||
server.registerTool(
|
||||
'list_sessions',
|
||||
{ description: 'List all stored sessions (id, sessionName, createdAt, updatedAt)' },
|
||||
async () => {
|
||||
const sessions = await this.sessionService.findAll();
|
||||
{
|
||||
description: 'List all stored sessions (id, sessionName, createdAt, updatedAt), paginated',
|
||||
inputSchema: {
|
||||
page: z.number().int().min(1).optional().describe('Page number (default 1)'),
|
||||
limit: z.number().int().min(1).optional().describe('Items per page (default 20)'),
|
||||
orderBy: z.enum(['id', 'sessionName', 'createdAt', 'updatedAt']).optional().describe('Field to order by (default id)'),
|
||||
orderDir: z.enum(['ASC', 'DESC']).optional().describe('Sort direction (default ASC)'),
|
||||
},
|
||||
},
|
||||
async ({ page, limit, orderBy, orderDir }) => {
|
||||
const sessions = await this.sessionService.findAll({ page, limit, orderBy, orderDir });
|
||||
return { content: [{ type: 'text' as const, text: JSON.stringify(sessions) }] };
|
||||
},
|
||||
);
|
||||
@@ -71,8 +79,8 @@ export class McpService {
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
const sessions = await this.sessionService.findAll();
|
||||
if (!sessions.find(s => s.id === id)) {
|
||||
const { data } = await this.sessionService.findAll();
|
||||
if (!data.find(s => s.id === id)) {
|
||||
return { isError: true, content: [{ type: 'text' as const, text: `Session ${id} not found` }] };
|
||||
}
|
||||
await this.sessionService.remove(id);
|
||||
@@ -84,9 +92,17 @@ export class McpService {
|
||||
|
||||
server.registerTool(
|
||||
'list_environments',
|
||||
{ description: 'List all environments' },
|
||||
async () => {
|
||||
const envs = await this.environmentService.findAll();
|
||||
{
|
||||
description: 'List all environments, paginated',
|
||||
inputSchema: {
|
||||
page: z.number().int().min(1).optional().describe('Page number (default 1)'),
|
||||
limit: z.number().int().min(1).optional().describe('Items per page (default 20)'),
|
||||
orderBy: z.enum(['id', 'name', 'createdAt', 'updatedAt']).optional().describe('Field to order by (default id)'),
|
||||
orderDir: z.enum(['ASC', 'DESC']).optional().describe('Sort direction (default ASC)'),
|
||||
},
|
||||
},
|
||||
async ({ page, limit, orderBy, orderDir }) => {
|
||||
const envs = await this.environmentService.findAll({ page, limit, orderBy, orderDir });
|
||||
return { content: [{ type: 'text' as const, text: JSON.stringify(envs) }] };
|
||||
},
|
||||
);
|
||||
@@ -218,10 +234,12 @@ export class McpService {
|
||||
inputSchema: {
|
||||
page: z.number().int().min(1).optional().describe('Page number (default 1)'),
|
||||
limit: z.number().int().min(1).optional().describe('Items per page (default 20)'),
|
||||
orderBy: z.enum(['id', 'name', 'createdAt', 'updatedAt']).optional().describe('Field to order by (default id)'),
|
||||
orderDir: z.enum(['ASC', 'DESC']).optional().describe('Sort direction (default ASC)'),
|
||||
},
|
||||
},
|
||||
async ({ page, limit }) => {
|
||||
const result = await this.scenarioService.findAll({ page, limit });
|
||||
async ({ page, limit, orderBy, orderDir }) => {
|
||||
const result = await this.scenarioService.findAll({ page, limit, orderBy, orderDir });
|
||||
return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] };
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user