diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index d2bcf13410..33bf086fd2 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -55,11 +55,17 @@ "rundown", "production" ], + "devDependencies": { + "@types/koa": "^3.0.0", + "@types/koa__router": "^12.0.4" + }, "dependencies": { + "@koa/router": "^14.0.0", "@sofie-automation/server-core-integration": "1.52.0", "@sofie-automation/shared-lib": "1.52.0", "debug": "^4.4.0", "influx": "^5.9.7", + "koa": "^3.0.1", "timeline-state-resolver": "9.3.0", "tslib": "^2.8.1", "underscore": "^1.13.7", diff --git a/packages/playout-gateway/src/config.ts b/packages/playout-gateway/src/config.ts index d47e20572e..2795c20278 100644 --- a/packages/playout-gateway/src/config.ts +++ b/packages/playout-gateway/src/config.ts @@ -20,6 +20,8 @@ let influxUser: string | undefined = process.env.INFLUX_USER || 'sofie' let influxPassword: string | undefined = process.env.INFLUX_PASSWORD || undefined let influxDatabase: string | undefined = process.env.INFLUX_DB || 'sofie' +let healthPort: number | undefined = parseInt(process.env.HEALTH_PORT + '') || undefined + let prevProcessArg = '' process.argv.forEach((val) => { val = val + '' @@ -50,6 +52,8 @@ process.argv.forEach((val) => { influxPassword = val } else if (prevProcessArg.match(/-influxDatabase/i)) { influxDatabase = val + } else if (prevProcessArg.match(/-healthPort/i)) { + healthPort = parseInt(val) // arguments with no options: } else if (val.match(/-disableWatchdog/i)) { @@ -57,7 +61,9 @@ process.argv.forEach((val) => { } else if (val.match(/-disableAtemUpload/i)) { disableAtemUpload = true } else if (val.match(/-unsafeSSL/i)) { - // Will cause the Node applocation to blindly accept all certificates. Not recommenced unless in local, controlled networks. + // Will cause the Node application to blindly accept all certificates. + // Not recommenced unless in local, controlled networks. + // Instead use "-certificates cert1 cert2" unsafeSSL = true } prevProcessArg = nextPrevProcessArg + '' @@ -85,6 +91,9 @@ const config: Config = { password: influxPassword, database: influxDatabase, }, + health: { + port: healthPort, + }, } export { config, logPath, logLevel, disableWatchdog, disableAtemUpload } diff --git a/packages/playout-gateway/src/connector.ts b/packages/playout-gateway/src/connector.ts index c13d2e0c8f..bf1195634b 100644 --- a/packages/playout-gateway/src/connector.ts +++ b/packages/playout-gateway/src/connector.ts @@ -6,7 +6,9 @@ import { CertificatesConfig, PeripheralDeviceId, loadCertificatesFromDisk, + stringifyError, } from '@sofie-automation/server-core-integration' +import { HealthConfig, HealthEndpoints } from './health' export interface Config { certificates: CertificatesConfig @@ -14,6 +16,7 @@ export interface Config { core: CoreConfig tsr: TSRConfig influx: InfluxConfig + health: HealthConfig } export interface DeviceConfig { @@ -21,6 +24,9 @@ export interface DeviceConfig { deviceToken: string } export class Connector { + public initialized = false + public initializedError: string | undefined = undefined + private tsrHandler: TSRHandler | undefined private coreHandler: CoreHandler | undefined private _logger: Logger @@ -38,6 +44,8 @@ export class Connector { this._logger.info('Initializing Core...') this.coreHandler = new CoreHandler(this._logger, config.device) + new HealthEndpoints(this, this.coreHandler, config.health) + await this.coreHandler.init(config.core, this._certificates) this._logger.info('Core initialized') @@ -47,12 +55,15 @@ export class Connector { this._logger.info('TSR initialized') this._logger.info('Initialization done') + this.initialized = true return } catch (e: any) { this._logger.error('Error during initialization:') this._logger.error(e) this._logger.error(e.stack) + this.initializedError = stringifyError(e) + try { if (this.coreHandler) { this.coreHandler.destroy().catch(this._logger.error) diff --git a/packages/playout-gateway/src/coreHandler.ts b/packages/playout-gateway/src/coreHandler.ts index 54227a78fa..b906656928 100644 --- a/packages/playout-gateway/src/coreHandler.ts +++ b/packages/playout-gateway/src/coreHandler.ts @@ -59,6 +59,8 @@ export class CoreHandler { private _statusInitialized = false private _statusDestroyed = false + public connectedToCore = false + constructor(logger: Logger, deviceOptions: DeviceConfig) { this.logger = logger this._deviceOptions = deviceOptions @@ -73,11 +75,13 @@ export class CoreHandler { this.core.onConnected(() => { this.logger.info('Core Connected!') + this.connectedToCore = true if (this._onConnected) this._onConnected() }) this.core.onDisconnected(() => { this.logger.warn('Core Disconnected!') + this.connectedToCore = false }) this.core.onError((err: any) => { this.logger.error('Core Error: ' + (typeof err === 'string' ? err : err.message || err.toString() || err)) @@ -389,9 +393,12 @@ export class CoreHandler { return Object.fromEntries(this._tsrHandler.getDebugStates().entries()) } - async updateCoreStatus(): Promise { + getCoreStatus(): { + statusCode: StatusCode + messages: string[] + } { let statusCode = StatusCode.GOOD - const messages: Array = [] + const messages: string[] = [] if (!this._statusInitialized) { statusCode = StatusCode.BAD @@ -401,11 +408,13 @@ export class CoreHandler { statusCode = StatusCode.BAD messages.push('Shut down') } - - return this.core.setStatus({ - statusCode: statusCode, - messages: messages, - }) + return { + statusCode, + messages, + } + } + async updateCoreStatus(): Promise { + return this.core.setStatus(this.getCoreStatus()) } } diff --git a/packages/playout-gateway/src/health.ts b/packages/playout-gateway/src/health.ts new file mode 100644 index 0000000000..d872f396af --- /dev/null +++ b/packages/playout-gateway/src/health.ts @@ -0,0 +1,67 @@ +import * as Koa from 'koa' +import * as Router from '@koa/router' +import { StatusCode } from 'timeline-state-resolver' +import { assertNever } from '@sofie-automation/server-core-integration' +import { CoreHandler } from './coreHandler' +import { Connector } from './connector' + +export interface HealthConfig { + /** If set, exposes health HTTP endpoints on the given port */ + port?: number +} + +/** + * Exposes health endpoints for Kubernetes or other orchestrators to monitor + * see https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes + */ +export class HealthEndpoints { + private app = new Koa() + constructor(private connector: Connector, private coreHandler: CoreHandler, private config: HealthConfig) { + if (!config.port) return // disabled + + const router = new Router() + + router.get('/healthz', async (ctx) => { + if (this.connector.initializedError !== undefined) { + ctx.status = 503 + ctx.body = `Error during initialization: ${this.connector.initializedError}` + return + } + if (!this.connector.initialized) { + ctx.status = 503 + ctx.body = 'Not initialized' + return + } + + const coreStatus = this.coreHandler.getCoreStatus() + + if (coreStatus.statusCode === StatusCode.UNKNOWN) ctx.status = 503 + else if (coreStatus.statusCode === StatusCode.FATAL) ctx.status = 503 + else if (coreStatus.statusCode === StatusCode.BAD) ctx.status = 503 + else if (coreStatus.statusCode === StatusCode.WARNING_MAJOR) ctx.status = 200 + else if (coreStatus.statusCode === StatusCode.WARNING_MINOR) ctx.status = 200 + else if (coreStatus.statusCode === StatusCode.GOOD) ctx.status = 200 + else assertNever(coreStatus.statusCode) + + if (ctx.status !== 200) { + ctx.body = `Status: ${StatusCode[coreStatus.statusCode]}, messages: ${coreStatus.messages.join(', ')}` + } else { + ctx.body = 'OK' + } + }) + + router.get('/readyz', async (ctx) => { + if (!this.coreHandler.connectedToCore) { + ctx.status = 503 + ctx.body = 'Not connected to Core' + return + } + // else + ctx.status = 200 + ctx.body = 'READY' + }) + + this.app.use(router.routes()).use(router.allowedMethods()) + this.app.listen(this.config.port) + } +} diff --git a/packages/yarn.lock b/packages/yarn.lock index 3c21157f46..5c34790695 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -3987,6 +3987,18 @@ __metadata: languageName: node linkType: hard +"@koa/router@npm:^14.0.0": + version: 14.0.0 + resolution: "@koa/router@npm:14.0.0" + dependencies: + debug: "npm:^4.4.1" + http-errors: "npm:^2.0.0" + koa-compose: "npm:^4.1.0" + path-to-regexp: "npm:^8.2.0" + checksum: 10/f5f9bedd4c163ad376bcf9626ebb13f35febc44c1f81545ee5efaceb67324e3caf476f9d2a966b4590cac41ab9994b1bcb11f050afbdccd6343f27f31758ff68 + languageName: node + linkType: hard + "@kwsites/file-exists@npm:^1.1.1": version: 1.1.1 resolution: "@kwsites/file-exists@npm:1.1.1" @@ -6845,6 +6857,15 @@ __metadata: languageName: node linkType: hard +"@types/accepts@npm:*": + version: 1.3.7 + resolution: "@types/accepts@npm:1.3.7" + dependencies: + "@types/node": "npm:*" + checksum: 10/7678cf74976e16093aff6e6f9755826faf069ac1e30179276158ce46ea246348ff22ca6bdd46cef08428881337d9ceefbf00bab08a7731646eb9fc9449d6a1e7 + languageName: node + linkType: hard + "@types/acorn@npm:^4.0.0": version: 4.0.6 resolution: "@types/acorn@npm:4.0.6" @@ -6970,6 +6991,25 @@ __metadata: languageName: node linkType: hard +"@types/content-disposition@npm:*": + version: 0.5.9 + resolution: "@types/content-disposition@npm:0.5.9" + checksum: 10/d895703c0027ca6c4c0c1ede363909dbb590deec3b206a84b88a49c8b2840bcbd31b4ddeb2e1e6caa1af00801cc79c5b69a5c75a8152f2959810b10fe75a4e1f + languageName: node + linkType: hard + +"@types/cookies@npm:*": + version: 0.9.1 + resolution: "@types/cookies@npm:0.9.1" + dependencies: + "@types/connect": "npm:*" + "@types/express": "npm:*" + "@types/keygrip": "npm:*" + "@types/node": "npm:*" + checksum: 10/512635d55e25fb113412a8f0edc59a00f68ab79646ce19ebd95f8e97815f9ea506b69ec61da12e024565bb03d238fbb7983805c53a6f8d92684c45869a9ac7cf + languageName: node + linkType: hard + "@types/d3-array@npm:*": version: 3.2.1 resolution: "@types/d3-array@npm:3.2.1" @@ -7417,6 +7457,13 @@ __metadata: languageName: node linkType: hard +"@types/http-assert@npm:*": + version: 1.5.6 + resolution: "@types/http-assert@npm:1.5.6" + checksum: 10/dfe1010164ba633859d90a50c4c53e69a38a16972061ef614acc1b0bdb7e53a1c923a11b4169a4a7eedc20b2303962d761727a212ae099717327cf4f38293817 + languageName: node + linkType: hard + "@types/http-cache-semantics@npm:*, @types/http-cache-semantics@npm:^4.0.2": version: 4.0.4 resolution: "@types/http-cache-semantics@npm:4.0.4" @@ -7431,6 +7478,13 @@ __metadata: languageName: node linkType: hard +"@types/http-errors@npm:^2": + version: 2.0.5 + resolution: "@types/http-errors@npm:2.0.5" + checksum: 10/a88da669366bc483e8f3b3eb3d34ada5f8d13eeeef851b1204d77e2ba6fc42aba4566d877cca5c095204a3f4349b87fe397e3e21288837bdd945dd514120755b + languageName: node + linkType: hard + "@types/http-proxy@npm:^1.17.8": version: 1.17.12 resolution: "@types/http-proxy@npm:1.17.12" @@ -7493,6 +7547,13 @@ __metadata: languageName: node linkType: hard +"@types/keygrip@npm:*": + version: 1.0.6 + resolution: "@types/keygrip@npm:1.0.6" + checksum: 10/d157f60bf920492347791d2b26d530d5069ce05796549fbacd4c24d66ffbebbcb0ab67b21e7a1b80a593b9fd4b67dc4843dec04c12bbc2e0fddfb8577a826c41 + languageName: node + linkType: hard + "@types/keyv@npm:^3.1.4": version: 3.1.4 resolution: "@types/keyv@npm:3.1.4" @@ -7502,6 +7563,40 @@ __metadata: languageName: node linkType: hard +"@types/koa-compose@npm:*": + version: 3.2.8 + resolution: "@types/koa-compose@npm:3.2.8" + dependencies: + "@types/koa": "npm:*" + checksum: 10/95c32bdee738ac7c10439bbf6342ca3b9f0aafd7e8118739eac7fb0fa703a23cfe4c88f63e13a69a16fbde702e0bcdc62b272aa734325fc8efa7e5625479752e + languageName: node + linkType: hard + +"@types/koa@npm:*, @types/koa@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/koa@npm:3.0.0" + dependencies: + "@types/accepts": "npm:*" + "@types/content-disposition": "npm:*" + "@types/cookies": "npm:*" + "@types/http-assert": "npm:*" + "@types/http-errors": "npm:^2" + "@types/keygrip": "npm:*" + "@types/koa-compose": "npm:*" + "@types/node": "npm:*" + checksum: 10/db461810b71afe7b73dc849c0832669d1d838edd15b81b0c07d37d32545620dfb0efc19cc120485f5e06a805a151cd89696eb53a5bfad8e223d7e593080069cb + languageName: node + linkType: hard + +"@types/koa__router@npm:^12.0.4": + version: 12.0.4 + resolution: "@types/koa__router@npm:12.0.4" + dependencies: + "@types/koa": "npm:*" + checksum: 10/c01311980bf9a921b77cca5a93cc85522a6d13fe49575e6190fa80407a60237e7351d99a399316dda3119641d498f5d8236b905cd3b4f54fad2c0839ab655dd4 + languageName: node + linkType: hard + "@types/lodash@npm:^4.14.168": version: 4.14.198 resolution: "@types/lodash@npm:4.14.198" @@ -8427,7 +8522,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": +"accepts@npm:^1.3.8, accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -10940,7 +11035,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"content-disposition@npm:0.5.4": +"content-disposition@npm:0.5.4, content-disposition@npm:~0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -10949,7 +11044,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"content-type@npm:~1.0.4": +"content-type@npm:^1.0.5, content-type@npm:~1.0.4": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 10/585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 @@ -11084,6 +11179,16 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"cookies@npm:~0.9.1": + version: 0.9.1 + resolution: "cookies@npm:0.9.1" + dependencies: + depd: "npm:~2.0.0" + keygrip: "npm:~1.1.0" + checksum: 10/4816461a38d907b20f3fb7a2bc4741fe580e7a195f3e248ef7025cb3be56a07638a0f4e72553a5f535554ca30172c8a3245c63ac72c9737cec034e9a47773392 + languageName: node + linkType: hard + "copy-text-to-clipboard@npm:^3.2.0": version: 3.2.0 resolution: "copy-text-to-clipboard@npm:3.2.0" @@ -12249,6 +12354,18 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"debug@npm:^4.4.1": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10/9ada3434ea2993800bd9a1e320bd4aa7af69659fb51cca685d390949434bc0a8873c21ed7c9b852af6f2455a55c6d050aa3937d52b3c69f796dab666f762acad + languageName: node + linkType: hard + "debuglog@npm:^1.0.1": version: 1.0.1 resolution: "debuglog@npm:1.0.1" @@ -12338,6 +12455,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"deep-equal@npm:~1.0.1": + version: 1.0.1 + resolution: "deep-equal@npm:1.0.1" + checksum: 10/cbecc071afb2891334ced9e9de5834889b9a9992ae8d8369b7eb74c513529eb6d1f6c04d4e2b5f34d8386f7816cd7a6cda45edff847695faea45e43c23973f45 + languageName: node + linkType: hard + "deep-extend@npm:0.6.0, deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -12487,7 +12611,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"depd@npm:2.0.0": +"depd@npm:2.0.0, depd@npm:~2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca @@ -12532,7 +12656,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"destroy@npm:1.2.0": +"destroy@npm:1.2.0, destroy@npm:^1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 10/0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 @@ -13106,6 +13230,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"encodeurl@npm:^2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe + languageName: node + linkType: hard + "encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" @@ -14758,7 +14889,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"fresh@npm:0.5.2": +"fresh@npm:0.5.2, fresh@npm:~0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 @@ -15961,6 +16092,16 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"http-assert@npm:^1.5.0": + version: 1.5.0 + resolution: "http-assert@npm:1.5.0" + dependencies: + deep-equal: "npm:~1.0.1" + http-errors: "npm:~1.8.0" + checksum: 10/69c9b3c14cf8b2822916360a365089ce936c883c49068f91c365eccba5c141a9964d19fdda589150a480013bf503bf37d8936c732e9635819339e730ab0e7527 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -15975,7 +16116,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"http-errors@npm:2.0.0": +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": version: 2.0.0 resolution: "http-errors@npm:2.0.0" dependencies: @@ -16000,6 +16141,19 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"http-errors@npm:~1.8.0": + version: 1.8.1 + resolution: "http-errors@npm:1.8.1" + dependencies: + depd: "npm:~1.1.2" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:>= 1.5.0 < 2" + toidentifier: "npm:1.0.1" + checksum: 10/76fc491bd8df2251e21978e080d5dae20d9736cfb29bb72b5b76ec1bcebb1c14f0f58a3a128dd89288934379d2173cfb0421c571d54103e93dd65ef6243d64d8 + languageName: node + linkType: hard + "http-headers@npm:^3.0.2": version: 3.0.2 resolution: "http-headers@npm:3.0.2" @@ -18265,6 +18419,15 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"keygrip@npm:~1.1.0": + version: 1.1.0 + resolution: "keygrip@npm:1.1.0" + dependencies: + tsscmp: "npm:1.0.6" + checksum: 10/078cd16a463d187121f0a27c1c9c95c52ad392b620f823431689f345a0501132cee60f6e96914b07d570105af470b96960402accd6c48a0b1f3cd8fac4fa2cae + languageName: node + linkType: hard + "keyv@npm:^4.0.0, keyv@npm:^4.5.3": version: 4.5.3 resolution: "keyv@npm:4.5.3" @@ -18302,6 +18465,39 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"koa-compose@npm:^4.1.0": + version: 4.1.0 + resolution: "koa-compose@npm:4.1.0" + checksum: 10/46cb16792d96425e977c2ae4e5cb04930280740e907242ec9c25e3fb8b4a1d7b54451d7432bc24f40ec62255edea71894d2ceeb8238501842b4e48014f2e83db + languageName: node + linkType: hard + +"koa@npm:^3.0.1": + version: 3.0.1 + resolution: "koa@npm:3.0.1" + dependencies: + accepts: "npm:^1.3.8" + content-disposition: "npm:~0.5.4" + content-type: "npm:^1.0.5" + cookies: "npm:~0.9.1" + delegates: "npm:^1.0.0" + destroy: "npm:^1.2.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + fresh: "npm:~0.5.2" + http-assert: "npm:^1.5.0" + http-errors: "npm:^2.0.0" + koa-compose: "npm:^4.1.0" + mime-types: "npm:^3.0.1" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + type-is: "npm:^2.0.1" + vary: "npm:^1.1.2" + checksum: 10/0e56f77f7192c10be6a3f5c4b248ec10b9b223e6894065a431df3c5c425db439fcc28ead29e7145087974550b51538790aafee6aeb5b0e26a32307d02a52bd41 + languageName: node + linkType: hard + "kolorist@npm:^1.8.0": version: 1.8.0 resolution: "kolorist@npm:1.8.0" @@ -19569,6 +19765,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10/a58dd60804df73c672942a7253ccc06815612326dc1c0827984b1a21704466d7cde351394f47649e56cf7415e6ee2e26e000e81b51b3eebb5a93540e8bf93cbd + languageName: node + linkType: hard + "memfs@npm:^3.1.2, memfs@npm:^3.4.3": version: 3.5.3 resolution: "memfs@npm:3.5.3" @@ -20230,6 +20433,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"mime-db@npm:^1.54.0": + version: 1.54.0 + resolution: "mime-db@npm:1.54.0" + checksum: 10/9e7834be3d66ae7f10eaa69215732c6d389692b194f876198dca79b2b90cbf96688d9d5d05ef7987b20f749b769b11c01766564264ea5f919c88b32a29011311 + languageName: node + linkType: hard + "mime-db@npm:~1.33.0": version: 1.33.0 resolution: "mime-db@npm:1.33.0" @@ -20255,6 +20465,15 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1": + version: 3.0.1 + resolution: "mime-types@npm:3.0.1" + dependencies: + mime-db: "npm:^1.54.0" + checksum: 10/fa1d3a928363723a8046c346d87bf85d35014dae4285ad70a3ff92bd35957992b3094f8417973cfe677330916c6ef30885109624f1fb3b1e61a78af509dba120 + languageName: node + linkType: hard + "mime@npm:1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" @@ -21770,7 +21989,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:2.4.1, on-finished@npm:^2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -22564,7 +22783,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" checksum: 10/407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 @@ -22701,6 +22920,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"path-to-regexp@npm:^8.2.0": + version: 8.3.0 + resolution: "path-to-regexp@npm:8.3.0" + checksum: 10/568f148fc64f5fd1ecebf44d531383b28df924214eabf5f2570dce9587a228e36c37882805ff02d71c6209b080ea3ee6a4d2b712b5df09741b67f1f3cf91e55a + languageName: node + linkType: hard + "path-type@npm:^3.0.0": version: 3.0.0 resolution: "path-type@npm:3.0.0" @@ -22930,10 +23156,14 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: + "@koa/router": "npm:^14.0.0" "@sofie-automation/server-core-integration": "npm:1.52.0" "@sofie-automation/shared-lib": "npm:1.52.0" + "@types/koa": "npm:^3.0.0" + "@types/koa__router": "npm:^12.0.4" debug: "npm:^4.4.0" influx: "npm:^5.9.7" + koa: "npm:^3.0.1" timeline-state-resolver: "npm:9.3.0" tslib: "npm:^2.8.1" underscore: "npm:^1.13.7" @@ -26934,13 +27164,20 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"statuses@npm:>= 1.4.0 < 2": +"statuses@npm:>= 1.4.0 < 2, statuses@npm:>= 1.5.0 < 2": version: 1.5.0 resolution: "statuses@npm:1.5.0" checksum: 10/c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c languageName: node linkType: hard +"statuses@npm:^2.0.1": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10/6927feb50c2a75b2a4caab2c565491f7a93ad3d8dbad7b1398d52359e9243a20e2ebe35e33726dee945125ef7a515e9097d8a1b910ba2bbd818265a2f6c39879 + languageName: node + linkType: hard + "std-env@npm:^3.7.0": version: 3.8.0 resolution: "std-env@npm:3.8.0" @@ -28070,6 +28307,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"tsscmp@npm:1.0.6": + version: 1.0.6 + resolution: "tsscmp@npm:1.0.6" + checksum: 10/850405080ea3ecb158e9e01bc4e87c9edb94a829d8ad8747f30ba103fcc41a287d7949ab84d7b27c36294036a2c9878f050db15b73a1a1961abfb7688b82ac53 + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -28210,6 +28454,17 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"type-is@npm:^2.0.1": + version: 2.0.1 + resolution: "type-is@npm:2.0.1" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10/bacdb23c872dacb7bd40fbd9095e6b2fca2895eedbb689160c05534d7d4810a7f4b3fd1ae87e96133c505958f6d602967a68db5ff577b85dd6be76eaa75d58af + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -28983,7 +29238,7 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"vary@npm:~1.1.2": +"vary@npm:^1.1.2, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" checksum: 10/31389debef15a480849b8331b220782230b9815a8e0dbb7b9a8369559aed2e9a7800cd904d4371ea74f4c3527db456dc8e7ac5befce5f0d289014dbdf47b2242