From 40c5e978cd60cf4053f8af0ef389a7fd3efba4d5 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Tue, 21 Feb 2023 14:46:00 -0800 Subject: [PATCH] fix: embed interface name cleanup (#300) --- src/embed/filestorage.ts | 14 +++++++------- src/embed/modelstore.ts | 32 ++++++++++++++++---------------- src/embed/protocol.ts | 40 +++++++++++++++++++++++----------------- src/embed/transport.ts | 26 +++++++++++++------------- src/jdom/bus.ts | 34 ++++++++++++++++++++++++++++++++-- 5 files changed, 91 insertions(+), 55 deletions(-) diff --git a/src/embed/filestorage.ts b/src/embed/filestorage.ts index 72916164e..4992b8b92 100644 --- a/src/embed/filestorage.ts +++ b/src/embed/filestorage.ts @@ -1,8 +1,8 @@ import { delay } from "../jdom/utils" -import { ISaveTextMessage } from "./protocol" -import { ITransport } from "./transport" +import { EmbedSaveTextMessage } from "./protocol" +import { EmbedTransport } from "./transport" -export interface IFileStorage { +export interface FileStorage { saveText(name: string, data: string): Promise } @@ -17,7 +17,7 @@ export async function downloadUrl(url: string, name: string): Promise { a.remove() } -export class BrowserFileStorage implements IFileStorage { +export class BrowserFileStorage implements FileStorage { saveText(name: string, data: string, mimeType?: string): Promise { if (!mimeType) { if (/\.(csv|txt)/i.test(name)) mimeType = "text/plain" @@ -30,14 +30,14 @@ export class BrowserFileStorage implements IFileStorage { } } -export class HostedFileStorage implements IFileStorage { - constructor(public readonly transport: ITransport) {} +export class HostedFileStorage implements FileStorage { + constructor(public readonly transport: EmbedTransport) {} saveText(name: string, data: string): Promise { return this.transport .postMessage({ type: "save-text", data: { name, data }, - } as ISaveTextMessage) + } as EmbedSaveTextMessage) .then(resp => {}) } } diff --git a/src/embed/modelstore.ts b/src/embed/modelstore.ts index a38363440..e9c5ca4a9 100644 --- a/src/embed/modelstore.ts +++ b/src/embed/modelstore.ts @@ -1,51 +1,51 @@ import { CHANGE } from "../jdom/constants" import { JDEventSource } from "../jdom/eventsource" import { - IFile, - IFileContent, - IFileLoadMessage, - IModelListMessage, + EmbedFile, + EmbedFileContent, + EmbedFileLoadMessage, + EmbedModelListMessage, } from "./protocol" -import { ITransport } from "./transport" +import { EmbedTransport } from "./transport" export abstract class ModelStore extends JDEventSource { - abstract models(): IFile[] - abstract inputConfigurations(): IFile[] - abstract loadFile(model: IFile): Promise + abstract models(): EmbedFile[] + abstract inputConfigurations(): EmbedFile[] + abstract loadFile(model: EmbedFile): Promise } export class HostedModelStore extends JDEventSource { - private _models: IModelListMessage + private _models: EmbedModelListMessage - constructor(public readonly transport: ITransport) { + constructor(public readonly transport: EmbedTransport) { super() this.handleModelList = this.handleModelList.bind(this) this.transport.onMessage("model-list", this.handleModelList) } - private handleModelList(msg: IModelListMessage) { + private handleModelList(msg: EmbedModelListMessage) { this._models = msg this.emit(CHANGE) } - models(): IFile[] { + models(): EmbedFile[] { return this._models?.data.models?.slice(0) } - inputConfigurations(): IFile[] { + inputConfigurations(): EmbedFile[] { return this._models?.data.inputConfigurations?.slice(0) } - async loadFile(model: IFile): Promise { + async loadFile(model: EmbedFile): Promise { const { path } = model const ack = await this.transport.postMessage({ type: "file-load", requireAck: true, data: { path }, - } as IFileLoadMessage) + } as EmbedFileLoadMessage) - const data = ack?.data?.data as IFileContent + const data = ack?.data?.data as EmbedFileContent if (!data) return undefined const base64 = data.mimetype === "application/octet-stream" diff --git a/src/embed/protocol.ts b/src/embed/protocol.ts index ed746dec8..39b6381ec 100644 --- a/src/embed/protocol.ts +++ b/src/embed/protocol.ts @@ -1,12 +1,12 @@ /** Jacdac IFrame Message protocol */ -export interface IMessage { +export interface EmbedMessage { id?: string source: "jacdac" type: string data: any requireAck?: boolean } -export interface IAckMessage extends IMessage { +export interface EmbedAckMessage extends EmbedMessage { type: "ack" ackId?: string data: { @@ -15,54 +15,60 @@ export interface IAckMessage extends IMessage { error?: any } } -export type LogLevel = "error" | "warn" | "log" | "info" | "debug" -export interface ILogMessage extends IMessage { +export type EmbedLogLevel = "error" | "warn" | "log" | "info" | "debug" +export interface EmbedLogMessage extends EmbedMessage { type: "log" data: { - level?: LogLevel + level?: EmbedLogLevel message: any } } -export interface IThemeMessage extends IMessage { +export interface EmbedThemeMessage extends EmbedMessage { type: "theme" data: { type: "light" | "dark" } } -export type Status = "unknown" | "ready" -export interface IStatusMessage extends IMessage { - type: "status" +export interface EmbedSpecsMessage extends EmbedMessage { + type: "specs" data: { - status: Status + services?: jdspec.ServiceSpec[] } } -export interface ISaveTextMessage extends IMessage { +export type EmbedStatus = "unknown" | "ready" +export interface EmbedStatusMessage extends EmbedMessage { + type: "status" + data: { + status: EmbedStatus + } +} +export interface EmbedSaveTextMessage extends EmbedMessage { type: "save-text" data: { name: string data: string } } -export interface IFile { +export interface EmbedFile { name: string path: string size: number mimetype: string } -export interface IFileContent { +export interface EmbedFileContent { content: string mimetype: string } -export interface IModelListMessage extends IMessage { +export interface EmbedModelListMessage extends EmbedMessage { type: "model-list" data: { - models: IFile[] - inputConfigurations: IFile[] + models: EmbedFile[] + inputConfigurations: EmbedFile[] } } -export interface IFileLoadMessage extends IMessage { +export interface EmbedFileLoadMessage extends EmbedMessage { type: "file-load" requireAck: true data: { diff --git a/src/embed/transport.ts b/src/embed/transport.ts index a47871164..978a425f1 100644 --- a/src/embed/transport.ts +++ b/src/embed/transport.ts @@ -1,11 +1,11 @@ import { JDClient } from "../jdom/client" -import { IAckMessage, IMessage, IStatusMessage } from "./protocol" +import { EmbedAckMessage, EmbedMessage, EmbedStatusMessage } from "./protocol" -export interface ITransport { - postMessage( +export interface EmbedTransport { + postMessage( msg: TMessage ): Promise - onMessage( + onMessage( type: string, handler: (msg: TMessage) => void ): void @@ -14,7 +14,7 @@ export interface ITransport { /** * @internal */ -export class IFrameTransport extends JDClient implements ITransport { +export class IFrameTransport extends JDClient implements EmbedTransport { // eslint-disable-next-line @typescript-eslint/no-explicit-any private readonly ackAwaiters: Record void> = {} @@ -41,23 +41,23 @@ export class IFrameTransport extends JDClient implements ITransport { data: { status: "ready", }, - } as IStatusMessage) + } as EmbedStatusMessage) } /** * Post message to client and awaits for ack if needed * @internal */ - postMessage( + postMessage( msg: TMessage - ): Promise { - let p: Promise + ): Promise { + let p: Promise msg.id = "jd:" + Math.random() msg.source = "jacdac" if (msg.requireAck) { - p = new Promise(resolve => { + p = new Promise(resolve => { this.ackAwaiters[msg.id] = msg => { resolve(msg) } @@ -68,7 +68,7 @@ export class IFrameTransport extends JDClient implements ITransport { return p || Promise.resolve(undefined) } - onMessage( + onMessage( type: string, handler: (msg: TMessage) => void ): void { @@ -78,12 +78,12 @@ export class IFrameTransport extends JDClient implements ITransport { private handleMessage(event: MessageEvent) { if (!this.isOriginValid(event)) return - const msg = event.data as IMessage + const msg = event.data as EmbedMessage if (!msg || msg.source !== "jacdac") return // handle acks separately if (msg.type === "ack") { - const ack = msg as IAckMessage + const ack = msg as EmbedAckMessage const awaiter = this.ackAwaiters[ack.ackId] delete this.ackAwaiters[ack.ackId] if (awaiter) awaiter(msg) diff --git a/src/jdom/bus.ts b/src/jdom/bus.ts index 7c91c7b0b..622e5cd12 100644 --- a/src/jdom/bus.ts +++ b/src/jdom/bus.ts @@ -63,7 +63,13 @@ import { serviceClass } from "./pretty" import { JDNode } from "./node" import { FirmwareBlob, sendStayInBootloaderCommand } from "./flashing" import { JDService } from "./service" -import { isConstRegister, isReading, isSensor } from "./spec" +import { + isConstRegister, + isReading, + isSensor, + loadServiceSpecifications, + serviceSpecifications, +} from "./spec" import { LoggerPriority, LoggerReg, @@ -740,7 +746,15 @@ export class JDBus extends JDNode { this._serviceProviders.forEach(host => (host.bus = undefined)) this._serviceProviders = [] } + this.clearDevices() + this.resetTime(timestamp) + this.emit(CHANGE) + } + /** + * Clears current device list and let's them repopulate + */ + private clearDevices() { // clear devices const devs = this._devices if (devs?.length) { @@ -751,7 +765,6 @@ export class JDBus extends JDNode { this.emit(DEVICE_CHANGE, dev) }) } - this.resetTime(timestamp) } /** @@ -1391,6 +1404,23 @@ ${dev } } + /** + * Gets the current list of service specifications + */ + get serviceSpecifications() { + return serviceSpecifications() + } + + /** + * Updates the current list of device and clears the bus + * @param services + */ + setCustomServiceSpecifications(services: jdspec.ServiceSpec[]) { + loadServiceSpecifications(services) + this.clearDevices() + this.emit(CHANGE) + } + /** * Gets the virtual device created by this bus to handle pipes. * @category Services