fix: embed interface name cleanup (#300)

This commit is contained in:
Peli de Halleux 2023-02-21 14:46:00 -08:00 коммит произвёл GitHub
Родитель 9c63509431
Коммит 40c5e978cd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 91 добавлений и 55 удалений

Просмотреть файл

@ -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<void>
}
@ -17,7 +17,7 @@ export async function downloadUrl(url: string, name: string): Promise<void> {
a.remove()
}
export class BrowserFileStorage implements IFileStorage {
export class BrowserFileStorage implements FileStorage {
saveText(name: string, data: string, mimeType?: string): Promise<void> {
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<void> {
return this.transport
.postMessage({
type: "save-text",
data: { name, data },
} as ISaveTextMessage)
} as EmbedSaveTextMessage)
.then(resp => {})
}
}

Просмотреть файл

@ -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<any>
abstract models(): EmbedFile[]
abstract inputConfigurations(): EmbedFile[]
abstract loadFile(model: EmbedFile): Promise<any>
}
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<Blob> {
async loadFile(model: EmbedFile): Promise<Blob> {
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"

Просмотреть файл

@ -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: {

Просмотреть файл

@ -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<TMessage extends IMessage, TResponse extends IMessage>(
export interface EmbedTransport {
postMessage<TMessage extends EmbedMessage, TResponse extends EmbedMessage>(
msg: TMessage
): Promise<TResponse>
onMessage<TMessage extends IMessage>(
onMessage<TMessage extends EmbedMessage>(
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<string, (msg: any) => 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<TMessage extends IMessage, IAckMessage>(
postMessage<TMessage extends EmbedMessage, AckMessage>(
msg: TMessage
): Promise<IAckMessage> {
let p: Promise<IAckMessage>
): Promise<AckMessage> {
let p: Promise<AckMessage>
msg.id = "jd:" + Math.random()
msg.source = "jacdac"
if (msg.requireAck) {
p = new Promise<IAckMessage>(resolve => {
p = new Promise<AckMessage>(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<TMessage extends IMessage>(
onMessage<TMessage extends EmbedMessage>(
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)

Просмотреть файл

@ -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