Skip to content

Commit 6d1e6dc

Browse files
committed
refactor: migrate instances.get endpoint to new chained API pattern
Migrates the instances.get REST API endpoint from the legacy API.v1.addRoute() pattern to the new chained .get() pattern with: - Typed response schemas for OpenAPI spec generation - Standardized error response validators (401, 403) - Named action function instead of anonymous method Part of #38876
1 parent 3145c41 commit 6d1e6dc

File tree

2 files changed

+81
-23
lines changed

2 files changed

+81
-23
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rocket.chat/meteor': patch
3+
---
4+
5+
refactor: Migrate `instances.get` API endpoint to new chained pattern with response schemas
Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import { InstanceStatus } from '@rocket.chat/models';
2+
import {
3+
ajv,
4+
validateUnauthorizedErrorResponse,
5+
validateForbiddenErrorResponse,
6+
} from '@rocket.chat/rest-typings';
27

38
import { isRunningMs } from '../../../../server/lib/isRunningMs';
49
import { API } from '../api';
@@ -12,33 +17,81 @@ const getConnections = (() => {
1217
return () => getInstanceList();
1318
})();
1419

15-
API.v1.addRoute(
20+
API.v1.get(
1621
'instances.get',
17-
{ authRequired: true, permissionsRequired: ['view-statistics'] },
1822
{
19-
async get() {
20-
const instanceRecords = await InstanceStatus.find().toArray();
21-
22-
const connections = await getConnections();
23-
24-
const result = instanceRecords.map((instanceRecord) => {
25-
const connection = connections.find((c) => c.id === instanceRecord._id);
26-
27-
return {
28-
address: connection?.ipList[0],
23+
authRequired: true,
24+
permissionsRequired: ['view-statistics'],
25+
response: {
26+
200: ajv.compile<{
27+
instances: {
28+
address?: string;
2929
currentStatus: {
30-
connected: connection?.available || false,
31-
lastHeartbeatTime: connection?.lastHeartbeatTime,
32-
local: connection?.local,
30+
connected: boolean;
31+
lastHeartbeatTime?: number;
32+
local?: boolean;
33+
};
34+
instanceRecord: object;
35+
broadcastAuth: boolean;
36+
}[];
37+
}>({
38+
type: 'object',
39+
properties: {
40+
instances: {
41+
type: 'array',
42+
items: {
43+
type: 'object',
44+
properties: {
45+
address: { type: 'string', nullable: true },
46+
currentStatus: {
47+
type: 'object',
48+
properties: {
49+
connected: { type: 'boolean' },
50+
lastHeartbeatTime: { type: 'number', nullable: true },
51+
local: { type: 'boolean', nullable: true },
52+
},
53+
required: ['connected'],
54+
},
55+
instanceRecord: { type: 'object' },
56+
broadcastAuth: { type: 'boolean' },
57+
},
58+
required: ['currentStatus', 'broadcastAuth'],
59+
},
3360
},
34-
instanceRecord,
35-
broadcastAuth: true,
36-
};
37-
});
38-
39-
return API.v1.success({
40-
instances: result,
41-
});
61+
success: {
62+
type: 'boolean',
63+
enum: [true],
64+
},
65+
},
66+
required: ['instances', 'success'],
67+
additionalProperties: false,
68+
}),
69+
401: validateUnauthorizedErrorResponse,
70+
403: validateForbiddenErrorResponse,
4271
},
4372
},
73+
async function action() {
74+
const instanceRecords = await InstanceStatus.find().toArray();
75+
76+
const connections = await getConnections();
77+
78+
const result = instanceRecords.map((instanceRecord) => {
79+
const connection = connections.find((c) => c.id === instanceRecord._id);
80+
81+
return {
82+
address: connection?.ipList[0],
83+
currentStatus: {
84+
connected: connection?.available || false,
85+
lastHeartbeatTime: connection?.lastHeartbeatTime,
86+
local: connection?.local,
87+
},
88+
instanceRecord,
89+
broadcastAuth: true,
90+
};
91+
});
92+
93+
return API.v1.success({
94+
instances: result,
95+
});
96+
},
4497
);

0 commit comments

Comments
 (0)