Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7606665
chore: ignore expected legacy AsyncApi version
justandras Oct 10, 2025
0a7933f
chore: refactor LSG schemas
justandras Oct 10, 2025
b335063
chore: finalize structure for components directory
justandras Oct 13, 2025
9da5c53
chore: add script for resolving examples recursively
justandras Oct 13, 2025
b45541b
core: remove console logs where not needed
justandras Oct 13, 2025
00545cf
chore: clean up structure for buckets topic
justandras Oct 15, 2025
6cfbf21
chore: clean up structure for ping and heartbeat topic
justandras Oct 15, 2025
6b3d40d
chore: clean up structure for packages topic
justandras Oct 15, 2025
851ccaa
chore: clean up structure for part components
justandras Oct 15, 2025
a5f6e13
chore: clean up structure for activePieces topic
justandras Oct 15, 2025
16ffcda
chore: clean up structure for activeSegmentPart
justandras Oct 15, 2025
04a8aa9
fix: resolve multiple references in examples
justandras Oct 16, 2025
c7a4a28
chore: clean up structure for segments topic
justandras Oct 16, 2025
a47e7aa
chore: clean up structure for studio topic
justandras Oct 16, 2025
488a88b
chore: clean up structure for subscriptions topic
justandras Oct 20, 2025
5bfdb91
chore: rename activePieces.yaml to follow the naming pattern
justandras Oct 20, 2025
ece864d
chore: add missing $refs for examples
justandras Oct 20, 2025
f62a4e4
chore: rename bucket.yaml to bucketStatus.yaml
justandras Oct 20, 2025
d6a2e5c
chore: add missing $def to files
justandras Oct 20, 2025
3f84e9a
chore: clean up structure for playlist topic
justandras Oct 20, 2025
7c0d460
chore: clean up generated documentation page
justandras Oct 20, 2025
e48773f
chore: remove old schema files
justandras Oct 20, 2025
93e88f3
chore: revert changes that are not needed
justandras Oct 20, 2025
ab243a2
chore: fix references in CurrentSegmentTiming
justandras Oct 20, 2025
e6ae805
chore: fix spelling
justandras Oct 20, 2025
87d1844
chore: rename adlibBase-example.yaml
justandras Oct 20, 2025
38c4903
chore: rename globalAdlibStatus.yaml to globalAdLibStatus.yaml
justandras Oct 20, 2025
cbefe22
chore: fix spelling for bucketAdLibStatus.yaml
justandras Oct 20, 2025
8cf7054
chore: build types
justandras Oct 20, 2025
9602bbc
feat: generate merged schema for postman import
justandras Oct 29, 2025
82d6afc
chore: add banner to the merged schema file
justandras Oct 29, 2025
b5dd943
chore: use @apidevtools/json-schema-ref-parser for asyncapi schema me…
ianshade Nov 5, 2025
7b1f3d6
chore: correct description for QuickLoopMarker
justandras Nov 6, 2025
369ae34
chore: delete unused script
justandras Nov 6, 2025
656ebbf
chore: fix formatting
justandras Nov 6, 2025
fdf1ea3
feat(lsg-api): add schema for notifications
justandras Sep 18, 2025
9371998
feat: move notification publications into corelib
justandras Sep 29, 2025
3df1bdf
feat(lsg): add notification support to LSG
justandras Sep 29, 2025
cc2fd05
chore: remove unnecessary check for handlers
justandras Oct 15, 2025
873ef90
fix: add unknown notification target type default case
justandras Oct 15, 2025
25bc648
chore: simplify notification merge logic
justandras Oct 15, 2025
75d54a5
chore: refactor notifications topic schemas
justandras Oct 30, 2025
3fd48ee
chore: rebase to schema refactor
justandras Nov 10, 2025
4d06e30
chore: fix type mismatch for NotificationTargetTypes
justandras Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions meteor/server/publications/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RundownId, RundownPlaylistId, StudioId } from '@sofie-automation/coreli
import { check } from 'meteor/check'
import { SYSTEM_ID } from '@sofie-automation/meteor-lib/dist/collections/CoreSystem'
import { triggerWriteAccessBecauseNoCheckNecessary } from '../security/securityVerify'
import { CorelibPubSub } from '@sofie-automation/corelib/dist/pubsub'

meteorPublish(MeteorPubSub.coreSystem, async function (_token: string | undefined) {
triggerWriteAccessBecauseNoCheckNecessary()
Expand All @@ -26,7 +27,7 @@ meteorPublish(MeteorPubSub.coreSystem, async function (_token: string | undefine
})
})

