* patch: move clients to subfolder

* include version

* hide eventargetobservable

* fix packet defaults

* default device

* default service

* fixing exports

* default bus

* exported register

* top level field

* more defaults

* more defaults

* fixing exports

* moving trace classes

* more docs

* hide some fuctions

* organize members

* more docs

* moving away from smap

* more docs

* avoid SMap
This commit is contained in:
Peli de Halleux 2021-08-23 07:15:27 -07:00 коммит произвёл GitHub
Родитель 7f930f187b
Коммит 922a39d7fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
74 изменённых файлов: 681 добавлений и 271 удалений

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

@ -8,8 +8,8 @@ with applications to rapid prototyping, making, and physical computing.
This repository contains a **TypeScript/JavaScript** client library for the [Jacdac](https://aka.ms/jacdac) protocol.
* **[Jacdac Documentation](https://aka.ms/jacdac/)**
* **[Jacdac TypeScript Developer Documentation](https://microsoft.github.io/jacdac-ts/)**
* **[Jacdac Protocol Documentation](https://aka.ms/jacdac/)**
* **[Jacdac TypeScript API Documentation](https://microsoft.github.io/jacdac-ts/)**
* Discussions at https://github.com/microsoft/jacdac/discussions
* Issues are tracked on https://github.com/microsoft/jacdac/issues

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

@ -33,7 +33,7 @@
"prettier": "prettier --write src/**/*.ts tests/**/*.ts",
"predist": "rm -rf dist",
"dist": "node node_modules/rollup/dist/bin/rollup -c rollup.config.ts",
"watch": "node node_modules/rollup/dist/bin/rollup -c rollup.config.ts -w",
"watch:ts": "node node_modules/rollup/dist/bin/rollup -c rollup.config.ts -w",
"test": "cd tests && node ../node_modules/mocha/bin/mocha --require ts-node/register --watch-extensions ts,tsx -p ./tsconfig.json **/*.spec.ts",
"tools": "npx http-server . -c-1",
"disttools": "cd docs && mkdir tools && cd ../tools && node ./prepare.js && cp * -t ../docs/tools",
@ -41,7 +41,8 @@
"builddtdl": "node dist/jacdac-cli.js --dtdl dist/dtdl --rm=on",
"buildpxt": "cd pxt-jacdac && sh mk.sh",
"builddocs": "node node_modules/typedoc/bin/typedoc && cp .nojekyll docs",
"watchdocs": "node node_modules/typedoc/bin/typedoc --watch"
"watch:docs": "node node_modules/typedoc/bin/typedoc --watch",
"watch": "node node_modules/concurrently/bin/concurrently.js --kill-others \"npm:watch:*\""
},
"devDependencies": {
"@semantic-release/exec": "^5.0.0",
@ -78,7 +79,8 @@
"typescript": "^4.3.5",
"webusb": "^2.2.0",
"yargs-parser": "^20.2.9",
"typedoc": "^0.21.6"
"typedoc": "^0.21.6",
"concurrently": "^6.2.1"
},
"dependencies": {
"@types/node": "^16.7.1",

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

@ -32,7 +32,7 @@ export interface DTDLNode {
// ^[a-zA-Z](?:[a-zA-Z0-9_]*[a-zA-Z0-9])?$
name?: string
displayName?: string
description?: SMap<string>
description?: Record<string, string>
}
export interface DTDLSchema extends DTDLNode {

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

@ -61,7 +61,7 @@ function toUnit(pkt: jdspec.PacketInfo) {
| "varh" | "kvarh" | "kVAh" | "Wh/km" | "KiB" | "GB" | "Mbit/s" | "B/s" | "MB/s" | "mV" | "mA" | "dBm" | "ug/m3"
| "mm/h" | "m/h" | "ppm" | "/100" | "/1000" | "hPa" | "mm" | "cm" | "km" | "km/h";
*/
const units: jdspec.SMap<{ semantic: string; unit: string }> = {
const units: Record<string, { semantic: string; unit: string }> = {
"m/s2": {
semantic: "Acceleration",
unit: "metrePerSecondSquared",
@ -261,7 +261,7 @@ function packetToDTDL(
srv: jdspec.ServiceSpec,
pkt: jdspec.PacketInfo
): DTDLContent {
const types: jdspec.SMap<string> = {
const types: Record<string, string> = {
const: "Property",
rw: "Property",
ro: "Telemetry",

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

@ -15,7 +15,7 @@ import {
serviceSpecificationToDTDL,
} from "../azure-iot/dtdlspec"
import { deviceSpecifications } from "../jdom/spec"
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import { printPacket } from "../jdom/pretty"
import { parseLogicLog, replayLog } from "../jdom/logparser"
import { dashify } from "../../jacdac-spec/spectool/jdspec"

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

@ -19,7 +19,7 @@ export interface InputJSON {
type: number
name: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fields: SMap<FieldJSON>
fields: Record<string, FieldJSON>
child?: BlockJSON
}

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

@ -1,4 +1,4 @@
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import JDIFrameClient from "../jdom/iframeclient"
import { SMap } from "../jdom/utils"
import { IAckMessage, IMessage, IStatusMessage } from "./protocol"
@ -14,7 +14,8 @@ export interface ITransport {
}
export class IFrameTransport extends JDIFrameClient implements ITransport {
private readonly ackAwaiters: SMap<(msg: any) => void> = {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private readonly ackAwaiters: Record<string, (msg: any) => void> = {}
constructor(bus: JDBus) {
super(bus)

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

@ -1,4 +1,4 @@
import { JDBus } from "./bus"
import JDBus from "./bus"
import { JDClient } from "./client"
import { CHANGE, PACKET_PROCESS, PACKET_SEND } from "./constants"
import Packet from "./packet"

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

@ -1,5 +1,5 @@
import Packet from "./packet"
import { JDDevice } from "./device"
import JDDevice from "./device"
import { debounceAsync, strcmp, arrayConcatMany } from "./utils"
import {
JD_SERVICE_INDEX_CTRL,
@ -50,13 +50,13 @@ import {
REFRESH_REGISTER_POLL,
} from "./constants"
import { serviceClass } from "./pretty"
import { JDNode } from "./node"
import JDNode from "./node"
import {
FirmwareBlob,
scanFirmwares,
sendStayInBootloaderCommand,
} from "./flashing"
import { JDService } from "./service"
import JDService from "./service"
import { isConstRegister, isReading, isSensor } from "./spec"
import {
LoggerPriority,
@ -69,9 +69,9 @@ import {
import JDServiceProvider from "./serviceprovider"
import RealTimeClockServer from "../servers/realtimeclockserver"
import { SRV_ROLE_MANAGER } from "../../src/jdom/constants"
import { JDTransport } from "./transport/transport"
import JDTransport from "./transport/transport"
import { BusStatsMonitor } from "./busstats"
import { RoleManagerClient } from "./rolemanagerclient"
import RoleManagerClient from "./clients/rolemanagerclient"
import JDBridge from "./bridge"
import IFrameBridgeClient from "./iframebridgeclient"
import { randomDeviceId } from "./random"
@ -115,6 +115,9 @@ export interface ServiceFilter {
* @category JDOM
*/
export class JDBus extends JDNode {
/**
* @internal
*/
readonly selfDeviceId: string
readonly scheduler: Scheduler
readonly parentOrigin: string
@ -135,7 +138,7 @@ export class JDBus extends JDNode {
private _roleManagerClient: RoleManagerClient
private _minLoggerPriority = LoggerPriority.Debug
private _firmwareBlobs: FirmwareBlob[]
private _gcDevicesEnabled = 0
private _gcDevicesFrozen = 0
private _serviceProviders: JDServiceProvider[] = []
public readonly stats: BusStatsMonitor
@ -169,6 +172,7 @@ export class JDBus extends JDNode {
/**
* Gets the list of transports registers with the bus
* @category Transports and Bridges
*/
get transports() {
return this._transports.slice(0)
@ -176,6 +180,7 @@ export class JDBus extends JDNode {
/**
* Adds a transport to the bus
* @category Transports and Bridges
*/
addTransport(transport: JDTransport) {
if (this._transports.indexOf(transport) > -1) return // already added
@ -187,6 +192,7 @@ export class JDBus extends JDNode {
/**
* Gets the list of bridges registered with the bus
* @category Transports and Bridges
*/
get bridges() {
return this._bridges.slice(0)
@ -196,6 +202,7 @@ export class JDBus extends JDNode {
* Add a bridge to the bus and returns a callback to remove it.
* @param bridge
* @returns callback to remove bridge
* @category Transports and Bridges
*/
addBridge(bridge: JDBridge): () => void {
if (this._bridges.indexOf(bridge) < 0) {
@ -227,6 +234,7 @@ export class JDBus extends JDNode {
/**
* Connects the bus going through the transports chronologically. Does nothing if already connected.
* @param background connection was triggered automatically
* @category Lifecycle
*/
async connect(background?: boolean) {
if (this.connected) return
@ -241,6 +249,7 @@ export class JDBus extends JDNode {
/**
* Disconnects the bus and any connected transport.
* @category Lifecycle
*/
async disconnect() {
for (const transport of this._transports) {
@ -249,7 +258,8 @@ export class JDBus extends JDNode {
}
/**
* Starts process packet and updates the JDOM nodes
* Starts to process packets and updates the JDOM nodes
* @category Lifecycle
*/
start() {
if (!this._announceInterval)
@ -267,6 +277,7 @@ export class JDBus extends JDNode {
/**
* Stops processing packets
* @category Lifecycle
*/
async stop() {
await this.disconnect()
@ -284,6 +295,7 @@ export class JDBus extends JDNode {
/**
* Stops the bus and all transport connections.
* @category Lifecycle
*/
async dispose() {
console.debug(`${this.id}: disposing.`)
@ -294,6 +306,7 @@ export class JDBus extends JDNode {
/**
* Indicates that the bus is sending commands keep devices in bootloader mode.
* This property is signaled by CHANGE.
* @category Lifecycle
*/
get safeBoot() {
return !!this._safeBootInterval
@ -302,6 +315,7 @@ export class JDBus extends JDNode {
/**
* Turn on or off the safe boot mode where the bus keeps devices in bootloader mode.
* Triggers a CHANGE event.
* @category Lifecycle
*/
set safeBoot(enabled: boolean) {
if (enabled && !this._safeBootInterval) {
@ -321,6 +335,7 @@ export class JDBus extends JDNode {
/**
* Indicates if any of the transports is connected.
* Some transports might be in the process of connecting or disconnecting.
* @category Lifecycle
*/
get connected() {
return this._transports.some(t => t.connected)
@ -329,6 +344,7 @@ export class JDBus extends JDNode {
/**
* Indicates if any of the transports is disconnected.
* Some transports might be in the process of connecting or disconnecting.
* @category Lifecycle
*/
get disconnected() {
return this._transports.every(t => t.disconnected)
@ -360,31 +376,56 @@ export class JDBus extends JDNode {
/**
* Gets a unique identifier for this node in the Jacdac DOM.
* @category JDOM
*/
get id(): string {
return this.nodeKind
}
/**
* Gets the bus name
* @category JDOM
*/
get name(): string {
return "bus"
}
/**
* Gets the bus name
* @category JDOM
*/
get friendlyName(): string {
return this.name
}
get qualifiedName(): string {
/**
* Gets the bus name
* @category JDOM
*/
get qualifiedName(): string {
return this.name
}
/**
* Returns the ``BUS_NODE_NAME``
* @category JDOM
*/
get nodeKind(): string {
return BUS_NODE_NAME
}
/**
* Gets the default role manager service client, if any
* @category Service Clients
*/
get roleManager(): RoleManagerClient {
return this._roleManagerClient
}
/**
* Sets the default role manager service client
* @category Service Clients
*/
setRoleManagerService(service: JDService) {
//console.log(`set role manager`, { service })
// clean if needed
@ -411,6 +452,12 @@ export class JDBus extends JDNode {
return this.id
}
/**
* Resolves a JDOM node from an identifier
* @param id node identifier
* @returns node if found, undefined otherwise
* @category JDOM
*/
node(id: string): JDNode {
const resolve = (): JDNode => {
const m =
@ -472,6 +519,10 @@ export class JDBus extends JDNode {
}
}
/**
* Returns undefined
* @category JDOM
*/
get parent(): JDNode {
return undefined
}
@ -489,20 +540,32 @@ export class JDBus extends JDNode {
this.setRoleManagerService(service)
}
async sendPacketAsync(p: Packet) {
p.timestamp = this.timestamp
this.emit(PACKET_SEND, p)
/**
* Sends a packet to the bus
* @param packet packet to send
*/
async sendPacketAsync(packet: Packet) {
packet.timestamp = this.timestamp
this.emit(PACKET_SEND, packet)
await Promise.all(
this._transports.map(transport => transport.sendPacketAsync(p))
this._transports.map(transport => transport.sendPacketAsync(packet))
)
}
/**
* Gets the list of known firmware blobs
* @category Firmware
*/
get firmwareBlobs() {
return this._firmwareBlobs
}
set firmwareBlobs(blobs: FirmwareBlob[]) {
/**
* Sets the list of known firmware blobs
* @category Firmware
*/
set firmwareBlobs(blobs: FirmwareBlob[]) {
this._firmwareBlobs = blobs
this.emit(FIRMWARE_BLOBS_CHANGE)
this.emit(CHANGE)
@ -510,6 +573,7 @@ export class JDBus extends JDNode {
/**
* Gets the current list of known devices on the bus
* @category Service Clients
*/
devices(options?: DeviceFilter) {
if (options?.serviceName && options?.serviceClass > -1)
@ -533,6 +597,7 @@ export class JDBus extends JDNode {
/**
* Gets the current list of service providers on the bus
* @category Service Servers
*/
serviceProviders(): JDServiceProvider[] {
return this._serviceProviders.slice(0)
@ -541,13 +606,16 @@ export class JDBus extends JDNode {
/**
* Get a service providers for a given device
* @param deviceId
* @category Service Servers
*/
findServiceProvider(deviceId: string) {
return this._serviceProviders.find(d => d.deviceId === deviceId)
}
/**
* Adds the service provider to the bus
* Adds the service provider to the bus and returns the associated devoce
* @param provider instance to add
* @category Service Servers
*/
addServiceProvider(provider: JDServiceProvider) {
if (provider && this._serviceProviders.indexOf(provider) < 0) {
@ -563,7 +631,8 @@ export class JDBus extends JDNode {
/**
* Removes the service provider from the bus
* @param provider
* @param provider instance to remove
* @category Service Servers
*/
removeServiceProvider(provider: JDServiceProvider) {
if (!provider) return
@ -592,12 +661,17 @@ export class JDBus extends JDNode {
}
}
/**
* Gets the list of devices
* @category JDOM
*/
get children(): JDNode[] {
return this.devices()
}
/**
* Gets the current list of services from all the known devices on the bus
* @category Service Clients
*/
services(options?: ServiceFilter & DeviceFilter): JDService[] {
return arrayConcatMany(
@ -607,7 +681,10 @@ export class JDBus extends JDNode {
/**
* Gets a device on the bus
* @param id
* @param id device identifier to query
* @param skipCreate do not create new device if missing
* @param pkt packet that generated this device query
* @category Service Clients
*/
device(id: string, skipCreate?: boolean, pkt?: Packet) {
if (id === "0000000000000000" && !skipCreate) {
@ -633,6 +710,11 @@ export class JDBus extends JDNode {
}
private _debouncedScanFirmwares: () => void
/**
* Enables or disables automatically scanning and resolving firmware updates
* @param enabled true to scan firmware in the background
* @category Firmware
*/
setBackgroundFirmwareScans(enabled: boolean) {
const isSSR = typeof window === "undefined"
if (isSSR) enabled = false
@ -657,16 +739,28 @@ export class JDBus extends JDNode {
}
}
freezeDevices() {
this._gcDevicesEnabled++
/**
* Push a context to disable cleaning device that haven't issued packets recently.
* @category Lifecycle
*/
pushDeviceFrozen() {
this._gcDevicesFrozen++
}
unfreezeDevices() {
this._gcDevicesEnabled = Math.max(0, this._gcDevicesEnabled - 1)
/**
* Pop a context to disable cleaning device that haven't issued packets recently.
* @category Lifecycle
*/
popDeviceFrozen() {
this._gcDevicesFrozen = Math.max(0, this._gcDevicesFrozen - 1)
}
/**
* Indicates if the device list if currently frozen.
* @category Lifecycle
*/
get devicesFrozen() {
return this._gcDevicesEnabled > 0
return this._gcDevicesFrozen > 0
}
private gcDevices() {
@ -704,6 +798,7 @@ export class JDBus extends JDNode {
/**
* Ingests and process a packet received from the bus.
* @param pkt a jacdac packet
* @internal
*/
processPacket(pkt: Packet) {
if (!pkt.isMultiCommand && !pkt.device) {
@ -752,6 +847,10 @@ export class JDBus extends JDNode {
}
}
/**
* Gets the virtual device created by this bus to handle pipes.
* @category Service Clients
*/
get selfDevice() {
return this.device(this.selfDeviceId)
}
@ -810,13 +909,22 @@ export class JDBus extends JDNode {
}
}
/**
* Indicates if registers are automatically refreshed in the background.
* @category Service Clients
*/
get backgroundRefreshRegisters() {
return !!this._refreshRegistersInterval
}
set backgroundRefreshRegisters(value: boolean) {
if (!!value !== this.backgroundRefreshRegisters) {
if (!value) {
/**
* Enables or disables automatically refreshing registers in the background.
* @param enabled true to automatically refresh registers
* @category Service Clients
*/
set backgroundRefreshRegisters(enabled: boolean) {
if (!!enabled !== this.backgroundRefreshRegisters) {
if (!enabled) {
if (this._refreshRegistersInterval)
this.scheduler.clearInterval(this._refreshRegistersInterval)
this._refreshRegistersInterval = undefined
@ -999,3 +1107,5 @@ export class JDBus extends JDNode {
})
}
}
export default JDBus

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

@ -1,4 +1,4 @@
import { JDBus } from "./bus"
import JDBus from "./bus"
import { CHANGE, PACKET_PROCESS, PACKET_SEND, SELF_ANNOUNCE } from "./constants"
import { JDEventSource } from "./eventsource"
import Packet from "./packet"

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

@ -30,3 +30,4 @@ export class JDClient extends JDEventSource {
this.unmounted = true
}
}
export default JDClient

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

@ -1,14 +1,14 @@
import * as U from "./utils"
import Packet from "./packet"
import { REPORT_RECEIVE, SRV_MODEL_RUNNER } from "./constants"
import { JDService } from "./service"
import { ModelRunnerCmd, ModelRunnerReg } from "./constants"
import { bufferToArray, NumberFormat } from "./buffer"
import { OutPipe } from "./pipes"
import { JDRegister } from "./register"
import { JDServiceClient } from "./serviceclient"
import { serviceSpecificationFromClassIdentifier } from "./spec"
import { jdunpack } from "./pack"
import * as U from "../utils"
import Packet from "../packet"
import { REPORT_RECEIVE, SRV_MODEL_RUNNER } from "../constants"
import JDService from "../service"
import { ModelRunnerCmd, ModelRunnerReg } from "../constants"
import { bufferToArray, NumberFormat } from "../buffer"
import { OutPipe } from "../pipes"
import JDRegister from "../register"
import { JDServiceClient } from "../serviceclient"
import { serviceSpecificationFromClassIdentifier } from "../spec"
import { jdunpack } from "../pack"
/*
enum SampleType : u8 {
@ -135,6 +135,7 @@ export class ModelRunnerClient extends JDServiceClient {
return info
}
}
export default ModelRunnerClient
export interface TFModelStats {
modelSize: number

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

@ -1,7 +1,7 @@
import {
addServiceProvider,
serviceProviderDefinitionFromServiceClass,
} from "../servers/servers"
} from "../../servers/servers"
import {
CHANGE,
DEVICE_ANNOUNCE,
@ -15,19 +15,19 @@ import {
SRV_LOGGER,
SRV_ROLE_MANAGER,
SystemEvent,
} from "./constants"
import { jdpack, jdunpack } from "./pack"
import Packet from "./packet"
import { InPipeReader } from "./pipes"
import { JDService } from "./service"
import { JDServiceClient } from "./serviceclient"
} from "../constants"
import { jdpack, jdunpack } from "../pack"
import Packet from "../packet"
import { InPipeReader } from "../pipes"
import JDService from "../service"
import { JDServiceClient } from "../serviceclient"
import {
arrayConcatMany,
debounceAsync,
fromHex,
groupBy,
toHex,
} from "./utils"
} from "../utils"
export interface Role {
deviceId: string
@ -267,3 +267,4 @@ export class RoleManagerClient extends JDServiceClient {
}
}
}
export default RoleManagerClient

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

@ -1,15 +1,15 @@
import {
SensorAggregatorReg,
SensorAggregatorSampleType,
} from "../../jacdac-spec/dist/specconstants"
import { bufferToArray, NumberFormat } from "./buffer"
import { JD_SERIAL_MAX_PAYLOAD_SIZE, REPORT_RECEIVE } from "./constants"
import { jdpack } from "./pack"
import { JDRegister } from "./register"
import { JDService } from "./service"
import { JDServiceClient } from "./serviceclient"
import { isReading, serviceSpecificationFromClassIdentifier } from "./spec"
import { bufferConcat, bufferConcatMany, fromHex } from "./utils"
} from "../../../jacdac-spec/dist/specconstants"
import { bufferToArray, NumberFormat } from "../buffer"
import { JD_SERIAL_MAX_PAYLOAD_SIZE, REPORT_RECEIVE } from "../constants"
import { jdpack } from "../pack"
import JDRegister from "../register"
import JDService from "../service"
import { JDServiceClient } from "../serviceclient"
import { isReading, serviceSpecificationFromClassIdentifier } from "../spec"
import { bufferConcat, bufferConcatMany, fromHex } from "../utils"
export interface SensorAggregatorInputConfig {
serviceClass: number
@ -168,3 +168,4 @@ export class SensorAggregatorClient extends JDServiceClient {
return info
}
}
export default SensorAggregatorClient

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

@ -1,12 +1,16 @@
import { CHANGE, SettingsCmd } from "./constants"
import { jdpack, jdunpack } from "./pack"
import Packet from "./packet"
import { InPipeReader } from "./pipes"
import { JDService } from "./service"
import { JDServiceClient } from "./serviceclient"
import { bufferToString, stringToBuffer } from "./utils"
import { CHANGE, SettingsCmd } from "../constants"
import { jdpack, jdunpack } from "../pack"
import Packet from "../packet"
import { InPipeReader } from "../pipes"
import JDService from "../service"
import { JDServiceClient } from "../serviceclient"
import { bufferToString, stringToBuffer } from "../utils"
export default class SettingsClient extends JDServiceClient {
/**
* A settings service client implementation.
* @category Clients
*/
export class SettingsClient extends JDServiceClient {
constructor(service: JDService) {
super(service)
service.registersUseAcks = true
@ -90,3 +94,4 @@ export default class SettingsClient extends JDServiceClient {
this.emit(CHANGE)
}
}
export default SettingsClient

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

@ -11,7 +11,11 @@ import Packet from "./packet"
import JDRegisterServer from "./registerserver"
import JDServiceServer from "./serviceserver"
export default class ControlServer extends JDServiceServer {
/**
* A control service server
* @category Servers
*/
export class ControlServer extends JDServiceServer {
readonly deviceDescription: JDRegisterServer<[string]>
readonly mcuTemperature: JDRegisterServer<[number]>
readonly resetIn: JDRegisterServer<[number]>
@ -102,3 +106,5 @@ export default class ControlServer extends JDServiceServer {
this.emit(CHANGE)
}
}
export default ControlServer

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

@ -37,12 +37,12 @@ import {
REPORT_UPDATE,
SERIAL_TRANSPORT,
} from "./constants"
import { read32, SMap, bufferEq, setAckError, read16 } from "./utils"
import { read32, bufferEq, setAckError, read16 } from "./utils"
import { getNumber, NumberFormat } from "./buffer"
import { JDBus, ServiceFilter } from "./bus"
import { JDService } from "./service"
import JDService from "./service"
import { serviceClass, shortDeviceId } from "./pretty"
import { JDNode } from "./node"
import JDNode from "./node"
import { isInstanceOf } from "./spec"
import { FirmwareInfo } from "./flashing"
import { QualityOfService } from "./qualityofservice"
@ -71,17 +71,29 @@ export interface JDServiceGroup {
* @category JDOM
*/
export class JDDevice extends JDNode {
/**
* Indicates if the device is connected to a bus
* @category Lifecycle
*/
connected: boolean
private _source: string
private _replay: boolean
private _lost: boolean
private _servicesData: Uint8Array
private _statusLight: LEDController
/**
* Timestamp of the last packet received from the device
* @category Lifecycle
*/
lastSeen: number
/**
* Timestamp of the last service update packet received from the device
* @category Lifecycle
*/
lastServiceUpdate: number
private _shortId: string
private _services: JDService[]
private _ports: SMap<PipeInfo>
private _ports: Record<string, PipeInfo>
private _firmwareInfo: FirmwareInfo
private _ackAwaiting: AckAwaiter[]
private _flashing = false
@ -131,6 +143,7 @@ export class JDDevice extends JDNode {
/**
* Gets a unique identifier for this device in the bus
* @category JDOM
*/
get id() {
return `${this.nodeKind}:${this.deviceId}`
@ -138,6 +151,7 @@ export class JDDevice extends JDNode {
/**
* Gets the short id of the device
* @category JDOM
*/
get name() {
return this.shortId
@ -145,6 +159,7 @@ export class JDDevice extends JDNode {
/**
* Identifies node as a device
* @category JDOM
*/
get nodeKind() {
return DEVICE_NODE_NAME
@ -171,15 +186,24 @@ export class JDDevice extends JDNode {
/**
* Indicates if the device is part of a trace replay
* @category Lifecycle
*/
get replay() {
return this._replay
}
/**
* Gets the device short name
* @category JDOM
*/
get friendlyName() {
return this.shortId
}
/**
* Gets the device short name
* @category JDOM
*/
get qualifiedName() {
return this.shortId
}
@ -187,6 +211,7 @@ export class JDDevice extends JDNode {
/**
* Indicates if service information is available.
* This happens after a announce packet has been received.
* @category Lifecycle
*/
get announced(): boolean {
return !!this._servicesData?.length
@ -194,6 +219,7 @@ export class JDDevice extends JDNode {
/**
* Gets the control announce flag from the annouce packet.
* @category Announce
*/
get announceFlags(): ControlAnnounceFlags {
return this._servicesData ? read16(this._servicesData, 0) : 0
@ -201,6 +227,7 @@ export class JDDevice extends JDNode {
/**
* Gets the restart counter from the announce packet.
* @category Announce
*/
get restartCounter(): number {
return this.announceFlags & ControlAnnounceFlags.RestartCounterSteady
@ -208,6 +235,7 @@ export class JDDevice extends JDNode {
/**
* Gets the status light announce flags from the announce packet.
* @category Announce
*/
get statusLightFlags(): ControlAnnounceFlags {
return this.announceFlags & ControlAnnounceFlags.StatusLightRgbFade
@ -215,6 +243,7 @@ export class JDDevice extends JDNode {
/**
* Indicates if the device is announced as a client
* @category Announce
*/
get isClient() {
return !!(this.announceFlags & ControlAnnounceFlags.IsClient)
@ -223,11 +252,16 @@ export class JDDevice extends JDNode {
/**
* Gets the number of packets sent since the last announce packet,
* as read from the announce packet.
* @category Announce
*/
get packetCount(): number {
return this._servicesData?.[2] || 0
}
/**
* Gets the device short identifier
* @category JDOM
*/
get shortId() {
// TODO measure if caching is worth it
if (!this._shortId) this._shortId = shortDeviceId(this.deviceId)
@ -236,6 +270,7 @@ export class JDDevice extends JDNode {
/**
* Gets the bus instance hosting this device.
* @category JDOM
*/
get parent(): JDNode {
return this.bus
@ -243,6 +278,7 @@ export class JDDevice extends JDNode {
/**
* Gets the firmware information if any.
* @category Firmware
*/
get firmwareInfo() {
return this._firmwareInfo
@ -250,6 +286,7 @@ export class JDDevice extends JDNode {
/**
* Sets the firmware information.
* @category Firmware
*/
set firmwareInfo(info: FirmwareInfo) {
const changed =
@ -265,6 +302,7 @@ export class JDDevice extends JDNode {
/**
* Indicates if no packet from this device has been observed in a while.
* @category Lifecycle
*/
get lost() {
return this._lost
@ -272,6 +310,8 @@ export class JDDevice extends JDNode {
/**
* Sets the lost status
* @category Lifecycle
* @internal
*/
set lost(v: boolean) {
if (!!v === this._lost) return
@ -292,6 +332,7 @@ export class JDDevice extends JDNode {
/**
* A flashing sequence is in progress
* @category Lifecycle
*/
get flashing() {
return this._flashing
@ -299,6 +340,7 @@ export class JDDevice extends JDNode {
/**
* Sets the flashing sequence state
* @category Lifecycle
*/
set flashing(value: boolean) {
if (value !== this._flashing) {
@ -309,10 +351,17 @@ export class JDDevice extends JDNode {
}
}
/**
* Gets the number of events received by the service clients in this device
* @category Lifecycle
*/
get eventCounter() {
return this._eventCounter
}
/**
* @internal
*/
set eventCounter(v: number) {
this._eventCounter = v
}
@ -321,6 +370,7 @@ export class JDDevice extends JDNode {
* Indicates if the device contains at least one service matching the service class
* @param serviceClass service class to match
* @returns true if at least one service present
* @category Service Clients
*/
hasService(serviceClass: number): boolean {
if (!this.announced) return false
@ -338,6 +388,7 @@ export class JDDevice extends JDNode {
* Gets or allocates a pipe port
* @param id identifier of the port
* @returns a pipe port
* @category Pipes
*/
port(id: number) {
if (!this._ports) this._ports = {}
@ -349,6 +400,7 @@ export class JDDevice extends JDNode {
/**
* Gets the number of services hosted by the device
* @category Service Clients
*/
get serviceLength() {
if (!this.announced) return 0
@ -359,6 +411,7 @@ export class JDDevice extends JDNode {
* Gets the service class at a given index
* @param index index of the service
* @returns service class
* @category Service Clients
*/
serviceClassAt(index: number): number {
if (index == 0) return 0
@ -369,6 +422,10 @@ export class JDDevice extends JDNode {
return read32(this._servicesData, index)
}
/**
* Gets the list of service classes
* @category Service Clients
*/
get serviceClasses(): number[] {
const r = []
const n = this.serviceLength
@ -400,6 +457,7 @@ export class JDDevice extends JDNode {
* Gets the service client at the given service index
* @param serviceIndex index of the service client
* @returns service client
* @category Service Clients
*/
service(serviceIndex: number): JDService {
if (!this.announced) return undefined
@ -412,6 +470,7 @@ export class JDDevice extends JDNode {
* Gets a filtered list of service clients.
* @param options filters for services
* @returns services matching the filter
* @category Service Clients
*/
services(options?: ServiceFilter): JDService[] {
if (!this.announced) return []
@ -439,6 +498,7 @@ export class JDDevice extends JDNode {
/**
* Gets the list of child services.
* @category JDOM
*/
get children(): JDNode[] {
return this.services()
@ -452,6 +512,9 @@ export class JDDevice extends JDNode {
return pkt.sendCmdAsync(this)
}
/**
* @internal
*/
processAnnouncement(pkt: Packet) {
this.qualityOfService.processAnnouncement(pkt)
@ -500,6 +563,9 @@ export class JDDevice extends JDNode {
}
}
/**
* @internal
*/
processPacket(pkt: Packet) {
this.qualityOfService.processPacket(pkt)
this.lost = false
@ -511,6 +577,9 @@ export class JDDevice extends JDNode {
if (service) service.processPacket(pkt)
}
/**
* @internal
*/
disconnect() {
this.connected = false
this.emit(DISCONNECT)
@ -529,6 +598,10 @@ export class JDDevice extends JDNode {
return this._statusLight
}
/**
* Sends an ``identify`` command to the device
* @category Lifecycle
*/
async identify() {
if (this._identifying) return
@ -550,10 +623,18 @@ export class JDDevice extends JDNode {
}
}
/**
* Indicates the device should be identifying.
* @category Lifecycle
*/
get identifying() {
return this._identifying
}
/**
* Sends a ``reset`` command to the device
* @category Lifecycle
*/
reset() {
return this.service(0)?.sendCmdAsync(ControlCmd.Reset)
}
@ -652,3 +733,5 @@ export class JDDevice extends JDNode {
await this.sendPktWithAck(pkt)
}
}
export default JDDevice

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

@ -1,5 +1,5 @@
import { JDNode } from "./node"
import { JDService } from "./service"
import JDNode from "./node"
import JDService from "./service"
import Packet from "./packet"
import { intOfBuffer } from "./buffer"
import {
@ -9,9 +9,9 @@ import {
EVENT_NODE_NAME,
} from "./constants"
import { isEvent } from "./spec"
import { JDServiceMemberNode } from "./servicemembernode"
import JDServiceMemberNode from "./servicemembernode"
import { DecodedPacket } from "./pretty"
import { JDField } from "./field"
import JDField from "./field"
/**
* A Jacdac event client.
@ -63,6 +63,9 @@ export class JDEvent extends JDServiceMemberNode {
return this._lastReportPkt?.decoded
}
/**
* @internal
*/
processEvent(pkt: Packet) {
const { device } = this.service
const ec = (device.eventCounter || 0) + 1
@ -89,3 +92,5 @@ export class JDEvent extends JDServiceMemberNode {
device.eventCounter = pkt.eventCounter
}
}
export default JDEvent

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

@ -46,21 +46,53 @@ export function dependencyId(nodes: IEventSource[]) {
}
let nextNodeId = 0
/**
* Base class for evented nodes in Jacdac
*/
export class JDEventSource implements IEventSource {
public readonly nodeId = nextNodeId++ // debugging
private readonly listeners: SMap<Listener[]> = {}
readonly eventStats: SMap<number> = {}
newListenerStats: SMap<number> = undefined
/**
* Gets an internal unique node identifier, mostly used for debugging.
* @category JDOM
*/
public readonly nodeId = nextNodeId++
private readonly listeners: Record<string, Listener[]> = {}
/**
* Gets a counter of event emit calls.
* @category JDOM
*/
readonly eventStats: Record<string, number> = {}
/**
* Gets a counter map from events to new listener counts
* @category JDOM
*/
newListenerStats: Record<string, number> = undefined
constructor() {}
/**
* Registers a handler for one or more events
* @param eventName name or names of the events to subscribe
* @param handler handler to register
* @returns current object instance
*/
on(eventName: string | string[], handler: EventHandler) {
if (!handler) return this
normalizeEventNames(eventName).forEach(eventName =>
this.addListenerInternal(eventName, handler, false)
)
return this
}
/**
* Unregisters a handler for one or more events
* @param eventName name or names of the events to subscribe
* @param handler handler to unregister
* @returns current object instance
*/
off(eventName: string | string[], handler: EventHandler) {
normalizeEventNames(eventName).forEach(eventName =>
this.removeListenerInternal(eventName, handler)
@ -68,6 +100,12 @@ export class JDEventSource implements IEventSource {
return this
}
/**
* Registers a handler for one or more events to run only once.
* @param eventName name or names of the events to subscribe
* @param handler handler to execute
* @returns current object instance
*/
once(eventName: string | string[], handler: EventHandler) {
normalizeEventNames(eventName).forEach(eventName =>
this.addListenerInternal(eventName, handler, true)
@ -129,12 +167,13 @@ export class JDEventSource implements IEventSource {
}
/**
* Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each.
* Synchronously calls each of the listeners registered for the event named eventName,
* in the order they were registered, passing the supplied arguments to each.
* @param eventName
* @param args
* @category JDOM
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
emit(eventName: string, ...args: any[]): boolean {
emit(eventName: string, ...args: unknown[]): boolean {
if (!eventName) return false
// track event stats
@ -164,12 +203,24 @@ export class JDEventSource implements IEventSource {
return true
}
/**
* Gets the number of listeners for a given event
* @param eventName name of the event
* @returns number of registered handlers
* @category JDOM
*/
listenerCount(eventName: string): number {
if (!eventName) return 0
const listeners = this.listeners[eventName]
return listeners?.length || 0
}
/**
* Gets the list stack trace where an event was registered. Only enabled if ``Flags.debug`` is true.
* @param eventName name of the event
* @returns stack traces where a listener was added
* @category JDOM
*/
listenerStackTraces(eventName: string): string[] {
const listeners = this.listeners[eventName]
return listeners?.map(listener => listener.stackTrace)
@ -177,6 +228,7 @@ export class JDEventSource implements IEventSource {
/**
* Returns an array listing the events for which the emitter has registered listeners.
* @category JDOM
*/
eventNames(): string[] {
return Object.keys(this.listeners)
@ -185,6 +237,7 @@ export class JDEventSource implements IEventSource {
/**
* Creates an observable from the given event
* @param eventName
* @category JDOM
*/
observe<T>(eventName: string | string[]): Observable<T> {
return fromEvent<T>(this, eventName)
@ -194,6 +247,7 @@ export class JDEventSource implements IEventSource {
* Subscribes to an event and returns the unsubscription handler
* @param eventName
* @param next
* @category JDOM
*/
subscribe<T>(
eventName: string | string[],
@ -203,6 +257,10 @@ export class JDEventSource implements IEventSource {
return observer.subscribe({ next }).unsubscribe
}
/**
* Gets a counter for the ``CHANGE`` event.
* @category JDOM
*/
get changeId() {
return this.eventStats[CHANGE] || 0
}

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

@ -1,7 +1,7 @@
import { FIELD_NODE_NAME } from "./constants"
import { JDNode } from "./node"
import JDNode from "./node"
import { DecodedMember } from "./pretty"
import { JDServiceMemberNode } from "./servicemembernode"
import JDServiceMemberNode from "./servicemembernode"
/**
* A Jacdac field.
@ -70,3 +70,5 @@ export class JDField extends JDNode {
return this.decoded?.value
}
}
export default JDField

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

@ -1,4 +1,4 @@
export default class Flags {
export class Flags {
/**
* Enables additional logging and diagnostics
*/
@ -22,3 +22,4 @@ export default class Flags {
*/
static storage = false
}
export default Flags

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

@ -1,7 +1,7 @@
import { bufferToArray, NumberFormat, getNumber } from "./buffer"
import { JDBus } from "./bus"
import JDBus from "./bus"
import Packet from "./packet"
import { JDDevice } from "./device"
import JDDevice from "./device"
import {
BootloaderCmd,
ControlCmd,
@ -32,7 +32,7 @@ const BL_PAGE_DELAY = 5
let _startTime = 0
const uf2ExtTags: SMap<number> = {
const uf2ExtTags: Record<string, number> = {
version: -0x9fc7bc,
name: -0x650d9d,
pageSize: 0x0be9f7,
@ -431,7 +431,7 @@ async function scanCore(
makeFlashers: boolean,
recovery = false
) {
const devices: SMap<FirmwareInfo> = {}
const devices: Record<string, FirmwareInfo> = {}
const flashers: FlashClient[] = []
try {
bus.on(PACKET_REPORT, handlePkt)

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

@ -5,7 +5,7 @@ import {
SRV_ROLE_MANAGER,
SRV_SETTINGS,
} from "../jdom/constants"
import { JDBus } from "./bus"
import JDBus from "./bus"
import {
CHANGE,
DEVICE_ANNOUNCE,
@ -13,18 +13,12 @@ import {
PACKET_PROCESS,
PACKET_SEND,
} from "./constants"
import { JDDevice } from "./device"
import JDDevice from "./device"
import JDIFrameClient from "./iframeclient"
import { resolveMakecodeServiceFromClassIdentifier } from "./makecode"
import Packet from "./packet"
import { JDService } from "./service"
import {
arrayConcatMany,
debounce,
roundWithPrecision,
SMap,
unique,
} from "./utils"
import JDService from "./service"
import { arrayConcatMany, debounce, roundWithPrecision, unique } from "./utils"
export interface PacketMessage {
channel: "jacdac"
@ -42,20 +36,20 @@ interface SimulatorRunOptions {
builtinParts?: string[]
fnArgs?: unknown
aspectRatio?: number
partDefinitions?: SMap<unknown> // SMap<PartDefinition>;
partDefinitions?: Record<string, unknown> // SMap<PartDefinition>;
mute?: boolean
highContrast?: boolean
light?: boolean
cdnUrl?: string
localizedStrings?: SMap<string>
localizedStrings?: Record<string, string>
refCountingDebug?: boolean
version?: string
clickTrigger?: boolean
breakOnStart?: boolean
storedState?: SMap<unknown>
storedState?: Record<string, unknown>
autoRun?: boolean
ipc?: boolean
dependencies?: SMap<string> // Map<string>;
dependencies?: Record<string, string> // Map<string>;
// single iframe, no message simulators
single?: boolean
}
@ -71,7 +65,7 @@ const ignoredServices = [
/**
* A client that bridges received and sent packets to a parent iframe
*/
export default class IFrameBridgeClient extends JDIFrameClient {
export class IFrameBridgeClient extends JDIFrameClient {
// this is a unique id used to trace packets sent by this bridge
readonly bridgeId = "bridge" + Math.random()
packetSent = 0
@ -284,3 +278,5 @@ export default class IFrameBridgeClient extends JDIFrameClient {
)
}
}
export default IFrameBridgeClient

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

@ -1,7 +1,7 @@
import { JDBus } from "./bus"
import { JDClient } from "./client"
import JDBus from "./bus"
import JDClient from "./client"
export default class JDIFrameClient extends JDClient {
export class JDIFrameClient extends JDClient {
constructor(readonly bus: JDBus) {
super()
}
@ -15,6 +15,8 @@ export default class JDIFrameClient extends JDClient {
}
}
export default JDIFrameClient
export function inIFrame() {
try {
return typeof window !== "undefined" && window.self !== window.top

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

@ -3,7 +3,6 @@ export * from "./utils"
export * from "./buffer"
export * from "./msgpack"
export * from "./observable"
export * from "./eventtargetobservable"
export * from "./packet"
export * from "./eventsource"
export * from "./node"
@ -22,19 +21,17 @@ export * from "./speedtest"
export * from "./spec"
export * from "./client"
export * from "./serviceclient"
export * from "./sensoraggregatorclient"
export * from "./modelrunner"
export * from "./clients/sensoraggregatorclient"
export * from "./iframeclient"
export * from "./iframebridgeclient"
export * from "./frame"
export * from "./traceplayer"
export * from "./trace/trace"
export * from "./trace/traceplayer"
export * from "./command"
export * from "./packetfilter"
export * from "./tracerecorder"
export * from "./traceview"
export * from "./traceplayer"
export * from "./trace/tracerecorder"
export * from "./trace/traceview"
export * from "./flags"
export * from "./settingsclient"
export * from "./pack"
export * from "./packobject"
export * from "./light"
@ -44,9 +41,11 @@ export * from "./serviceprovider"
export * from "./controlserver"
export * from "./color"
export * from "./makecode"
export * from "./rolemanagerclient"
export * from "./qualityofservice"
export * from "./bridge"
export * from "./clients/modelrunnerclient"
export * from "./clients/settingsclient"
export * from "./clients/rolemanagerclient"
export * from "./transport/transport"
export * from "./transport/bluetooth"
export * from "./transport/usbio"

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

@ -1,6 +1,6 @@
import { JDEventSource } from "./eventsource"
import { jdpack } from "./pack"
import { JDService } from "./service"
import JDService from "./service"
function trgbToValues(trgb: number) {
return [
@ -11,7 +11,7 @@ function trgbToValues(trgb: number) {
]
}
export default class LEDController extends JDEventSource {
export class LEDController extends JDEventSource {
constructor(
public readonly service: JDService,
public readonly command: number
@ -31,3 +31,4 @@ export default class LEDController extends JDEventSource {
}
}
}
export default LEDController

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

@ -1,9 +1,9 @@
import { arrayConcatMany, fromHex } from "./utils"
import { JDBus } from "./bus"
import JDBus from "./bus"
import Packet from "./packet"
import TracePlayer from "./traceplayer"
import TracePlayer from "./trace/traceplayer"
import Frame from "./frame"
import Trace from "./trace"
import Trace from "./trace/trace"
export function parseTrace(contents: string): Trace {
const description: string[] = []

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

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { JDEventSource } from "./eventsource"
/**
@ -11,21 +12,25 @@ export abstract class JDNode extends JDEventSource {
/**
* Globally unique identifier in the tree
* @category JDOM
*/
abstract get id(): string
/**
* Gets a kind identifier useful for UI descriptions
* @category JDOM
*/
abstract get nodeKind(): string
/**
* Gets the local name
* @category JDOM
*/
abstract get name(): string
/**
* A human friendly name
* @category JDOM
*/
get friendlyName(): string {
return this.name
@ -33,20 +38,28 @@ export abstract class JDNode extends JDEventSource {
/**
* Gets the name including parents
* @category JDOM
*/
abstract get qualifiedName(): string
/**
* Gets the parent node in the Jacdac dom
* @category JDOM
*/
abstract get parent(): JDNode
/**
* Gets the children of the current node
* @category JDOM
*/
abstract get children(): JDNode[]
// eslint-disable-next-line @typescript-eslint/no-explicit-any
/**
* Emit event in current node and parent nodes
* @param event event to emit
* @param arg event arguments
* @category JDOM
*/
emitPropagated(event: string, arg?: any) {
let current = this as JDNode
while (current) {
@ -60,6 +73,8 @@ export abstract class JDNode extends JDEventSource {
}
}
export default JDNode
export function visitNodes(node: JDNode, vis: (node: JDNode) => void) {
const todo = [node]
while (todo.length) {

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

@ -35,9 +35,9 @@ import {
CMD_EVENT_MASK,
CMD_EVENT_COUNTER_POS,
} from "./constants"
import { JDDevice } from "./device"
import JDDevice from "./device"
import { NumberFormat, getNumber } from "./buffer"
import { JDBus } from "./bus"
import JDBus from "./bus"
import {
commandName,
DecodedPacket,
@ -58,7 +58,7 @@ const { warn } = console
export class Packet {
private _header: Uint8Array
private _data: Uint8Array
private _meta: any = undefined // accesory data used by clients
private _meta: Record<string, unknown> = undefined // accesory data used by clients
timestamp: number
device: JDDevice
private _decoded: DecodedPacket

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

@ -4,7 +4,7 @@ import {
SRV_CONTROL,
SRV_LOGGER,
} from "../../jacdac-spec/dist/specconstants"
import { JDBus } from "./bus"
import JDBus from "./bus"
import Packet from "./packet"
import { isInstanceOf, serviceSpecificationFromName } from "./spec"
import { SMap } from "./utils"
@ -22,7 +22,7 @@ export interface PacketFilterProps {
flags?: string[]
regGet?: boolean
regSet?: boolean
devices?: SMap<{ from?: boolean; to?: boolean }>
devices?: Record<string, { from?: boolean; to?: boolean }>
selfDevice?: boolean
serviceClasses?: number[]
pkts?: string[]
@ -67,7 +67,7 @@ export function parsePacketFilter(bus: JDBus, text: string): PacketFilter {
let log: boolean = undefined
let before: number = undefined
let after: number = undefined
const devices: SMap<{ from: boolean; to: boolean }> = {}
const devices: Record<string, { from: boolean; to: boolean }> = {}
let grouping = true
let pipes: boolean = undefined
let port: number = undefined

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

@ -1,4 +1,4 @@
import { JDDevice } from "./device"
import JDDevice from "./device"
import {
PIPE_PORT_SHIFT,
PIPE_COUNTER_MASK,
@ -10,7 +10,7 @@ import {
CLOSE,
} from "./constants"
import Packet from "./packet"
import { JDBus } from "./bus"
import JDBus from "./bus"
import { signal, fromHex, throwError, toHex } from "./utils"
import { JDClient } from "./client"
import { jdpack } from "./pack"

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

@ -2,7 +2,6 @@ import Packet from "./packet"
import { NumberFormat } from "./buffer"
import {
roundWithPrecision,
SMap,
idiv,
fromHex,
hash,
@ -485,7 +484,7 @@ export function decodePacketData(pkt: Packet): DecodedPacket {
return decodePacket(service, pkt)
}
function reverseLookup(map: SMap<number>, n: number) {
function reverseLookup(map: Record<string, number>, n: number) {
for (const k of Object.keys(map)) {
if (map[k] == n) return k
}

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

@ -11,7 +11,7 @@ import { OutPipe } from "./pipes"
import JDRegisterServer from "./registerserver"
import JDServiceServer from "./serviceserver"
export default class ProtocolTestServer extends JDServiceServer {
export class ProtocolTestServer extends JDServiceServer {
private rwBytes: JDRegisterServer<[Uint8Array]>
constructor() {
@ -105,3 +105,4 @@ export default class ProtocolTestServer extends JDServiceServer {
})
}
}
export default ProtocolTestServer

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

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { CHANGE } from "./constants"
import { JDEventSource } from "./eventsource"
import Packet from "./packet"
@ -25,6 +26,9 @@ export class QualityOfService extends JDEventSource {
return r
}
/**
* @internal
*/
processAnnouncement(pkt: Packet) {
// collect metrics
const received = this._receivedPackets
@ -38,7 +42,9 @@ export class QualityOfService extends JDEventSource {
this.emit(CHANGE)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
/**
* @internal
*/
processPacket(pkt: Packet) {
this._receivedPackets++
}

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

@ -11,14 +11,14 @@ import {
REGISTER_REFRESH_RETRY_0,
GET_ATTEMPT,
} from "./constants"
import { JDService } from "./service"
import JDService from "./service"
import { intOfBuffer, uintOfBuffer } from "./buffer"
import { bufferEq, toHex, fromUTF8, uint8ArrayToString } from "./utils"
import { DecodedPacket } from "./pretty"
import { isRegister, isReading } from "./spec"
import { JDField } from "./field"
import { JDServiceMemberNode } from "./servicemembernode"
import { JDNode } from "./node"
import JDField from "./field"
import JDServiceMemberNode from "./servicemembernode"
import JDNode from "./node"
import { jdpack, jdunpack, PackedValues } from "./pack"
import { PackedObject, unpackedToObject } from "./packobject"
@ -247,6 +247,8 @@ export class JDRegister extends JDServiceMemberNode {
}
}
export default JDRegister
export function stableSortRegisters(registers: JDRegister[]): JDRegister[] {
return registers?.sort((a, b) => a.compareTo(b))
}

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

@ -65,7 +65,11 @@ function defaultPayload<T extends PackedValues>(
return rs as T
}
export default class JDRegisterServer<
/**
* A register "server" instance, used to assembly service servers.
* @category Servers
*/
export class JDRegisterServer<
TValues extends PackedValues
> extends JDEventSource {
data: Uint8Array
@ -209,3 +213,4 @@ export default class JDRegisterServer<
return true
}
}
export default JDRegisterServer

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

@ -1,7 +1,7 @@
import { JDDevice } from "./device"
import JDDevice from "./device"
import Packet from "./packet"
import { serviceName } from "./pretty"
import { JDRegister } from "./register"
import JDRegister from "./register"
import {
PACKET_RECEIVE,
PACKET_SEND,
@ -12,7 +12,7 @@ import {
CHANGE,
ROLE_CHANGE,
} from "./constants"
import { JDNode } from "./node"
import JDNode from "./node"
import {
serviceSpecificationFromClassIdentifier,
isRegister,
@ -23,7 +23,7 @@ import {
isOptionalReadingRegisterCode,
isConstRegister,
} from "./spec"
import { JDEvent } from "./event"
import JDEvent from "./event"
import { strcmp } from "./utils"
import {
BaseEvent,
@ -418,6 +418,8 @@ export class JDService extends JDNode {
}
}
export default JDService
export function stableSortServices(services: JDService[]): JDService[] {
return services?.sort((a, b) => a.compareTo(b))
}

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

@ -1,6 +1,6 @@
import { JDService } from "./service"
import { JDDevice } from "./device"
import { JDBus } from "./bus"
import JDService from "./service"
import JDDevice from "./device"
import JDBus from "./bus"
import { JDClient } from "./client"
/**

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

@ -1,5 +1,5 @@
import { JDNode } from "./node"
import { JDService } from "./service"
import JDNode from "./node"
import JDService from "./service"
import { DecodedPacket } from "./pretty"
/**
@ -53,3 +53,5 @@ export abstract class JDServiceMemberNode extends JDNode {
abstract get decoded(): DecodedPacket
}
export default JDServiceMemberNode

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

@ -1,4 +1,4 @@
import { JDBus } from "./bus"
import JDBus from "./bus"
import JDServiceServer from "./serviceserver"
import Packet from "./packet"
import { shortDeviceId } from "./pretty"
@ -21,7 +21,11 @@ import {
} from "./constants"
import { anyRandomUint32 } from "./random"
export default class JDServiceProvider extends JDEventSource {
/**
* Implements a device with service servers.
* @category Servers
*/
export class JDServiceProvider extends JDEventSource {
private _bus: JDBus
private _services: JDServiceServer[]
public readonly deviceId: string
@ -261,3 +265,4 @@ export default class JDServiceProvider extends JDEventSource {
this.emit(RESET)
}
}
export default JDServiceProvider

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

@ -17,7 +17,7 @@ import Packet from "./packet"
import JDRegisterServer from "./registerserver"
import { isRegister, serviceSpecificationFromClassIdentifier } from "./spec"
import { PackedValues } from "./pack"
import { JDService } from "./service"
import JDService from "./service"
const CALIBRATION_DELAY = 5000
export interface ServerOptions {
@ -35,7 +35,11 @@ export interface ServerOptions {
}[]
}
export default class JDServiceServer extends JDEventSource {
/**
* Base class for service server implementations
* @category Servers
*/
export class JDServiceServer extends JDEventSource {
public serviceIndex = -1 // set by device
private _device: JDServiceProvider
public readonly specification: jdspec.ServiceSpec
@ -264,3 +268,4 @@ export default class JDServiceServer extends JDEventSource {
this.statusCode.setValues([SystemStatusCodes.Ready, 0])
}
}
export default JDServiceServer

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

@ -6,7 +6,7 @@
import { NumberFormat } from "./buffer"
import serviceSpecificationData from "../../jacdac-spec/dist/services.json"
import deviceRegistryData from "../../jacdac-spec/dist/devices.json"
import { fromHex, SMap, toHex } from "./utils"
import { fromHex, toHex } from "./utils"
import {
SystemEvent,
SystemReg,
@ -23,7 +23,7 @@ import {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let _serviceSpecifications: jdspec.ServiceSpec[] =
serviceSpecificationData as any
let _customServiceSpecifications: SMap<jdspec.ServiceSpec> = {}
let _customServiceSpecifications: Record<string, jdspec.ServiceSpec> = {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const _deviceRegistry: jdspec.DeviceSpec[] = deviceRegistryData as any
@ -48,8 +48,8 @@ export function clearCustomServiceSpecifications() {
_customServiceSpecifications = {}
}
export function serviceMap(): SMap<jdspec.ServiceSpec> {
const m: SMap<jdspec.ServiceSpec> = {}
export function serviceMap(): Record<string, jdspec.ServiceSpec> {
const m: Record<string, jdspec.ServiceSpec> = {}
_serviceSpecifications.forEach(spec => (m[spec.shortId] = spec))
return m
}

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

@ -1,6 +1,6 @@
import * as U from "./utils"
import Packet from "./packet"
import { JDDevice } from "./device"
import JDDevice from "./device"
import { PACKET_REPORT, CMD_GET_REG, JD_SERVICE_INDEX_CTRL } from "./constants"
import { ControlReg } from "../../jacdac-spec/dist/specconstants"

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

@ -1,50 +0,0 @@
import Packet from "./packet"
import { printPacket } from "./pretty"
import { toHex } from "./utils"
export default class Trace {
constructor(public packets: Packet[] = [], public description?: string) {}
get length() {
return this.packets.length
}
get duration() {
if (!this.packets.length) return 0
return (
this.packets[this.packets.length - 1].timestamp -
this.packets[0].timestamp
)
}
get startTimestamp() {
return this.packets[0]?.timestamp || 0
}
get endTimestamp() {
return this.packets[this.packets.length - 1]?.timestamp || 0
}
addPacket(pkt: Packet, maxLength = -1) {
this.packets.push(pkt)
if (maxLength > 0 && this.packets.length > maxLength * 1.1) {
// 10% overshoot of max
this.packets = this.packets.slice(-maxLength)
}
}
serializeToText() {
const start = this.packets[0]?.timestamp || 0
const text = this.packets.map(
pkt =>
`${pkt.timestamp - start}\t${toHex(
pkt.toBuffer()
)}\t${printPacket(pkt, {}).replace(/\r?\n/g, " ")}`
)
if (this.description) {
text.unshift(this.description)
text.unshift("")
}
return text.join("\n")
}
}

86
src/jdom/trace/trace.ts Normal file
Просмотреть файл

@ -0,0 +1,86 @@
import Packet from "../packet"
import { printPacket } from "../pretty"
import { toHex } from "../utils"
const TRACE_OVERSHOOT = 1.1
/**
* A sequence of packets.
* @category Trace
*/
export class Trace {
/**
* Constructs a new empty trace or from an existing list of packets
* @param packets list of packets
* @param description description of the trace
*/
constructor(public packets: Packet[] = [], public description?: string) {}
/**
* Number of packets in trace
*/
get length() {
return this.packets.length
}
/**
* Duration in milliseconds between the first and last packet.
*/
get duration() {
if (!this.packets.length) return 0
return (
this.packets[this.packets.length - 1].timestamp -
this.packets[0].timestamp
)
}
/**
* Timestamp of the first packet, defaults to 0 if trace is empty.
*/
get startTimestamp() {
return this.packets[0]?.timestamp || 0
}
/**
* Timestamp of the last packet, defaults to 0 if trace is empty.
*/
get endTimestamp() {
return this.packets[this.packets.length - 1]?.timestamp || 0
}
/**
* Appends a packet to the trace
* @param packet packet to add
* @param maxLength If positive, prunes older packets when the length reaches maxLength
*/
addPacket(packet: Packet, maxLength = -1) {
this.packets.push(packet)
if (
maxLength > 0 &&
this.packets.length > maxLength * TRACE_OVERSHOOT
) {
// 10% overshoot of max
this.packets = this.packets.slice(-maxLength)
}
}
/**
* Gets a text-rendered view of the trace
* @returns text where each line is a packet
*/
serializeToText() {
const start = this.packets[0]?.timestamp || 0
const text = this.packets.map(
pkt =>
`${pkt.timestamp - start}\t${toHex(
pkt.toBuffer()
)}\t${printPacket(pkt, {}).replace(/\r?\n/g, " ")}`
)
if (this.description) {
text.unshift(this.description)
text.unshift("")
}
return text.join("\n")
}
}
export default Trace

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

@ -1,9 +1,13 @@
import { JDBus } from "./bus"
import { JDClient } from "./client"
import { CHANGE, PROGRESS } from "./constants"
import JDBus from "../bus"
import JDClient from "../client"
import { CHANGE, PROGRESS } from "../constants"
import Trace from "./trace"
export default class TracePlayer extends JDClient {
/**
* A player for packet traces.
* @category Trace
*/
export class TracePlayer extends JDClient {
private _trace: Trace
private _busStartTimestamp = 0
private _index = 0
@ -101,3 +105,4 @@ export default class TracePlayer extends JDClient {
}
}
}
export default TracePlayer

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

@ -1,11 +1,16 @@
import { JDBus } from "./bus"
import { JDClient } from "./client"
import { CHANGE, PACKET_PROCESS, PACKET_SEND, START, STOP } from "./constants"
import Packet from "./packet"
import JDBus from "../bus"
import JDClient from "../client"
import { CHANGE, PACKET_PROCESS, PACKET_SEND, START, STOP } from "../constants"
import Packet from "../packet"
import Trace from "./trace"
const RECORDING_TRACE_MAX_ITEMS = 100000
export default class TraceRecorder extends JDClient {
/**
* A recorder of packets to create traces.
* @category Trace
*/
export class TraceRecorder extends JDClient {
public maxRecordingLength = RECORDING_TRACE_MAX_ITEMS
private _trace: Trace
private _subscription: () => void
@ -57,3 +62,4 @@ export default class TraceRecorder extends JDClient {
this.emit(PACKET_PROCESS, pkt)
}
}
export default TraceRecorder

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

@ -1,5 +1,5 @@
import { JDBus } from "./bus"
import { JDClient } from "./client"
import JDBus from "../bus"
import { JDClient } from "../client"
import {
CHANGE,
DEVICE_ANNOUNCE,
@ -9,11 +9,11 @@ import {
PACKET_PROCESS,
PACKET_SEND,
TRACE_FILTER_HORIZON,
} from "./constants"
import Packet from "./packet"
import { PacketFilter, parsePacketFilter } from "./packetfilter"
} from "../constants"
import Packet from "../packet"
import { PacketFilter, parsePacketFilter } from "../packetfilter"
import Trace from "./trace"
import { throttle } from "./utils"
import { throttle } from "../utils"
const FILTERED_TRACE_MAX_ITEMS = 100
const DUPLICATE_PACKET_MERGE_HORIZON_MAX_DISTANCE = 10
@ -25,7 +25,11 @@ export interface TracePacketProps {
count?: number
}
export default class TraceView extends JDClient {
/**
* A filtered view over a packet trace
* @category Trace
*/
export class TraceView extends JDClient {
private id = "v" + Math.random()
private _maxFilteredLength = FILTERED_TRACE_MAX_ITEMS
@ -276,3 +280,4 @@ export default class TraceView extends JDClient {
}
}
}
export default TraceView

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

@ -7,7 +7,7 @@ import {
BLUETOOTH_JACDAC_SERVICE,
BLUETOOTH_TRANSPORT,
} from "../constants"
import { JDTransport } from "./transport"
import JDTransport from "./transport"
const JD_BLE_FIRST_CHUNK_FLAG = 0x80

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

@ -1,4 +1,4 @@
import { Observable, Observer } from "./observable"
import { Observable, Observer } from "../observable"
export class EventTargetObservable<TEvent> implements Observable<TEvent> {
constructor(
@ -16,3 +16,4 @@ export class EventTargetObservable<TEvent> implements Observable<TEvent> {
}
}
}
export default EventTargetObservable

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

@ -2,7 +2,6 @@ import Proto from "./proto"
import {
throwError,
assert,
SMap,
PromiseBuffer,
PromiseQueue,
memcpy,
@ -105,6 +104,7 @@ export const HF2_EV_JDS_PACKET = 0x800020
export interface HF2_IO {
onData: (v: Uint8Array) => void
// eslint-disable-next-line @typescript-eslint/no-explicit-any
log(msg: string, v?: any): void
disconnectAsync(): Promise<void>
error(msg: string, code?: string): void
@ -112,7 +112,7 @@ export interface HF2_IO {
}
export class HF2Proto implements Proto {
eventHandlers: SMap<(buf: Uint8Array) => void> = {}
eventHandlers: Record<string, (buf: Uint8Array) => void> = {}
msgs = new PromiseBuffer<Uint8Array>()
cmdSeq = (Math.random() * 0xffff) | 0
private lock = new PromiseQueue()

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

@ -1,4 +1,4 @@
import { EventTargetObservable } from "../eventtargetobservable"
import EventTargetObservable from "./eventtargetobservable"
import { HF2_DEVICE_MAJOR } from "./hf2"
import { MICROBIT_V2_PRODUCT_ID, MICROBIT_V2_VENDOR_ID } from "./microbit"
import { USBOptions } from "./usbio"

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

@ -1,4 +1,4 @@
import { JDBus } from "../bus"
import JDBus from "../bus"
import {
CHANGE,
CONNECT,
@ -322,3 +322,5 @@ export abstract class JDTransport extends JDEventSource {
this._cleanups = []
}
}
export default JDTransport

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

@ -1,9 +1,9 @@
import Packet from "../packet"
import { EventTargetObservable } from "../eventtargetobservable"
import EventTargetObservable from "./eventtargetobservable"
import Flags from "../flags"
import { USB_TRANSPORT } from "../constants"
import { JDTransport } from "./transport"
import { JDBus } from "../bus"
import JDTransport from "./transport"
import JDBus from "../bus"
import Proto from "./proto"
import USBIO, { USBOptions } from "./usbio"

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

@ -1,8 +1,8 @@
import Packet from "../packet"
import Flags from "../flags"
import { SERIAL_TRANSPORT, USB_TRANSPORT } from "../constants"
import { JDTransport } from "./transport"
import { JDBus } from "../bus"
import JDTransport from "./transport"
import JDBus from "../bus"
import Proto from "./proto"
import WebSerialIO from "./webserialio"
import { createUSBTransport } from "./usb"

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

@ -1,5 +1,5 @@
import { USB_TRANSPORT } from "../constants"
import { EventTargetObservable } from "../eventtargetobservable"
import EventTargetObservable from "./eventtargetobservable"
import Flags from "../flags"
import Packet from "../packet"
import { JDTransport, JDTransportOptions } from "./transport"

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

@ -1,4 +1,4 @@
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import { JDClient } from "../jdom/client"
import { JoystickVariant } from "../jdom/constants"
import JDServiceProvider from "../jdom/serviceprovider"

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

@ -7,7 +7,7 @@ import {
SRV_REAL_TIME_CLOCK,
} from "../jdom/constants"
import JDRegisterServer from "../jdom/registerserver"
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import Packet from "../jdom/packet"
export type RealTimeClockReadingType = [

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

@ -7,9 +7,9 @@ import {
ROLE_UNBOUND,
UNBOUND,
} from "../jdom/constants"
import { JDBus } from "../jdom/bus"
import { JDDevice } from "../jdom/device"
import { JDService } from "../jdom/service"
import JDBus from "../jdom/bus"
import JDDevice from "../jdom/device"
import JDService from "../jdom/service"
import { serviceSpecificationFromClassIdentifier } from "../jdom/spec"
import { JDClient } from "../jdom/client"

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

@ -1,4 +1,4 @@
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import {
CharacterScreenTextDirection,
CharacterScreenVariant,

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

@ -3,10 +3,10 @@ import { jdpack } from "../jdom/pack"
import Packet from "../jdom/packet"
import { OutPipe } from "../jdom/pipes"
import JDServiceServer from "../jdom/serviceserver"
import { fromHex, SMap, toHex } from "../jdom/utils"
import { fromHex, toHex } from "../jdom/utils"
export default class SettingsServer extends JDServiceServer {
private settings: SMap<string>
private settings: Record<string, string>
constructor(readonly storageKey?: string) {
super(SRV_SETTINGS)
@ -82,7 +82,7 @@ export default class SettingsServer extends JDServiceServer {
this.save()
}
private read(): SMap<string> {
private read(): Record<string, string> {
if (!this.storageKey) return {}
try {

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

@ -3,7 +3,7 @@ import {
SpeechSynthesisReg,
SRV_SPEECH_SYNTHESIS,
} from "../jdom/constants"
import { Packet } from "../jdom/packet"
import Packet from "../jdom/packet"
import JDRegisterServer from "../jdom/registerserver"
import JDServiceServer from "../jdom/serviceserver"

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

@ -6,7 +6,7 @@ import { exprVisitor } from "../../jacdac-spec/spectool/jdutils"
import { CHANGE } from "../jdom/constants"
import { JDEventSource } from "../jdom/eventsource"
import { JDService } from "../jdom/service"
import JDService from "../jdom/service"
import { JDServiceClient } from "../jdom/serviceclient"
import { roundWithPrecision } from "../jdom/utils"
import { unparse, VMExprEvaluator, CallEvaluator, StartMap } from "../vm/expr"

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

@ -1,5 +1,5 @@
// Contains foundational abstractions for the testing system
import { JDBus } from "../jdom/bus"
import JDBus from "../jdom/bus"
import { assert } from "../jdom/utils"
// A base class that abstracts away user-facing logging events, eg to pipe it to a web page

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

@ -1,8 +1,8 @@
import { isEvent, isRegister, isCommand, isIntensity } from "../jdom/spec"
import { JDServiceClient } from "../jdom/serviceclient"
import { JDService } from "../jdom/service"
import { JDRegister } from "../jdom/register"
import { JDEvent } from "../jdom/event"
import JDService from "../jdom/service"
import JDRegister from "../jdom/register"
import JDEvent from "../jdom/event"
import { CHANGE, EVENT, REPORT_UPDATE, SystemReg } from "../jdom/constants"
import { SMap } from "../jdom/utils"
import { jdpack, PackedValues } from "../jdom/pack"

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

@ -1,5 +1,5 @@
import { assert, SMap } from "../jdom/utils"
import { JDService } from "../jdom/service"
import JDService from "../jdom/service"
import { JDEventSource } from "../jdom/eventsource"
import { PackedValues } from "../jdom/pack"
import { serviceSpecificationFromClassIdentifier } from "../jdom/spec"

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

@ -32,7 +32,7 @@ import { Mutex, atomic } from "./utils"
import { assert, SMap } from "../jdom/utils"
import { JDClient } from "../jdom/client"
import JDServiceProvider from "../jdom/serviceprovider"
import { JDDevice } from "../jdom/device"
import JDDevice from "../jdom/device"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type VMTraceContext = any

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

@ -1,4 +1,3 @@
import JDServiceServer from "../jdom/serviceserver"
import {
isHighLevelRegister,
isHighLevelEvent,
@ -8,7 +7,7 @@ import { SMap } from "../jdom/utils"
import { jdpack, PackedValues } from "../jdom/pack"
import { atomic } from "./utils"
import { CHANGE } from "../jdom/constants"
import { Packet } from "../jdom/packet"
import Packet from "../jdom/packet"
import { DecodedPacket } from "../jdom/pretty"
import JDRegisterServer from "../jdom/registerserver"
import { ExternalRequest } from "./environment"

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

@ -1,5 +1,5 @@
import { suite, test, afterEach } from "mocha"
import { JDBus } from "../../src/jdom/bus"
import JDBus from "../../src/jdom/bus"
import { SELF_ANNOUNCE } from "../../src/jdom/constants"
import { mkBus } from "../testutils"

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

@ -1,7 +1,7 @@
import { JDBus } from "../../src/jdom/bus"
import JDBus from "../../src/jdom/bus"
import { DEVICE_ANNOUNCE } from "../../src/jdom/constants"
import { JDDevice } from "../../src/jdom/device"
import { JDService } from "../../src/jdom/service"
import JDDevice from "../../src/jdom/device"
import JDService from "../../src/jdom/service"
import JDServiceProvider from "../../src/jdom/serviceprovider"
import JDServiceServer from "../../src/jdom/serviceserver"
import { assert } from "../../src/jdom/utils"

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

@ -1,6 +1,6 @@
import { loadServiceSpecifications } from "../src/jdom/spec"
import { readFileSync } from "fs"
import { JDBus } from "../src/jdom/bus"
import JDBus from "../src/jdom/bus"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let specs: any

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

@ -2,7 +2,7 @@
import { ROLE_BOUND } from "../../src/jdom/constants"
import { EventHandler } from "../../src/jdom/jacdac-jdom"
import { JDService } from "../../src/jdom/service"
import JDService from "../../src/jdom/service"
import { assert } from "../../src/jdom/utils"
import RoleManager, { RoleBinding } from "../../src/servers/rolemanager"
import { TestDriverInterface } from "../../src/tstester/base"

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

@ -15,5 +15,7 @@
"excludeInternal": true,
"excludeExternals": true,
"name": "Jacdac TypeScript",
"categoryOrder": ["JDOM", "Clients", "*"]
"categoryOrder": ["JDOM", "Clients", "Servers", "Trace", "*"],
"readme": "none",
"includeVersion": true
}

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

@ -1433,6 +1433,21 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
concurrently@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.2.1.tgz#d880fc1d77559084732fa514092a3d5109a0d5bf"
integrity sha512-emgwhH+ezkuYKSHZQ+AkgEpoUZZlbpPVYCVv7YZx0r+T7fny1H03r2nYRebpi2DudHR4n1Rgbo2YTxKOxVJ4+g==
dependencies:
chalk "^4.1.0"
date-fns "^2.16.1"
lodash "^4.17.21"
read-pkg "^5.2.0"
rxjs "^6.6.3"
spawn-command "^0.0.2-1"
supports-color "^8.1.0"
tree-kill "^1.2.2"
yargs "^16.2.0"
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
@ -1595,6 +1610,11 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
date-fns@^2.16.1:
version "2.23.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9"
integrity sha512-5ycpauovVyAk0kXNZz6ZoB9AYMZB4DObse7P3BPWmyEjXNORTI8EJ6X0uaSAq4sCHzM1uajzrkr6HnsLQpxGXA==
dateformat@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
@ -5826,6 +5846,13 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rxjs@^6.6.3:
version "6.6.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
dependencies:
tslib "^1.9.0"
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@ -6117,6 +6144,11 @@ sourcemap-codec@^1.4.4:
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
spawn-command@^0.0.2-1:
version "0.0.2-1"
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
spawn-error-forwarder@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029"
@ -6403,7 +6435,7 @@ strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
supports-color@8.1.1:
supports-color@8.1.1, supports-color@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
@ -6582,6 +6614,11 @@ traverse@~0.6.6:
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
trim-newlines@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30"
@ -6615,7 +6652,7 @@ tslib@2.1.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tslib@^1.8.1:
tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==