Skip to content

Commit deef73c

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 deef73c

File tree

2 files changed

+77
-23
lines changed

2 files changed

+77
-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: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { InstanceStatus } from '@rocket.chat/models';
2+
import { ajv, validateUnauthorizedErrorResponse, validateForbiddenErrorResponse } from '@rocket.chat/rest-typings';
23

34
import { isRunningMs } from '../../../../server/lib/isRunningMs';
45
import { API } from '../api';
@@ -12,33 +13,81 @@ const getConnections = (() => {
1213
return () => getInstanceList();
1314
})();
1415

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

0 commit comments

Comments
 (0)