meteorPublish(MeteorPubSub.notificationsForRundown, async function (studioId: StudioId, rundownId: RundownId) {
meteorPublish(CorelibPubSub.notificationsForRundown, async function (studioId: StudioId, rundownId: RundownId) {
// HACK: This should do real auth
triggerWriteAccessBecauseNoCheckNecessary()

Expand All @@ -41,7 +42,7 @@ meteorPublish(MeteorPubSub.notificationsForRundown, async function (studioId: St
})

meteorPublish(
MeteorPubSub.notificationsForRundownPlaylist,
CorelibPubSub.notificationsForRundownPlaylist,
async function (studioId: StudioId, playlistId: RundownPlaylistId) {
// HACK: This should do real auth
triggerWriteAccessBecauseNoCheckNecessary()
Expand Down
15 changes: 15 additions & 0 deletions packages/corelib/src/pubsub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { BlueprintId, BucketId, RundownPlaylistActivationId, SegmentId, ShowStyl
import { PackageInfoDB } from './dataModel/PackageInfos.js'
import { UIPieceContentStatus } from './dataModel/PieceContentStatus.js'
import { Bucket } from './dataModel/Bucket.js'
import { DBNotificationObj } from './dataModel/Notifications.js'

/**
* Ids of possible DDP subscriptions for any the UI and gateways accessing the Rundown & RundownPlaylist model.
Expand Down Expand Up @@ -130,6 +131,14 @@ export enum CorelibPubSub {
* Fetch all Expected Package statuses in the specified Studios
*/
expectedPackageWorkStatuses = 'expectedPackageWorkStatuses',
/**
* Fetch notifications for playlist
*/
notificationsForRundownPlaylist = 'notificationsForRundownPlaylist',
/**
* Fetch notifications for rundown
*/
notificationsForRundown = 'notificationsForRundown',
/**
* Fetch all Package container statuses in the specified Studios
*/
Expand Down Expand Up @@ -328,6 +337,11 @@ export interface CorelibPubSubTypes {
studioIds: StudioId[],
token?: string
) => CollectionName.PackageContainerStatuses
[CorelibPubSub.notificationsForRundown]: (studioId: StudioId, rundownId: RundownId) => CollectionName.Notifications
[CorelibPubSub.notificationsForRundownPlaylist]: (
studioId: StudioId,
playlistId: RundownPlaylistId
) => CollectionName.Notifications
[CorelibPubSub.packageInfos]: (deviceId: PeripheralDeviceId, token?: string) => CollectionName.PackageInfos

[CorelibPubSub.uiPieceContentStatuses]: (
Expand All @@ -345,6 +359,7 @@ export type CorelibPubSubCollections = {
[CollectionName.ExpectedPackages]: ExpectedPackageDBBase
[CollectionName.ExpectedPackageWorkStatuses]: ExpectedPackageWorkStatus
[CollectionName.ExternalMessageQueue]: ExternalMessageQueueObj
[CollectionName.Notifications]: DBNotificationObj
[CollectionName.NrcsIngestDataCache]: NrcsIngestDataCacheObj
[CollectionName.PartInstances]: DBPartInstance
[CollectionName.PackageContainerStatuses]: PackageContainerStatusDB
Expand Down
1 change: 1 addition & 0 deletions packages/live-status-gateway-api/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
dist
temp
test
src/**.js

Expand Down
144 changes: 28 additions & 116 deletions packages/live-status-gateway-api/api/asyncapi.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
asyncapi: 2.6.0
id: 'urn:nrk:no:sofie:live-status-gateway:server'
asyncapi: '2.6.0'
id: 'sofie:live-status-gateway:server'
info:
title: Sofie Live Status Service
version: '2.0.1'
description: This service provides subscriptions for status updates from Sofie
version: 2.0.0
license:
name: MIT License
url: http://opensource.org/licenses/MIT
contact:
name: Sofie TV Automation - NRK Team
name: Sofie TV Automation
url: https://github.com/Sofie-Automation/sofie-core/issues

servers:
development:
url: localhost
description: Server available without authorisation
description: Server available without authorization
protocol: ws
protocolVersion: '13'

Expand All @@ -26,114 +26,26 @@ tags:
- name: broadcast

channels:
/:
publish:
description: Send messages to the root API
operationId: processRootMessage
message:
oneOf:
- $ref: '#/components/messages/ping'
- $ref: '#/components/messages/subscribe'
- $ref: '#/components/messages/unsubscribe'
subscribe:
description: Messages that are received from the API
operationId: sendRootMessage
message:
oneOf:
- $ref: '#/components/messages/pong'
- $ref: '#/components/messages/heartbeat'
- $ref: '#/components/messages/subscriptionStatus'
- $ref: '#/components/messages/studio'
- $ref: '#/components/messages/activePlaylist'
- $ref: '#/components/messages/activePieces'
- $ref: '#/components/messages/segments'
- $ref: '#/components/messages/adLibs'
- $ref: '#/components/messages/packages'
- $ref: '#/components/messages/buckets'
components:
messages:
ping:
name: ping
messageId: ping
summary: Ping server to determine whether connection is alive
description: Client can ping server to determine whether connection is alive, server responds with pong. This is an application level ping as opposed to default ping in websockets standard which is server initiated
payload:
$ref: './schemas/root.yaml#/$defs/ping'
x-response:
$ref: '#/components/messages/pong'
pong:
name: pong
messageId: pong
summary: Pong is a response to ping message
description: Server pong response to a ping to determine whether connection is alive. This is an application level pong as opposed to default pong in websockets standard which is sent by client in response to a ping
payload:
$ref: './schemas/root.yaml#/$defs/pong'
heartbeat:
name: heartbeat
messageId: heartbeat
description: Server heartbeat sent if no subscription traffic within 1 second (approximately)
payload:
$ref: './schemas/root.yaml#/$defs/heartbeat'
subscribe:
name: subscribe
messageId: subscribe
description: Subscribe to a topic
payload:
$ref: './schemas/root.yaml#/$defs/subscribe'
x-response:
$ref: './schemas/root.yaml#/$defs/subscriptionStatus'
unsubscribe:
name: unsubscribe
messageId: unsubscribe
description: Unsubscribe from a topic
payload:
$ref: './schemas/root.yaml#/$defs/unsubscribe'
x-response:
$ref: './schemas/root.yaml#/$defs/subscriptionStatus'
subscriptionStatus:
messageId: subscriptionStatus
description: Subscription status response to subscribe or unsubscribe
payload:
$ref: './schemas/root.yaml#/$defs/subscriptionStatus'
studio:
name: studio
messageId: studioUpdate
description: Studio status
payload:
$ref: './schemas/studio.yaml#/$defs/studio'
activePlaylist:
name: activePlaylist
messageId: activePlaylistUpdate
description: Active Playlist status
payload:
$ref: './schemas/activePlaylist.yaml#/$defs/activePlaylist'
activePieces:
name: activePieces
messageId: activePiecesUpdate
summary: Active Pieces status
description: Pieces from the active Playlist that are currently active (on air)
payload:
$ref: './schemas/activePieces.yaml#/$defs/activePieces'
segments:
name: segments
messageId: segmentsUpdate
description: Segments in active Playlist
payload:
$ref: './schemas/segments.yaml#/$defs/segments'
adLibs:
name: adLibs
messageId: adLibsUpdate
description: AdLibs in active Playlist
payload:
$ref: './schemas/adLibs.yaml#/$defs/adLibs'
packages:
name: packages
messageId: packages
description: Status of Packages expected by Pieces
payload:
$ref: './schemas/packages.yaml#/$defs/packages'
buckets:
name: buckets
description: Buckets in Studio
payload:
$ref: './schemas/buckets.yaml#/$defs/buckets'
# As the LSG is websocket only, channels are only used for logical grouping for the generated docs and folder structure.
ping:
$ref: './topics/ping/pingTopic.yaml'
heartbeat:
$ref: './topics/heartbeat/heartbeatTopic.yaml'
subscriptions:
$ref: './topics/subscriptions/subscriptionsTopic.yaml'
studio:
$ref: './topics/studio/studioTopic.yaml'
activePlaylist:
$ref: './topics/activePlaylist/activePlaylistTopic.yaml'
activePieces:
$ref: './topics/activePieces/activePiecesTopic.yaml'
segments:
$ref: './topics/segments/segmentsTopic.yaml'
adLibs:
$ref: './topics/adLibs/adLibsTopic.yaml'
packages:
$ref: './topics/packages/packagesTopic.yaml'
buckets:
$ref: './topics/buckets/bucketsTopic.yaml'
notifications:
$ref: './topics/notifications/notificationsTopic.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: pvw
label: Preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
$defs:
adLibActionType:
title: AdLibActionType
type: object
properties:
name:
type: string
description: The string to be passed to the ExecuteAdlib function
label:
type: string
description: The label for the AdLib type
required: [name, label]
additionalProperties: false
examples:
- $ref: './actionType-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
id: 'C6K_yIMuGFUk8X_L9A9_jRT6aq4_'
name: Music video clip
sourceLayer: Video Clip
actionType:
- $ref: '../actionType/actionType-example.yaml'
tags: ['music_video']
publicData:
fileName: MV000123.mxf
optionsSchema: '{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Play Video Clip","type":"object","properties":{"type":"adlib_action_video_clip","label":{"type":"string"},"clipId":{"type":"string"},"vo":{"type":"boolean"},"target":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Object Id","description":"Id of an object sent to Sofie","type":"string"},"duration":{"type":"number","exclusiveMinimum":0},"takeType":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"AdLib Action Take Type","type":"string","enum":["take_immediate","queue"]},"transition":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"AdLib Action Transition Type","oneOf":[{"type":"object","properties":{"type":"cut"},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":"mix","duration":{"type":"number","exclusiveMinimum":0,"description":"Duration in ms"}},"required":["type","duration"],"additionalProperties":false},{"type":"object","properties":{"type":"wipe","duration":{"type":"number","exclusiveMinimum":0,"description":"Duration in ms"},"patternId":{"type":"string","description":"Type of wipe to use"}},"required":["type","duration","patternId"],"additionalProperties":false},{"type":"object","properties":{"type":"macro","macroId":{"type":"string","description":"Macro template to recall"}},"required":["type","macroId"],"additionalProperties":false}]}},"required":["type","clipId","vo","target"],"additionalProperties":false}"'
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
$defs:
adLibBase:
title: AdLibBase
type: object
properties:
id:
type: string
description: Unique id of the AdLib
name:
type: string
description: The user defined AdLib name
sourceLayer:
type: string
description: The source layer name for this AdLib
outputLayer:
type: string
description: The output layer name for this AdLib
actionType:
type: array
description: The available action type names that can be used to modify the execution of the AdLib
items:
$ref: '../actionType/actionType.yaml#/$defs/adLibActionType'
tags:
type: array
description: Tags attached to this AdLib
items:
type: string
publicData:
description: Optional arbitrary data
optionsSchema:
type: string
description: JSON schema definition of the adLib properties that can be modified using the adLibOptions property in executeAdLib
required: [id, name, sourceLayer, actionType]
examples:
- $ref: './adLibBase-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$ref: '../adLibBase/adLibBase-example.yaml'
segmentId: HsD8_QwE1ZmR5vN3XcK_Ab7y
partId: JkL3_OpR6WxT1bF8Vq2_Zy9u
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
$defs:
adLibStatus:
title: AdLibStatus
allOf:
- $ref: '../adLibBase/adLibBase.yaml#/$defs/adLibBase'
- type: object
title: AdLibStatus
properties:
segmentId:
description: Unique id of the segment this adLib belongs to
type: string
partId:
description: Unique id of the part this adLib belongs to
type: string
required: [segmentId, partId]
examples:
- $ref: './adLibStatus-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
event: 'adLibs'
rundownPlaylistId: 'OKAgZmZ0Buc99lE_2uPPSKVbMrQ_'
adLibs:
- $ref: '../adLibStatus/adLibStatus-example.yaml'
globalAdLibs:
- $ref: '../globalAdLibStatus/globalAdLibStatus-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
$defs:
adLibsEvent:
type: object
title: AdLibsEvent
properties:
event:
type: string
const: adLibs
rundownPlaylistId:
description: Unique id of the rundown playlist, or null if no playlist is active
oneOf:
- type: string
title: Unique id of the rundown playlist
- type: 'null'
title: Null if no playlist is active
adLibs:
type: array
description: The available AdLibs for this playlist
items:
$ref: '../adLibStatus/adLibStatus.yaml#/$defs/adLibStatus'
globalAdLibs:
type: array
description: The available Global AdLibs for this playlist
items:
$ref: '../globalAdLibStatus/globalAdLibStatus.yaml#/$defs/globalAdLibStatus'
required: [event, rundownPlaylistId, adLibs, globalAdLibs]
additionalProperties: false
examples:
- $ref: './adLibsEvent-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$ref: '../adLibBase/adLibBase-example.yaml'
externalId: 'C6K_yIMuGFUk8X_L9A9_jRT6aq4_'
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
$defs:
bucketAdLibStatus:
title: BucketAdLibStatus
allOf:
- $ref: '../adLibBase/adLibBase.yaml#/$defs/adLibBase'
- type: object
title: BucketAdLibStatus
properties:
externalId:
type: string
description: Id of the adLib recognizable by the external source. Unique within a bucket.
required: [externalId]
examples:
- $ref: './bucketAdLibStatus-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ref: '../adLibBase/adLibBase-example.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$defs:
globalAdLibStatus:
title: GlobalAdLibStatus
allOf:
- $ref: '../adLibBase/adLibBase.yaml#/$defs/adLibBase'
examples:
- $ref: './globalAdLibStatus-example.yaml'
Loading
Loading