@@ -20,6 +20,8 @@ import { registerRoutes as registerSystemRoutes } from './system'
2020import { registerRoutes as registerBucketsRoutes } from './buckets'
2121import { registerRoutes as registerSnapshotRoutes } from './snapshots'
2222import { APIFactory , ServerAPIContext } from './types'
23+ import { getSystemStatus } from '../../../systemStatus/systemStatus'
24+ import { Component , ExternalStatus } from '@sofie-automation/meteor-lib/dist/api/systemStatus'
2325
2426function restAPIUserEvent (
2527 ctx : Koa . ParameterizedContext <
@@ -193,6 +195,82 @@ koaRouter.get('/', async (ctx, next) => {
193195 await next ( )
194196} )
195197
198+ koaRouter . get ( '/health' , async ( ctx , next ) => {
199+ ctx . type = 'application/json'
200+ const systemStatus = await getSystemStatus ( null )
201+ const coreVersion = systemStatus . _internal . versions [ 'core' ] ?? 'unknown'
202+ const blueprint = Object . keys ( systemStatus . _internal . versions ) . find ( ( component ) =>
203+ component . startsWith ( 'blueprint' )
204+ )
205+ const blueprintsVersion = blueprint ? systemStatus . _internal . versions [ blueprint ] : 'unknown'
206+
207+ interface ComponentStatus {
208+ name : string
209+ updated : string
210+ status : ExternalStatus
211+ version ?: string
212+ components ?: ComponentStatus [ ]
213+ statusMessage ?: string
214+ }
215+
216+ // Array of all devices that have a parentId
217+ const subComponents =
218+ systemStatus . components ?. filter ( ( c ) => c . instanceId !== undefined && c . parentId !== undefined ) ?? [ ]
219+
220+ function mapComponents ( components ?: Component [ ] ) : ComponentStatus [ ] | undefined {
221+ return (
222+ components ?. map ( ( c ) => {
223+ const version = c . _internal . versions [ '_process' ]
224+ const children = subComponents . filter ( ( sub ) => sub . parentId === c . instanceId )
225+ return {
226+ name : c . name ,
227+ updated : c . updated ,
228+ status : c . status ,
229+ version : version ?? undefined ,
230+ components : children . length ? mapComponents ( children ) : undefined ,
231+ statusMessage : c . statusMessage ?. length ? c . statusMessage : undefined ,
232+ }
233+ } ) ?? undefined
234+ )
235+ }
236+
237+ // Patch the component statusMessage to be from the _internal field if required
238+ const allComponentsPatched = systemStatus . components ?. map ( ( c ) => {
239+ return {
240+ ...c ,
241+ statusMessage : c . statusMessage ?? ( c . status !== 'OK' ? c . _internal . messages . join ( ', ' ) : undefined ) ,
242+ }
243+ } )
244+
245+ // Report status for all devices that are not children and any non-devices that are not OK
246+ const componentStatus =
247+ mapComponents (
248+ allComponentsPatched ?. filter (
249+ ( c ) => ( c . instanceId !== undefined || c . status !== 'OK' ) && c . parentId === undefined
250+ )
251+ ) ?? [ ]
252+
253+ const allStatusMessages =
254+ allComponentsPatched // include children by not using componentStatus here
255+ ?. filter ( ( c ) => c . statusMessage !== undefined )
256+ . map ( ( c ) => `${ c . name } : ${ c . statusMessage } ` )
257+ . join ( '; ' ) ?? ''
258+
259+ const response = ClientAPI . responseSuccess ( {
260+ name : systemStatus . name ,
261+ updated : systemStatus . updated ,
262+ status : systemStatus . status ,
263+ version : coreVersion ,
264+ blueprintsVersion : blueprintsVersion ,
265+ components : componentStatus ,
266+ statusMessage : allStatusMessages ,
267+ } )
268+
269+ ctx . body = JSON . stringify ( { status : response . success , result : response . result } )
270+ ctx . status = response . success
271+ await next ( )
272+ } )
273+
196274registerBlueprintsRoutes ( sofieAPIRequest )
197275registerDevicesRoutes ( sofieAPIRequest )
198276registerPlaylistsRoutes ( sofieAPIRequest )
0 commit comments