mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-10 17:49:58 +00:00
Improve app message types
This commit is contained in:
@@ -4,8 +4,8 @@ import castv2 from "castv2";
|
|||||||
|
|
||||||
import Session from "./Session";
|
import Session from "./Session";
|
||||||
|
|
||||||
import { Message } from "../../types";
|
import { Message } from "../../messaging";
|
||||||
import { sendMessage } from "../../lib/messaging"
|
import { sendMessage } from "../../lib/nativeMessaging"
|
||||||
|
|
||||||
|
|
||||||
const NS_MEDIA = "urn:x-cast:com.google.cast.media";
|
const NS_MEDIA = "urn:x-cast:com.google.cast.media";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { Channel, Client } from "castv2";
|
import { Channel, Client } from "castv2";
|
||||||
|
|
||||||
import { Message } from "../../types";
|
import { Message } from "../../messaging";
|
||||||
import { sendMessage } from "../../lib/messaging";
|
import { sendMessage } from "../../lib/nativeMessaging";
|
||||||
|
|
||||||
|
|
||||||
export const NS_CONNECTION = "urn:x-cast:com.google.cast.tp.connection";
|
export const NS_CONNECTION = "urn:x-cast:com.google.cast.tp.connection";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import mdns from "mdns";
|
|||||||
|
|
||||||
import StatusListener from "./chromecast/StatusListener";
|
import StatusListener from "./chromecast/StatusListener";
|
||||||
import { ReceiverStatus } from "../types";
|
import { ReceiverStatus } from "../types";
|
||||||
import { sendMessage } from "../lib/messaging";
|
import { sendMessage } from "../lib/nativeMessaging";
|
||||||
|
|
||||||
|
|
||||||
interface CastTxtRecord {
|
interface CastTxtRecord {
|
||||||
@@ -44,7 +44,7 @@ function onBrowserServiceUp (service: mdns.Service) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBrowserServiceDown (service: mdns.Service) {
|
function onBrowserServiceDown (_service: mdns.Service) {
|
||||||
// TODO: Fix service down detection
|
// TODO: Fix service down detection
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ export function startDiscovery (options: InitializeOptions) {
|
|||||||
statusListeners.set(id, listener);
|
statusListeners.set(id, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStatusBrowserServiceDown (service: mdns.Service) {
|
function onStatusBrowserServiceDown (_service: mdns.Service) {
|
||||||
// TODO: Fix service down detection
|
// TODO: Fix service down detection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import stream from "stream";
|
|||||||
|
|
||||||
import mime from "mime-types";
|
import mime from "mime-types";
|
||||||
|
|
||||||
import { sendMessage } from "../lib/messaging";
|
import { sendMessage } from "../lib/nativeMessaging";
|
||||||
import { convertSrtToVtt } from "../lib/subtitles";
|
import { convertSrtToVtt } from "../lib/subtitles";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import child_process from "child_process";
|
import child_process from "child_process";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import { sendMessage } from "../lib/messaging";
|
import { sendMessage } from "../lib/nativeMessaging";
|
||||||
|
|
||||||
|
|
||||||
function fatal (message: string) {
|
function fatal (message: string) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { decodeTransform, encodeTransform } from "./lib/messaging";
|
import { decodeTransform, encodeTransform } from "./lib/nativeMessaging";
|
||||||
import { Message } from "./types";
|
import { Message } from "./messaging";
|
||||||
|
|
||||||
import { handleSessionMessage, handleMediaMessage, stopReceiverApp }
|
import { handleSessionMessage, handleMediaMessage, stopReceiverApp }
|
||||||
from "./components/chromecast";
|
from "./components/chromecast";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { DecodeTransform, EncodeTransform } from "../../transforms";
|
import { DecodeTransform, EncodeTransform } from "../../transforms";
|
||||||
import { Message } from "../types";
|
import { Message } from "../messaging";
|
||||||
|
|
||||||
|
|
||||||
export const decodeTransform = new DecodeTransform();
|
export const decodeTransform = new DecodeTransform();
|
||||||
172
app/src/bridge/messaging.ts
Normal file
172
app/src/bridge/messaging.ts
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { Receiver
|
||||||
|
, ReceiverSelectionCast
|
||||||
|
, ReceiverSelectionStop
|
||||||
|
, ReceiverStatus } from "./types";
|
||||||
|
|
||||||
|
|
||||||
|
type MessageDefinitions = {
|
||||||
|
"shim:serviceUp": { id: Receiver["id"] }
|
||||||
|
, "shim:serviceDown": { id: Receiver["id"] }
|
||||||
|
|
||||||
|
, "shim:launchApp": { receiver: Receiver }
|
||||||
|
|
||||||
|
// Session messages
|
||||||
|
, "shim:session/stopped": {}
|
||||||
|
, "shim:session/connected": {
|
||||||
|
sessionId: string
|
||||||
|
, namespaces: Array<{ name: string }>
|
||||||
|
, displayName: string
|
||||||
|
, statusText: string
|
||||||
|
}
|
||||||
|
, "shim:session/updateStatus": { volume: any /* Volume */ }
|
||||||
|
, "shim:session/impl_addMessageListener": {
|
||||||
|
namespace: string
|
||||||
|
, data: string
|
||||||
|
}
|
||||||
|
, "shim:session/impl_sendMessage": {
|
||||||
|
messageId: string
|
||||||
|
, error: boolean
|
||||||
|
}
|
||||||
|
, "shim:session/impl_setReceiverMuted": {
|
||||||
|
volumeId: string
|
||||||
|
, error: boolean
|
||||||
|
}
|
||||||
|
, "shim:session/impl_setReceiverVolumeLevel": {
|
||||||
|
volumeId: string
|
||||||
|
, error: boolean
|
||||||
|
}
|
||||||
|
, "shim:session/impl_stop": {
|
||||||
|
stopId: string
|
||||||
|
, error: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bridge session messages
|
||||||
|
, "bridge:session/initialize": {
|
||||||
|
address: string
|
||||||
|
, port: number
|
||||||
|
, appId: string
|
||||||
|
, sessionId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:session/close": {}
|
||||||
|
, "bridge:session/impl_leave": {
|
||||||
|
id: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:session/impl_sendMessage": {
|
||||||
|
namespace: string
|
||||||
|
, message: any
|
||||||
|
, messageId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:session/impl_setReceiverMuted": {
|
||||||
|
muted: boolean
|
||||||
|
, volumeId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:session/impl_setReceiverVolumeLevel": {
|
||||||
|
newLevel: number
|
||||||
|
, volumeId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:session/impl_stop": {
|
||||||
|
stopId: string;
|
||||||
|
_id: string;
|
||||||
|
}
|
||||||
|
, "bridge:session/impl_addMessageListener": {
|
||||||
|
namespace: string;
|
||||||
|
_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Media messages
|
||||||
|
, "shim:media/update": {
|
||||||
|
currentTime: number
|
||||||
|
, _lastCurrentTime: number
|
||||||
|
, customData: any
|
||||||
|
, playbackRate: number
|
||||||
|
, playerState: string
|
||||||
|
, repeatMode: string
|
||||||
|
, _volumeLevel: number
|
||||||
|
, _volumeMuted: boolean
|
||||||
|
, media: unknown // MediaInfo
|
||||||
|
, mediaSessionId: number
|
||||||
|
}
|
||||||
|
, "shim:media/sendMediaMessageResponse": {
|
||||||
|
messageId: string
|
||||||
|
, error: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bridge media messages
|
||||||
|
, "bridge:media/initialize": {
|
||||||
|
sessionId: string
|
||||||
|
, mediaSessionId: number
|
||||||
|
, _internalSessionId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
, "bridge:media/sendMediaMessage": {
|
||||||
|
message: any
|
||||||
|
, messageId: string
|
||||||
|
, _id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bridge messages
|
||||||
|
, "main:receiverSelector/selected": ReceiverSelectionCast
|
||||||
|
, "main:receiverSelector/error": string
|
||||||
|
, "main:receiverSelector/close": {}
|
||||||
|
, "main:receiverSelector/stop": ReceiverSelectionStop
|
||||||
|
|
||||||
|
, "bridge:getInfo": string
|
||||||
|
, "bridge:initialize": { shouldWatchStatus: boolean }
|
||||||
|
|
||||||
|
, "bridge:receiverSelector/open": any
|
||||||
|
, "bridge:receiverSelector/close": {}
|
||||||
|
|
||||||
|
, "bridge:stopReceiverApp": { receiver: Receiver }
|
||||||
|
|
||||||
|
, "bridge:mediaServer/start": {
|
||||||
|
filePath: string
|
||||||
|
, port: number
|
||||||
|
}
|
||||||
|
, "bridge:mediaServer/stop": {}
|
||||||
|
, "mediaCast:mediaServer/started": {
|
||||||
|
mediaPath: string
|
||||||
|
, subtitlePaths: string[]
|
||||||
|
, localAddress: string
|
||||||
|
}
|
||||||
|
, "mediaCast:mediaServer/stopped": {}
|
||||||
|
, "mediaCast:mediaServer/error": {}
|
||||||
|
|
||||||
|
, "main:serviceUp": Receiver
|
||||||
|
, "main:serviceDown": { id: string }
|
||||||
|
|
||||||
|
, "main:receiverStatus": {
|
||||||
|
id: string
|
||||||
|
, status: ReceiverStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface MessageBase<K extends keyof MessageDefinitions> {
|
||||||
|
subject: K;
|
||||||
|
data: MessageDefinitions[K];
|
||||||
|
}
|
||||||
|
|
||||||
|
type Messages = {
|
||||||
|
[K in keyof MessageDefinitions]: MessageBase<K>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For better call semantics, make message data key optional if
|
||||||
|
* specified as blank or with all-optional keys.
|
||||||
|
*/
|
||||||
|
type NarrowedMessage<L extends MessageBase<keyof MessageDefinitions>> =
|
||||||
|
L extends any
|
||||||
|
? {} extends L["data"]
|
||||||
|
? Omit<L, "data"> & Partial<L>
|
||||||
|
: L
|
||||||
|
: never;
|
||||||
|
|
||||||
|
|
||||||
|
export type Message = NarrowedMessage<Messages[keyof Messages]>;
|
||||||
@@ -84,211 +84,3 @@ export interface Receiver {
|
|||||||
port: number;
|
port: number;
|
||||||
status?: ReceiverStatus;
|
status?: ReceiverStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Messages = [
|
|
||||||
{
|
|
||||||
subject: "shim:serviceUp"
|
|
||||||
, data: { id: Receiver["id"] }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:serviceDown"
|
|
||||||
, data: { id: Receiver["id"] }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:launchApp"
|
|
||||||
, data: { receiver: Receiver }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Session messages
|
|
||||||
, {
|
|
||||||
subject: "shim:session/stopped"
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/connected"
|
|
||||||
, data: {
|
|
||||||
sessionId: string;
|
|
||||||
namespaces: Array<{ name: string }>;
|
|
||||||
displayName: string;
|
|
||||||
statusText: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/updateStatus"
|
|
||||||
, data: any
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/impl_addMessageListener"
|
|
||||||
, data: { namespace: string, data: string }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/impl_sendMessage"
|
|
||||||
, data: { messageId: string, error: boolean }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/impl_setReceiverMuted"
|
|
||||||
, data: { volumeId: string, error: boolean }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/impl_setReceiverVolumeLevel"
|
|
||||||
, data: { volumeId: string, error: boolean }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:session/impl_stop"
|
|
||||||
, data: { stopId: string, error: boolean }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bridge session messages
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/initialize"
|
|
||||||
, data: {
|
|
||||||
address: string
|
|
||||||
, port: number
|
|
||||||
, appId: string
|
|
||||||
, sessionId: string
|
|
||||||
}
|
|
||||||
, _id: string;
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/close"
|
|
||||||
, _id: string;
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_leave"
|
|
||||||
, data: { id: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_sendMessage"
|
|
||||||
, data: { namespace: string, message: any, messageId: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_setReceiverMuted"
|
|
||||||
, data: { muted: boolean, volumeId: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_setReceiverVolumeLevel"
|
|
||||||
, data: { newLevel: number, volumeId: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_stop"
|
|
||||||
, data: { stopId: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:session/impl_addMessageListener"
|
|
||||||
, data: { namespace: string }
|
|
||||||
, _id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Media messages
|
|
||||||
, {
|
|
||||||
subject: "shim:media/update"
|
|
||||||
, data: {
|
|
||||||
currentTime: number
|
|
||||||
, _lastCurrentTime: number
|
|
||||||
, customData: any
|
|
||||||
, playbackRate: number
|
|
||||||
, playerState: string
|
|
||||||
, repeatMode: string
|
|
||||||
, _volumeLevel: number
|
|
||||||
, _volumeMuted: boolean
|
|
||||||
, media: any
|
|
||||||
, mediaSessionId: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "shim:media/sendMediaMessageResponse"
|
|
||||||
, data: { messageId: string, error: boolean }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bridge media messages
|
|
||||||
, {
|
|
||||||
subject: "bridge:media/initialize"
|
|
||||||
, data: {
|
|
||||||
sessionId: string
|
|
||||||
, mediaSessionId: number
|
|
||||||
, _internalSessionId: string
|
|
||||||
}
|
|
||||||
, _id: string;
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:media/sendMediaMessage"
|
|
||||||
, data: { message: any, messageId: string }
|
|
||||||
, _id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bridge messages
|
|
||||||
, {
|
|
||||||
subject: "main:receiverSelector/selected"
|
|
||||||
, data: ReceiverSelectionCast
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "main:receiverSelector/error"
|
|
||||||
, data: string
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "main:receiverSelector/close"
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "main:receiverSelector/stop"
|
|
||||||
, data: ReceiverSelectionStop
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:getInfo"
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:initialize"
|
|
||||||
, data: { shouldWatchStatus: boolean }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:receiverSelector/open"
|
|
||||||
, data: any }
|
|
||||||
, {
|
|
||||||
subject: "bridge:receiverSelector/close"
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:stopReceiverApp"
|
|
||||||
, data: { receiver: Receiver }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:mediaServer/start"
|
|
||||||
, data: { filePath: string, port: number }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "bridge:mediaServer/stop"
|
|
||||||
}
|
|
||||||
|
|
||||||
, {
|
|
||||||
subject: "mediaCast:mediaServer/started"
|
|
||||||
, data: {
|
|
||||||
mediaPath: string
|
|
||||||
, subtitlePaths: string[]
|
|
||||||
, localAddress: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "mediaCast:mediaServer/stopped"
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "mediaCast:mediaServer/error"
|
|
||||||
}
|
|
||||||
|
|
||||||
, {
|
|
||||||
subject: "main:serviceUp"
|
|
||||||
, data: Receiver
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "main:serviceDown"
|
|
||||||
, data: { id: string }
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
subject: "main:receiverStatus"
|
|
||||||
, data: { id: string, status: ReceiverStatus }
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export type Message = Messages[number];
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { Transform } from "stream";
|
import { Transform } from "stream";
|
||||||
import { Message } from "./bridge/types";
|
import { Message } from "./bridge/messaging";
|
||||||
|
|
||||||
|
|
||||||
type ResponseHandlerFunction = (message: Message) => Promise<any>;
|
type ResponseHandlerFunction = (message: Message) => Promise<any>;
|
||||||
|
|||||||
@@ -15,17 +15,23 @@ import { MediaInfo } from "./shim/cast/media";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Messages are JSON objects with a `subject` string key and a
|
* Messages are JSON objects with a `subject` string key and a
|
||||||
* generic `data` key.
|
* generic `data` key:
|
||||||
|
* { subject: "...", data: ... }
|
||||||
*
|
*
|
||||||
* Message subjects may include an optional destination and response
|
* Message subjects may include an optional destination and
|
||||||
* name formatted like this:
|
* response name formatted like this:
|
||||||
* ^(destination:)?messageName(\/responseName)?$
|
* ^(destination:)?messageName(\/responseName)?$
|
||||||
*
|
*
|
||||||
* Message formats are specified with subject as a key and data as the
|
* Message formats are specified with subject as a key and data
|
||||||
* value in the message table.
|
* as the value in the message tables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type MessagesBase = {
|
|
||||||
|
/**
|
||||||
|
* Messages exclusively used internally between extension
|
||||||
|
* components.
|
||||||
|
*/
|
||||||
|
type ExtMessageDefinitions = {
|
||||||
"popup:init": { appId?: string }
|
"popup:init": { appId?: string }
|
||||||
, "popup:update": {
|
, "popup:update": {
|
||||||
receivers: Receiver[]
|
receivers: Receiver[]
|
||||||
@@ -46,10 +52,18 @@ type MessagesBase = {
|
|||||||
|
|
||||||
, "main:sessionCreated": {}
|
, "main:sessionCreated": {}
|
||||||
|
|
||||||
, "shim:serviceUp": { id: Receiver["id"] }
|
, "shim:initialized": BridgeInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages that cross the native messaging channel. MUST keep
|
||||||
|
* in-sync with the bridge's version at:
|
||||||
|
* app/bridge/messaging.ts > MessagesBase
|
||||||
|
*/
|
||||||
|
type AppMessageDefinitions = {
|
||||||
|
"shim:serviceUp": { id: Receiver["id"] }
|
||||||
, "shim:serviceDown": { id: Receiver["id"] }
|
, "shim:serviceDown": { id: Receiver["id"] }
|
||||||
|
|
||||||
, "shim:initialized": BridgeInfo
|
|
||||||
, "shim:launchApp": { receiver: Receiver }
|
, "shim:launchApp": { receiver: Receiver }
|
||||||
|
|
||||||
// Session messages
|
// Session messages
|
||||||
@@ -90,6 +104,7 @@ type MessagesBase = {
|
|||||||
, sessionId: string
|
, sessionId: string
|
||||||
, _id: string
|
, _id: string
|
||||||
}
|
}
|
||||||
|
, "bridge:session/close": {}
|
||||||
, "bridge:session/impl_leave": {
|
, "bridge:session/impl_leave": {
|
||||||
id: string
|
id: string
|
||||||
, _id: string
|
, _id: string
|
||||||
@@ -168,6 +183,7 @@ type MessagesBase = {
|
|||||||
filePath: string
|
filePath: string
|
||||||
, port: number
|
, port: number
|
||||||
}
|
}
|
||||||
|
, "bridge:mediaServer/stop": {}
|
||||||
, "mediaCast:mediaServer/started": {
|
, "mediaCast:mediaServer/started": {
|
||||||
mediaPath: string
|
mediaPath: string
|
||||||
, subtitlePaths: string[]
|
, subtitlePaths: string[]
|
||||||
@@ -185,20 +201,25 @@ type MessagesBase = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MessageBase<K extends keyof MessagesBase> {
|
type MessageDefinitions =
|
||||||
|
ExtMessageDefinitions
|
||||||
|
& AppMessageDefinitions;
|
||||||
|
|
||||||
|
|
||||||
|
interface MessageBase<K extends keyof MessageDefinitions> {
|
||||||
subject: K;
|
subject: K;
|
||||||
data: MessagesBase[K];
|
data: MessageDefinitions[K];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Messages = {
|
type Messages = {
|
||||||
[K in keyof MessagesBase]: MessageBase<K>;
|
[K in keyof MessageDefinitions]: MessageBase<K>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For better call semantics, make message data key optional if
|
* For better call semantics, make message data key optional if
|
||||||
* specified as blank or with all-optional keys.
|
* specified as blank or with all-optional keys.
|
||||||
*/
|
*/
|
||||||
type NarrowedMessage<L extends MessageBase<keyof MessagesBase>> =
|
type NarrowedMessage<L extends MessageBase<keyof MessageDefinitions>> =
|
||||||
L extends any
|
L extends any
|
||||||
? {} extends L["data"]
|
? {} extends L["data"]
|
||||||
? Omit<L, "data"> & Partial<L>
|
? Omit<L, "data"> & Partial<L>
|
||||||
|
|||||||
Reference in New Issue
Block a user