diff --git a/app/package.json b/app/package.json index 142e4d3e..6e3ed57d 100644 --- a/app/package.json +++ b/app/package.json @@ -47,6 +47,7 @@ "react-split-pane": "^0.1.85", "react-transition-group": "^4", "react-vis": "^1.11.6", + "react-window": "^1.8.10", "redux": "^4.0.1", "redux-batched-actions": "0.5", "redux-thunk": "^2.3.0", @@ -65,6 +66,8 @@ "@types/react-dom": "^16.0.11", "@types/react-redux": "^7.0.9", "@types/react-resize-detector": "^4.0.1", + "@types/react-virtualized": "^9.21.30", + "@types/react-window": "^1.8.8", "@types/sha1": "^1.1.1", "@types/socket.io-client": "^1.4.32", "@types/uuid": "^7.0.2", @@ -82,12 +85,12 @@ "style-loader": "^1", "ts-loader": "^9.2.6", "typescript": "^4.5.5", - "webpack": "^5.69.1", + "webpack": "^5.91.0", "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.7.4" + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" }, "peerDependencies": { "electron": "^29" } -} \ No newline at end of file +} diff --git a/app/src/actions/Publish.ts b/app/src/actions/Publish.ts index 91130b41..a752251e 100644 --- a/app/src/actions/Publish.ts +++ b/app/src/actions/Publish.ts @@ -2,7 +2,7 @@ import { Action, ActionTypes } from '../reducers/Publish' import { AppState } from '../reducers' import { Base64Message } from '../../../backend/src/Model/Base64Message' import { Dispatch } from 'redux' -import { makePublishEvent, rendererEvents } from '../../../events' +import { MqttMessage, makePublishEvent, rendererEvents } from '../../../events' export const setTopic = (topic?: string): Action => { return { @@ -41,7 +41,7 @@ export const publish = (connectionId: string) => (dispatch: Dispatch, ge } const publishEvent = makePublishEvent(connectionId) - const mqttMessage = { + const mqttMessage: Partial = { topic, payload: state.publish.payload ? Base64Message.fromString(state.publish.payload) : null, retain: state.publish.retain, diff --git a/app/src/actions/Settings.ts b/app/src/actions/Settings.ts index 257e5e5d..80282e6d 100644 --- a/app/src/actions/Settings.ts +++ b/app/src/actions/Settings.ts @@ -1,5 +1,5 @@ import * as q from '../../../backend/src/Model' -import { ActionTypes, SettingsStateModel, TopicOrder } from '../reducers/Settings' +import { ActionTypes, SettingsStateModel, TopicOrder, ValueRendererDisplayMode } from '../reducers/Settings' import { AppState } from '../reducers' import { autoExpandLimitSet } from '../components/SettingsDrawer/Settings' import { Base64Message } from '../../../backend/src/Model/Base64Message' @@ -68,13 +68,14 @@ export const selectTopicWithMouseOver = (doSelect: boolean) => (dispatch: Dispat dispatch(storeSettings()) } -export const setValueDisplayMode = (valueRendererDisplayMode: 'diff' | 'raw') => (dispatch: Dispatch) => { - dispatch({ - valueRendererDisplayMode, - type: ActionTypes.SETTINGS_SET_VALUE_RENDERER_DISPLAY_MODE, - }) - dispatch(storeSettings()) -} +export const setValueDisplayMode = + (valueRendererDisplayMode: ValueRendererDisplayMode) => (dispatch: Dispatch) => { + dispatch({ + valueRendererDisplayMode, + type: ActionTypes.SETTINGS_SET_VALUE_RENDERER_DISPLAY_MODE, + }) + dispatch(storeSettings()) + } export const toggleHighlightTopicUpdates = () => (dispatch: Dispatch) => { dispatch({ @@ -117,7 +118,7 @@ export const filterTopics = (filterStr: string) => (dispatch: Dispatch, get const messageMatches = node.message && node.message.payload && - Base64Message.toUnicodeString(node.message.payload).toLowerCase().indexOf(filterStr) !== -1 + node.message.payload.toUnicodeString().toLowerCase().indexOf(filterStr) !== -1 return Boolean(messageMatches) } diff --git a/app/src/actions/Tree.ts b/app/src/actions/Tree.ts index 0dd1896b..25ddcc04 100644 --- a/app/src/actions/Tree.ts +++ b/app/src/actions/Tree.ts @@ -33,13 +33,8 @@ const debouncedSelectTopic = debounce( setTopicDispatch = setTopic(topic.path()) } - if (previouslySelectedTopic && previouslySelectedTopic.viewModel) { - previouslySelectedTopic.viewModel.setSelected(false) - } - - if (topic.viewModel) { - topic.viewModel.setSelected(true) - } + previouslySelectedTopic?.viewModel?.setSelected(false) + topic.viewModel?.setSelected(true) const selectTreeTopicDispatch = { selectedTopic: topic, diff --git a/app/src/components/ChartPanel/TopicChart.tsx b/app/src/components/ChartPanel/TopicChart.tsx index 35008600..33a943ae 100644 --- a/app/src/components/ChartPanel/TopicChart.tsx +++ b/app/src/components/ChartPanel/TopicChart.tsx @@ -114,6 +114,7 @@ function TopicChart(props: Props) { { + const connect = useCallback(() => { + const mqttOptions = toMqttConnection(props.connection) + if (mqttOptions) { + props.actions.connection.connect(mqttOptions, props.connection.id) + } + }, [props.connection, props]) + const connection = props.connection.host && toMqttConnection(props.connection) return ( props.actions.selectConnection(props.connection.id)} + onClick={() => props.actions.connectionManager.selectConnection(props.connection.id)} + onDoubleClick={() => { + props.actions.connectionManager.selectConnection(props.connection.id) + connect() + }} > {props.connection.name || 'mqtt broker'} {connection && connection.url} @@ -30,10 +44,12 @@ const ConnectionItem = (props: Props) => { export const mapDispatchToProps = (dispatch: any) => { return { - actions: bindActionCreators(connectionManagerActions, dispatch), + actions: { + connection: bindActionCreators(connectionActions, dispatch), + connectionManager: bindActionCreators(connectionManagerActions, dispatch), + }, } } - export const connectionItemStyle = (theme: Theme) => ({ name: { width: '100%', diff --git a/app/src/components/ConnectionSetup/ProfileList/index.tsx b/app/src/components/ConnectionSetup/ProfileList/index.tsx index eb76fc1a..8efa4619 100644 --- a/app/src/components/ConnectionSetup/ProfileList/index.tsx +++ b/app/src/components/ConnectionSetup/ProfileList/index.tsx @@ -7,7 +7,7 @@ import { connect } from 'react-redux' import { connectionManagerActions } from '../../../actions' import { ConnectionOptions } from '../../../model/ConnectionOptions' import { KeyCodes } from '../../../utils/KeyCodes' -import { List, ListSubheader } from '@material-ui/core' +import { List } from '@material-ui/core' import { Theme, withStyles } from '@material-ui/core/styles' import { useGlobalKeyEventHandler } from '../../../effects/useGlobalKeyEventHandler' diff --git a/app/src/components/SettingsDrawer/BrokerStatistics.tsx b/app/src/components/SettingsDrawer/BrokerStatistics.tsx index c5c210db..4006c90b 100644 --- a/app/src/components/SettingsDrawer/BrokerStatistics.tsx +++ b/app/src/components/SettingsDrawer/BrokerStatistics.tsx @@ -123,7 +123,7 @@ function renderStat(tree: q.Tree, stat: Stats) { return null } - const str = node.message.payload ? Base64Message.toUnicodeString(node.message.payload) : '' + const str = node.message.payload ? node.message.payload.toUnicodeString() : '' let value = node.message && node.message.payload ? parseFloat(str) : NaN value = !isNaN(value) ? abbreviate(value) : str diff --git a/app/src/components/Sidebar/CodeDiff/ChartPreview.tsx b/app/src/components/Sidebar/CodeDiff/ChartPreview.tsx index 4d430c41..e41cf283 100644 --- a/app/src/components/Sidebar/CodeDiff/ChartPreview.tsx +++ b/app/src/components/Sidebar/CodeDiff/ChartPreview.tsx @@ -52,16 +52,16 @@ function ChartPreview(props: Props) { /> ) : ( - - - - ) + + + + ) return ( @@ -69,7 +69,7 @@ function ChartPreview(props: Props) { - {open ? : } + {open ? : } diff --git a/app/src/components/Sidebar/Sidebar.tsx b/app/src/components/Sidebar/Sidebar.tsx index 4e257cf9..a24a9817 100644 --- a/app/src/components/Sidebar/Sidebar.tsx +++ b/app/src/components/Sidebar/Sidebar.tsx @@ -1,10 +1,9 @@ import * as q from '../../../../backend/src/Model' import React, { useState, useEffect, useCallback } from 'react' -import ExpandMore from '@material-ui/icons/ExpandMore' import NodeStats from './NodeStats' import ValuePanel from './ValueRenderer/ValuePanel' import { AppState } from '../../reducers' -import { Badge, ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, Typography } from '@material-ui/core' +import { ExpansionPanelDetails } from '@material-ui/core' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import { settingsActions, sidebarActions } from '../../actions' @@ -28,7 +27,7 @@ interface Props { } function useUpdateNodeWhenNodeReceivesUpdates(node?: q.TreeNode) { - const [lastUpdate, setLastUpdate] = useState(0) + const [, setLastUpdate] = useState(0) const updateNode = useCallback( throttle(() => { setLastUpdate(node ? node.lastUpdate : 0) @@ -52,7 +51,6 @@ function Sidebar(props: Props) { const { classes, tree, nodePath } = props const node = usePollingToFetchTreeNode(tree, nodePath || '') useUpdateNodeWhenNodeReceivesUpdates(node) - // console.log(node && node.path(), tree, nodePath) return ( ) - }, [treeNode.lastUpdate, treeNode, name, isCollapsed, selected, theme, mouseOver, settings]) + }, [treeNode.lastUpdate, treeNode, name, isCollapsed, selected, theme, mouseOver, settings, doNotRenderSubnodes]) } export default withStyles(styles, { withTheme: true })(React.memo(TreeNodeComponent)) diff --git a/app/src/components/Tree/index.tsx b/app/src/components/Tree/index.tsx index b4f486ab..9ae5a4e3 100644 --- a/app/src/components/Tree/index.tsx +++ b/app/src/components/Tree/index.tsx @@ -1,6 +1,6 @@ import * as q from '../../../../backend/src/Model' -import React from 'react' -import TreeNode from './TreeNode' +import React, { useCallback, useMemo, useRef } from 'react' +import { Infinitree } from './Infinitree' import { AppState } from '../../reducers' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' @@ -8,6 +8,8 @@ import { KeyCodes } from '../../utils/KeyCodes' import { SettingsState } from '../../reducers/Settings' import { TopicViewModel } from '../../model/TopicViewModel' import { treeActions } from '../../actions' +import { FixedSizeList as List } from 'react-window' +import { useSubscription } from '../hooks/useSubscription' const MovingAverage = require('moving-average') const averagingTimeInterval = 10 * 1000 @@ -24,84 +26,64 @@ interface Props { settings: SettingsState } -interface State { - lastUpdate: number -} - function useArrowKeyEventHandler(actions: typeof treeActions) { - return (event: React.KeyboardEvent) => { - switch (event.keyCode) { - case KeyCodes.arrow_down: - actions.moveSelectionUpOrDownwards('next') - event.preventDefault() - break - case KeyCodes.arrow_up: - actions.moveSelectionUpOrDownwards('previous') - event.preventDefault() - break - case KeyCodes.arrow_left: - actions.moveOutward() - event.preventDefault() - break - case KeyCodes.arrow_right: - actions.moveInward() - event.preventDefault() - break - } - } + return useCallback( + (event: React.KeyboardEvent) => { + switch (event.keyCode) { + case KeyCodes.arrow_down: + actions.moveSelectionUpOrDownwards('next') + event.preventDefault() + break + case KeyCodes.arrow_up: + actions.moveSelectionUpOrDownwards('previous') + event.preventDefault() + break + case KeyCodes.arrow_left: + actions.moveOutward() + event.preventDefault() + break + case KeyCodes.arrow_right: + actions.moveInward() + event.preventDefault() + break + } + }, + [actions] + ) } -class TreeComponent extends React.PureComponent { - private updateTimer?: any - private perf: number = 0 - private renderTime = 0 - - constructor(props: any) { - super(props) - this.state = { lastUpdate: 0 } - } - - private keyEventHandler = useArrowKeyEventHandler(this.props.actions) - private performanceCallback = (ms: number) => { +const TreeComponent: React.FC = props => { + const keyEventHandler = useArrowKeyEventHandler(props.actions) + const performanceCallback = useCallback((ms: number) => { average.push(Date.now(), ms) - } + }, []) - public componentWillReceiveProps(nextProps: Props) { - if (this.props.tree !== nextProps.tree) { - if (this.props.tree) { - this.props.tree.didUpdate.unsubscribe(this.throttledTreeUpdate) - } - if (nextProps.tree) { - nextProps.tree.didUpdate.subscribe(this.throttledTreeUpdate) - } - this.setState(this.state) - } - } - - public componentWillUnmount() { - this.props.tree && this.props.tree.didUpdate.unsubscribe(this.throttledTreeUpdate) - } + const updateTimer = useRef() + const perf = useRef(performance.now()) + const renderTime = useRef(0) + const listRef = useRef(null) + const [lastUpdate, triggerUpdate] = React.useState(0) - public throttledTreeUpdate = () => { - if (this.updateTimer) { + const throttledTreeUpdate = useCallback(() => { + if (updateTimer.current) { return } const expectedRenderTime = average.forecast() - const updateInterval = Math.max(expectedRenderTime * 7, 300) - const timeUntilNextUpdate = updateInterval - (performance.now() - this.renderTime) + const updateInterval = Math.max(expectedRenderTime * 7, 500) + const timeUntilNextUpdate = updateInterval - (performance.now() - renderTime.current) - this.updateTimer = setTimeout( + updateTimer.current = setTimeout( () => { window.requestIdleCallback( () => { - this.updateTimer && clearTimeout(this.updateTimer) - this.updateTimer = undefined - this.renderTime = performance.now() + updateTimer.current && clearTimeout(updateTimer.current) + updateTimer.current = undefined + renderTime.current = performance.now() window.requestIdleCallback( () => { - this.setState({ lastUpdate: this.renderTime }) + triggerUpdate(renderTime.current) }, { timeout: 100 } ) @@ -111,49 +93,52 @@ class TreeComponent extends React.PureComponent { }, Math.max(0, timeUntilNextUpdate) ) - } + }, []) - public componentWillUpdate() { - this.perf = performance.now() - } + perf.current = performance.now() + window.requestIdleCallback(() => { + performanceCallback(performance.now() - perf.current) + }) + const fixedOnTreeNodeRef = useRef | null>(null) - public componentDidUpdate() { - this.performanceCallback(performance.now() - this.perf) - } + useSubscription(props.tree?.didUpdate, throttledTreeUpdate) - public render() { - const { tree } = this.props - if (!tree) { - return null - } - - const style: React.CSSProperties = { + const style: React.CSSProperties = useMemo( + () => ({ lineHeight: '1.1', cursor: 'default', - overflowY: 'scroll', - overflowX: 'hidden', + // overflowY: 'scroll', + // overflowX: 'hidden', height: '100%', width: '100%', outline: '24px black !important', paddingBottom: '16px', // avoid conflict with chart panel Resizer - } + }), + [] + ) - return ( -
- -
- ) + const { tree } = props + if (!tree) { + return null } + + const rendered = ( +
+ +
+ ) + + return rendered } const mapStateToProps = (state: AppState) => { diff --git a/app/src/components/UpdateNotifier.tsx b/app/src/components/UpdateNotifier.tsx index e68719df..c7b41724 100644 --- a/app/src/components/UpdateNotifier.tsx +++ b/app/src/components/UpdateNotifier.tsx @@ -1,7 +1,7 @@ -import * as compareVersions from 'compare-versions' -import * as electron from 'electron' -import * as os from 'os' -import * as React from 'react' +import compareVersions from 'compare-versions' +import electron from 'electron' +import os from 'os' +import React from 'react' import axios from 'axios' import Close from '@material-ui/icons/Close' import CloudDownload from '@material-ui/icons/CloudDownload' diff --git a/app/src/components/helper/Copy.tsx b/app/src/components/helper/Copy.tsx index 8542c576..a958cad0 100644 --- a/app/src/components/helper/Copy.tsx +++ b/app/src/components/helper/Copy.tsx @@ -9,7 +9,8 @@ import { globalActions } from '../../actions' const copy = require('copy-text-to-clipboard') interface Props { - value: string + value?: string + getValue?: () => string | undefined actions: { global: typeof globalActions } @@ -28,7 +29,7 @@ class Copy extends React.PureComponent { private handleClick = (event: React.MouseEvent) => { event.stopPropagation() - copy(this.props.value) + copy(this.props.value ?? this.props.getValue?.()) this.props.actions.global.showNotification('Copied to clipboard') this.setState({ didCopy: true }) setTimeout(() => { diff --git a/app/src/components/helper/DateFormatter.tsx b/app/src/components/helper/DateFormatter.tsx index 9741f5e7..523ebbaf 100644 --- a/app/src/components/helper/DateFormatter.tsx +++ b/app/src/components/helper/DateFormatter.tsx @@ -1,5 +1,5 @@ -import * as moment from 'moment' -import * as React from 'react' +import moment from 'moment' +import React from 'react' import { AppState } from '../../reducers' import { connect } from 'react-redux' @@ -12,6 +12,7 @@ interface Props { } const unitMapping = { + ms: 'milliseconds', s: 'seconds', m: 'minutes', h: 'hours', @@ -21,7 +22,7 @@ class DateFormatter extends React.PureComponent { private intervalSince(intervalSince: Date) { const interval = intervalSince.getTime() - this.props.date.getTime() const unit = this.unitForInterval(interval) - return `${Math.round(moment.duration(interval).as(unit) * 100) / 100} ${unitMapping[unit]}` + return `${moment.duration(interval).as(unit).toFixed(3)} ${unitMapping[unit]}` } private legacyDate() { @@ -31,10 +32,11 @@ class DateFormatter extends React.PureComponent { private localizedDate(locale: string) { return moment(this.props.date) .locale(locale) - .format(this.props.timeFirst ? 'LTS L' : 'L LTS') + .format(this.props.timeFirst ? 'LTS.SSS L' : 'L LTS.SSS') } private unitForInterval(milliseconds: number) { + const oneSecond = 1000 * 1 const oneMinute = 1000 * 60 const oneHour = oneMinute * 60 @@ -46,7 +48,11 @@ class DateFormatter extends React.PureComponent { return 'm' } - return 's' + if (milliseconds > oneSecond * 0.5) { + return 's' + } + + return 'ms' } public render() { diff --git a/app/src/components/hooks/useDecoder.ts b/app/src/components/hooks/useDecoder.ts new file mode 100644 index 00000000..7c4668ca --- /dev/null +++ b/app/src/components/hooks/useDecoder.ts @@ -0,0 +1,31 @@ +import * as q from '../../../../backend/src/Model' +import { useCallback, useState } from 'react' +import { TopicViewModel } from '../../model/TopicViewModel' +import { useSubscription } from './useSubscription' +import { useViewModel } from '../Tree/TreeNode/effects/useViewModel' +import { DecoderEnvelope } from '../../decoders/DecoderEnvelope' +import { Decoder } from '../../../../backend/src/Model/Decoder' + +export type DecoderFunction = (message: q.Message) => DecoderEnvelope | undefined + +/** + * Provides the latest decoder for a topic + * + * @param treeNode + * @returns + */ +export function useDecoder(treeNode: q.TreeNode | undefined): DecoderFunction { + const viewModel = useViewModel(treeNode) + const [decoder, setDecoder] = useState(viewModel?.decoder) + + useSubscription(viewModel?.onDecoderChange, setDecoder) + + return useCallback( + message => { + return decoder && message.payload + ? decoder.decoder.decode(message.payload, decoder.format) + : { message: message.payload ?? undefined, decoder: Decoder.NONE } + }, + [decoder] + ) +} diff --git a/app/src/components/hooks/useSubscription.ts b/app/src/components/hooks/useSubscription.ts new file mode 100644 index 00000000..413996e2 --- /dev/null +++ b/app/src/components/hooks/useSubscription.ts @@ -0,0 +1,10 @@ +import { useEffect } from 'react' +import { EventDispatcher } from '../../../../events' + +export function useSubscription(dispatcher: EventDispatcher | undefined, callback: (value: T) => void) { + useEffect(() => { + dispatcher?.subscribe(callback) + + return () => dispatcher?.unsubscribe(callback) + }, [dispatcher, callback]) +} diff --git a/app/src/decoders/BinaryDecoder.ts b/app/src/decoders/BinaryDecoder.ts new file mode 100644 index 00000000..b204cbac --- /dev/null +++ b/app/src/decoders/BinaryDecoder.ts @@ -0,0 +1,56 @@ +import { Base64Message } from '../../../backend/src/Model/Base64Message' +import { Decoder } from '../../../backend/src/Model/Decoder' +import { DecoderEnvelope } from './DecoderEnvelope' +import { MessageDecoder } from './MessageDecoder' + +type BinaryFormats = + | 'int8' + | 'int16' + | 'int32' + | 'int64' + | 'uint8' + | 'uint16' + | 'uint32' + | 'uint64' + | 'float' + | 'double' + +/** + * Binary decode primitive binary data type and arrays of these + */ +export const BinaryDecoder: MessageDecoder = { + formats: ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float', 'double'], + decode(input: Base64Message, format: BinaryFormats): DecoderEnvelope { + const decodingOption = { + int8: [Buffer.prototype.readInt8, 1], + int16: [Buffer.prototype.readInt16LE, 2], + int32: [Buffer.prototype.readInt32LE, 4], + int64: [Buffer.prototype.readBigInt64LE, 8], + uint8: [Buffer.prototype.readUint8, 1], + uint16: [Buffer.prototype.readUint16LE, 2], + uint32: [Buffer.prototype.readUint32LE, 4], + uint64: [Buffer.prototype.readBigUint64LE, 8], + float: [Buffer.prototype.readFloatLE, 4], + double: [Buffer.prototype.readDoubleLE, 8], + } as const + + const [readNumber, bytesToRead] = decodingOption[format] + + const buf = input.toBuffer() + let str: String[] = [] + if (buf.length % bytesToRead !== 0) { + return { + error: 'Data type does not align with message', + decoder: Decoder.NONE, + } + } + for (let index = 0; index < buf.length; index += bytesToRead) { + str.push((readNumber as any).apply(buf, [index]).toString()) + } + + return { + message: Base64Message.fromString(JSON.stringify(str.length === 1 ? str[0] : str)), + decoder: Decoder.NONE, + } + }, +} diff --git a/app/src/decoders/DecoderEnvelope.ts b/app/src/decoders/DecoderEnvelope.ts new file mode 100644 index 00000000..c15fa4f4 --- /dev/null +++ b/app/src/decoders/DecoderEnvelope.ts @@ -0,0 +1,8 @@ +import { Base64Message } from '../../../backend/src/Model/Base64Message' +import { Decoder } from '../../../backend/src/Model/Decoder' + +export interface DecoderEnvelope { + message?: Base64Message + error?: string + decoder: Decoder +} diff --git a/app/src/decoders/MessageDecoder.ts b/app/src/decoders/MessageDecoder.ts new file mode 100644 index 00000000..dc96ef66 --- /dev/null +++ b/app/src/decoders/MessageDecoder.ts @@ -0,0 +1,13 @@ +import { Base64Message } from '../../../backend/src/Model/Base64Message' +import { DecoderEnvelope } from './DecoderEnvelope' + +export interface MessageDecoder { + /** + * Can be used to + * @param topic + */ + formats: T[] + canDecodeTopic?(topic: string): boolean + canDecodeData?(data: Base64Message): boolean + decode(input: Base64Message, format: T | string | undefined): DecoderEnvelope +} diff --git a/app/src/decoders/SparkplugBDecoder.ts b/app/src/decoders/SparkplugBDecoder.ts new file mode 100644 index 00000000..b5bedbde --- /dev/null +++ b/app/src/decoders/SparkplugBDecoder.ts @@ -0,0 +1,28 @@ +import { Base64Message } from '../../../backend/src/Model/Base64Message' +import { Decoder } from '../../../backend/src/Model/Decoder' +import { get } from 'sparkplug-payload' +import { MessageDecoder } from './MessageDecoder' +var sparkplug = get('spBv1.0') + +export const SparkplugDecoder: MessageDecoder = { + formats: ['Sparkplug'], + canDecodeTopic(topic: string) { + return !!topic.match(/^spBv1\.0\/[^/]+\/[ND](DATA|CMD|DEATH|BIRTH)\/[^/]+(\/[^/]+)?$/u) + }, + decode(input) { + try { + const message = Base64Message.fromString( + JSON.stringify( + // @ts-ignore + sparkplug.decodePayload(new Uint8Array(input.toBuffer())) + ) + ) + return { message, decoder: Decoder.SPARKPLUG } + } catch { + return { + error: 'Failed to decode sparkplugb payload', + decoder: Decoder.NONE, + } + } + }, +} diff --git a/app/src/decoders/StringDecoder.ts b/app/src/decoders/StringDecoder.ts new file mode 100644 index 00000000..f586bb7f --- /dev/null +++ b/app/src/decoders/StringDecoder.ts @@ -0,0 +1,10 @@ +import { Base64Message } from '../../../backend/src/Model/Base64Message' +import { Decoder } from '../../../backend/src/Model/Decoder' +import { MessageDecoder } from './MessageDecoder' + +export const StringDecoder: MessageDecoder = { + formats: ['string'], + decode(input: Base64Message) { + return { message: input, decoder: Decoder.NONE } + }, +} diff --git a/app/src/decoders/index.ts b/app/src/decoders/index.ts new file mode 100644 index 00000000..2971340c --- /dev/null +++ b/app/src/decoders/index.ts @@ -0,0 +1,6 @@ +import { StringDecoder } from './StringDecoder' +import { BinaryDecoder } from './BinaryDecoder' +import { SparkplugDecoder } from './SparkplugBDecoder' +export * from './MessageDecoder' + +export const decoders = [SparkplugDecoder, BinaryDecoder, StringDecoder] as const diff --git a/app/src/model/ConnectionOptions.ts b/app/src/model/ConnectionOptions.ts index 8eb98719..e20d1223 100644 --- a/app/src/model/ConnectionOptions.ts +++ b/app/src/model/ConnectionOptions.ts @@ -77,11 +77,11 @@ export function createEmptyConnection(): ConnectionOptions { export function makeDefaultConnections() { return { // remember: there was also iot.eclipse.org once - 'mqtt.eclipse.org': { + 'mqtt.eclipseprojects.io': { ...createEmptyConnection(), - id: 'mqtt.eclipse.org', - name: 'mqtt.eclipse.org', - host: 'mqtt.eclipse.org', + id: 'mqtt.eclipseprojects.io', + name: 'mqtt.eclipseprojects.io', + host: 'mqtt.eclipseprojects.io', }, 'test.mosquitto.org': { ...createEmptyConnection(), diff --git a/app/src/model/LegacyConnectionSettings.ts b/app/src/model/LegacyConnectionSettings.ts index 88043889..bc0be12d 100644 --- a/app/src/model/LegacyConnectionSettings.ts +++ b/app/src/model/LegacyConnectionSettings.ts @@ -1,5 +1,4 @@ import { ConnectionOptions, createEmptyConnection } from './ConnectionOptions' -import { v4 } from 'uuid' interface LegacyConnectionSettings { host: string diff --git a/app/src/model/TopicViewModel.ts b/app/src/model/TopicViewModel.ts index 3c7ef540..319f64a1 100644 --- a/app/src/model/TopicViewModel.ts +++ b/app/src/model/TopicViewModel.ts @@ -1,19 +1,157 @@ -import { Destroyable } from '../../../backend/src/Model/Destroyable' +import * as q from '../../../backend/src/Model' +import { Destroyable, MemoryLifecycle } from '../../../backend/src/Model/Destroyable' +import { MessageDecoder, decoders } from '../decoders' import { EventDispatcher } from '../../../events' -export class TopicViewModel implements Destroyable { +function findDecoder(node: q.TreeNode): TopicDecoder | undefined { + const decoder = decoders.find( + decoder => + decoder.canDecodeTopic?.(node.path()) || (node.message?.payload && decoder.canDecodeData?.(node.message?.payload)) + ) + + return decoder + ? { + decoder, + format: undefined, + } + : undefined +} + +type TopicDecoder = { decoder: MessageDecoder; format: string | undefined } + +export class TopicViewModel implements Destroyable, MemoryLifecycle { private selected: boolean private expanded: boolean + private owner: q.TreeNode | undefined + private _decoder?: TopicDecoder + /** + * Reference counter for useViewModel hook + */ + private referenceCounter = 0 public selectionChange = new EventDispatcher() public expandedChange = new EventDispatcher() + public onDecoderChange = new EventDispatcher() + + get decoder(): TopicDecoder | undefined { + if (!this._decoder) { + this._decoder = this.owner && findDecoder(this.owner) + } + + return this._decoder + } + + set decoder(override: TopicDecoder | undefined) { + this._decoder = override + + this.onDecoderChange.dispatch(override) + } - public constructor() { + private clearCache = () => { + if (this._cachedChildTopicCount) { + this._cachedChildTopicCount = undefined + // when child changes, parents are affected as well + this.owner?.sourceEdge?.source?.viewModel?.clearCache() + } + } + + public constructor(treeNode: q.TreeNode) { + this.owner = treeNode this.selected = false - this.expanded = false + this.expanded = true + treeNode.onMerge.subscribe(this.clearCache) + } + + private _cachedChildTopicCount: number | undefined = undefined + + /** + * This function only returns valid values if parents are expanded + * @returns + */ + public getIndex(): number { + if (!this.owner) { + throw new Error('integrity error') + } + + const source = this.owner.sourceEdge?.source + + const parentIndex = source?.viewModel?.getIndex() + // If we have a parent, we have its index + 1 (at least) + const parentIndexWithDepth = parentIndex !== undefined ? parentIndex + 1 : 0 + let position = 0 + const edgeToMatch = this.owner.sourceEdge + for (const edge of source?.edgeArray ?? []) { + if (edge === edgeToMatch) { + break + } + position += edge.target.viewModel?.visibleChildren() ?? 1 + } + + return parentIndexWithDepth + position + } + + public visibleChildAt( + index: number, + depth: number = 0, + parentOffset: number = 0 + ): [q.TreeNode, number] | undefined { + if (!this.owner) { + throw new Error('integrity error') + } + const node = this.owner + + if (parentOffset === index) { + return [node, depth] + } + + let position = parentOffset + 1 + for (const edge of node.edgeArray) { + let viewModel = edge.target.viewModel + const nextPosition = position + (viewModel?.visibleChildren() ?? 0) + if (nextPosition > index) { + return viewModel?.visibleChildAt(index, depth + 1, position) + } + position = nextPosition + } + } + + public visibleChildren(): number { + if (!this.owner) { + throw new Error('integrity error') + } + + if (this._cachedChildTopicCount === undefined) { + if (!this.expanded) { + return 1 + } + + this._cachedChildTopicCount = + 1 + this.owner.edgeArray.map(e => e.target.viewModel?.visibleChildren() ?? 1).reduce((a, b) => a + b, 0) + } + + return this._cachedChildTopicCount as number + } + + public retain() { + this.referenceCounter += 1 + } + + public release() { + this.referenceCounter -= 1 + if (this.referenceCounter <= 0) { + this.destroy() + } } public destroy() { + // console.log('destroy', this.owner?.path(), this.referenceCounter) + this.owner?.onMerge.unsubscribe(this.clearCache) + if (this.owner) { + this.owner.viewModel = undefined + this.owner = undefined + } this.selectionChange.removeAllListeners() + this.onDecoderChange.removeAllListeners() + this.expandedChange.removeAllListeners() } public isSelected() { @@ -32,6 +170,8 @@ export class TopicViewModel implements Destroyable { public setExpanded(expanded: boolean, fireEvent: boolean) { const didChange = this.expanded !== expanded this.expanded = expanded + this.clearCache() + if (didChange && fireEvent) { this.expandedChange.dispatch() } diff --git a/app/tsconfig.json b/app/tsconfig.json index d2847b8c..ca7c7b8a 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -4,38 +4,26 @@ "noImplicitAny": true, "strictNullChecks": true, "strict": true, - "lib": [ - "es2017", - "dom" - ], + "lib": ["es2019", "dom"], "moduleResolution": "node", "outDir": "./build/", "sourceMap": true, "module": "esnext", - "target": "es2017", + "target": "ES2017", "jsx": "react", "paths": { - "react": [ - "./node_modules/@types/react" - ] + "react": ["./node_modules/@types/react"] }, - "types": [ - "react" - ], + "types": ["react"], "allowSyntheticDefaultImports": true, - "skipLibCheck": true + "skipLibCheck": true, + "esModuleInterop": true }, - "include": [ - "./src/**/*" - ], - "exclude": [ - "**/*.d.ts", - ".src/**/*.png", - "./node_modules" - ], + "include": ["./src/**/*"], + "exclude": ["**/*.d.ts", ".src/**/*.png", "./node_modules"], "awesomeTypescriptLoaderOptions": { "useCache": true, "transpileModule": true, "errorsAsWarnings": true } -} \ No newline at end of file +} diff --git a/app/webpack.config.js b/app/webpack.config.js index c522ac4b..543c51ef 100644 --- a/app/webpack.config.js +++ b/app/webpack.config.js @@ -54,7 +54,15 @@ module.exports = { // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'. { test: /\.tsx?$/, - loader: 'ts-loader', + use: [ + { + loader: 'ts-loader', + // options: { + // configFile: './tsconfig.json', + // }, + }, + ], + exclude: /node_modules/, }, // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. { enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' }, @@ -96,4 +104,7 @@ module.exports = { // "react": "React", // "react-dom": "ReactDOM" }, + cache: { + type: 'filesystem', + }, } diff --git a/app/yarn.lock b/app/yarn.lock index 14e43951..1a8e5375 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@babel/runtime@^7.0.0": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c" + integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e" @@ -19,6 +26,18 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@jridgewell/gen-mapping@^0.3.0": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -59,6 +78,26 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsonjoy.com/base64@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/json-pack@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz#ab59c642a2e5368e8bcfd815d817143d4f3035d0" + integrity sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg== + dependencies: + "@jsonjoy.com/base64" "^1.1.1" + "@jsonjoy.com/util" "^1.1.2" + hyperdyperid "^1.2.0" + thingies "^1.20.0" + +"@jsonjoy.com/util@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.1.3.tgz#75b1c3cf21b70e665789d1ad3eabeff8b7fd1429" + integrity sha512-g//kkF4kOwUjemValCtOc/xiYzmwMRmWq3Bn+YnzOzuZLHq2PpMOxxIayN3cKbo7Ko2Np65t6D9H81IvXbXhqg== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -146,6 +185,11 @@ prop-types "^15.7.2" react-is "^16.8.0 || ^17.0.0" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@polka/url@^1.0.0-next.24": version "1.0.0-next.25" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" @@ -159,14 +203,14 @@ "@types/connect" "*" "@types/node" "*" -"@types/bonjour@^3.5.9": +"@types/bonjour@^3.5.13": version "3.5.13" resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" -"@types/connect-history-api-fallback@^1.3.5": +"@types/connect-history-api-fallback@^1.5.4": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== @@ -433,7 +477,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@*", "@types/express@^4.17.13": +"@types/express@*", "@types/express@^4.17.21": version "4.17.21" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -563,6 +607,21 @@ dependencies: "@types/react" "*" +"@types/react-virtualized@^9.21.30": + version "9.21.30" + resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.30.tgz#ba39821bcb2487512a8a2cdd9fbdb5e6fc87fedb" + integrity sha512-4l2TFLQ8BCjNDQlvH85tU6gctuZoEdgYzENQyZHpgTHU7hoLzYgPSOALMAeA58LOWua8AzC6wBivPj1lfl6JgQ== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + +"@types/react-window@^1.8.8": + version "1.8.8" + resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.8.tgz#c20645414d142364fbe735818e1c1e0a145696e3" + integrity sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q== + dependencies: + "@types/react" "*" + "@types/react@*": version "18.2.64" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.64.tgz#3700fbb6b2fa60a6868ec1323ae4cbd446a2197d" @@ -581,10 +640,10 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== "@types/scheduler@*": version "0.16.8" @@ -599,14 +658,14 @@ "@types/mime" "^1" "@types/node" "*" -"@types/serve-index@^1.9.1": +"@types/serve-index@^1.9.4": version "1.9.4" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" -"@types/serve-static@*", "@types/serve-static@^1.13.10": +"@types/serve-static@*": version "1.15.5" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== @@ -615,6 +674,15 @@ "@types/mime" "*" "@types/node" "*" +"@types/serve-static@^1.15.5": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/sha1@^1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@types/sha1/-/sha1-1.1.5.tgz#e9f78a187e5035c608b32567980443e16fcee2c6" @@ -627,7 +695,7 @@ resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.36.tgz#e4f1ca065f84c20939e9850e70222202bd76ff3f" integrity sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag== -"@types/sockjs@^0.3.33": +"@types/sockjs@^0.3.36": version "0.3.36" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== @@ -646,17 +714,17 @@ dependencies: moment ">=2.13.0" -"@types/ws@^8.5.5": +"@types/ws@^8.5.10": version "8.5.10" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== dependencies: "@types/node" "*" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" @@ -671,10 +739,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" @@ -690,15 +758,15 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/ieee754@1.11.6": version "1.11.6" @@ -719,77 +787,75 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-opt" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - "@webassemblyjs/wast-printer" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" -"@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-api-error" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" - integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== -"@webpack-cli/info@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" - integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== - dependencies: - envinfo "^7.7.3" +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== -"@webpack-cli/serve@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" - integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -888,6 +954,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -895,6 +966,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -997,7 +1073,7 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" -bonjour-service@^1.0.11: +bonjour-service@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== @@ -1010,14 +1086,6 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - brace-expansion@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" @@ -1052,6 +1120,13 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -1144,7 +1219,7 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" -chokidar@^3.5.3: +chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -1228,7 +1303,12 @@ commander@2, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^7.0.0, commander@^7.2.0: +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== @@ -1278,11 +1358,6 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - connect-history-api-fallback@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" @@ -1327,7 +1402,7 @@ cross-env@^7.0.2: dependencies: cross-spawn "^7.0.1" -cross-spawn@^7.0.1, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1797,6 +1872,19 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.5.1" +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -1813,10 +1901,10 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== define-properties@^1.2.1: version "1.2.1" @@ -1944,6 +2032,11 @@ duplexer@^0.1.2: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1959,6 +2052,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -1997,7 +2095,7 @@ engine.io-parser@~2.2.0: blob "0.0.5" has-binary2 "~1.0.2" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0: +enhanced-resolve@^5.0.0: version "5.15.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz#384391e025f099e67b4b00bfd7f0906a408214e1" integrity sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg== @@ -2005,6 +2103,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.16.0: + version "5.16.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567" + integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -2215,6 +2321,14 @@ follow-redirects@^1.0.0, follow-redirects@^1.15.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -2234,11 +2348,6 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-monkey@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" - integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2315,17 +2424,16 @@ glob@8.1.0: minimatch "^5.0.1" once "^1.3.0" -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== +glob@^10.3.7: + version "10.3.16" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.16.tgz#bf6679d5d51279c8cfae4febe0d051d2a4bf4c6f" + integrity sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw== dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.1" + minipass "^7.0.4" + path-scurry "^1.11.0" global@^4.3.1: version "4.4.0" @@ -2342,7 +2450,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -2434,7 +2542,7 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-entities@^2.3.2: +html-entities@^2.4.0: version "2.5.2" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== @@ -2534,6 +2642,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + hyphenate-style-name@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" @@ -2604,20 +2717,20 @@ internmap@^1.0.0: resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== is-arguments@^1.1.1: version "1.1.1" @@ -2648,10 +2761,10 @@ is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== is-extglob@^2.1.1: version "2.1.1" @@ -2675,6 +2788,18 @@ is-in-browser@^1.0.2, is-in-browser@^1.1.3: resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g== +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -2725,12 +2850,12 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== dependencies: - is-docker "^2.0.0" + is-inside-container "^1.0.0" isarray@2.0.1: version "2.0.1" @@ -2752,6 +2877,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +jackspeak@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.1.2.tgz#eada67ea949c6b71de50f1b09c92a961897b90ab" + integrity sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -2888,7 +3022,7 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -launch-editor@^2.6.0: +launch-editor@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== @@ -2992,6 +3126,11 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" +lru-cache@^10.2.0: + version "10.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -3004,12 +3143,20 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== +memfs@^4.6.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.9.2.tgz#42e7b48207268dad8c9c48ea5d4952c5d3840433" + integrity sha512-f16coDZlTG1jskq3mxarwB+fGRrd0uXWt+o1WIhRfOwbXQZqUDsTVxQBFK9JjRQHblg8eAG2JSbprDXKjc7ijQ== dependencies: - fs-monkey "^1.0.4" + "@jsonjoy.com/json-pack" "^1.0.3" + "@jsonjoy.com/util" "^1.1.2" + sonic-forest "^1.0.0" + tslib "^2.0.0" + +"memoize-one@>=3.1.1 <6": + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== merge-descriptors@1.0.1: version "1.0.1" @@ -3075,13 +3222,6 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -3089,11 +3229,23 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: + version "7.1.1" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481" + integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA== + mocha@^10.4.0: version "10.4.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" @@ -3243,7 +3395,7 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -3269,14 +3421,15 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^8.0.9: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== +open@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" opener@^1.5.2: version "1.5.2" @@ -3311,12 +3464,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== dependencies: - "@types/retry" "0.12.0" + "@types/retry" "0.12.2" + is-network-error "^1.0.0" retry "^0.13.1" p-try@^2.0.0: @@ -3365,11 +3519,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -3380,6 +3529,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -3689,6 +3846,14 @@ react-vis@^1.11.6: prop-types "^15.5.8" react-motion "^0.5.2" +react-window@^1.8.10: + version "1.8.10" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.10.tgz#9e6b08548316814b443f7002b1cf8fd3a1bdde03" + integrity sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg== + dependencies: + "@babel/runtime" "^7.0.0" + memoize-one ">=3.1.1 <6" + react@^16.11: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" @@ -3727,12 +3892,12 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== dependencies: - resolve "^1.9.0" + resolve "^1.20.0" redux-batched-actions@0.5: version "0.5.0" @@ -3814,7 +3979,7 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.9.0: +resolve@^1.20.0: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3828,12 +3993,17 @@ retry@^0.13.1: resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== +rimraf@^5.0.5: + version "5.0.7" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" + integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== dependencies: - glob "^7.1.3" + glob "^10.3.7" + +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== rw@1: version "1.3.3" @@ -3881,7 +4051,7 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: +schema-utils@^4.0.0, schema-utils@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -3896,7 +4066,7 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^2.1.1: +selfsigned@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== @@ -4051,6 +4221,11 @@ signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sirv@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" @@ -4095,6 +4270,13 @@ sockjs@^0.3.24: uuid "^8.3.2" websocket-driver "^0.7.4" +sonic-forest@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sonic-forest/-/sonic-forest-1.0.3.tgz#81363af60017daba39b794fce24627dc412563cb" + integrity sha512-dtwajos6IWMEWXdEbW1IkEkyL2gztCAgDplRIX+OT5aRKnEd5e7r7YCxRgXZdhRP1FBdOBf8axeTPhzDv8T4wQ== + dependencies: + tree-dump "^1.0.0" + source-map-loader@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271" @@ -4154,6 +4336,15 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -4163,6 +4354,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -4177,6 +4377,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -4184,6 +4391,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -4247,6 +4461,11 @@ terser@^5.10.0, terser@^5.26.0: commander "^2.20.0" source-map-support "~0.5.20" +thingies@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1" + integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g== + thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" @@ -4279,6 +4498,11 @@ totalist@^3.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== +tree-dump@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tree-dump/-/tree-dump-1.0.1.tgz#b448758da7495580e6b7830d6b7834fca4c45b96" + integrity sha512-WCkcRBVPSlHHq1dc/px9iOfqklvzCbdRwvlNfxGZsrHqf6aZttfPrd7DJTt6oR10dwUfpFFQeVTkPbBIZxX/YA== + ts-loader@^9.2.6: version "9.5.1" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" @@ -4290,7 +4514,7 @@ ts-loader@^9.2.6: semver "^7.3.4" source-map "^0.7.4" -tslib@^2.0.3: +tslib@^2.0.0, tslib@^2.0.3: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -4368,10 +4592,10 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -4402,70 +4626,72 @@ webpack-bundle-analyzer@^4.5.0: sirv "^2.0.3" ws "^7.3.1" -webpack-cli@^4.9.2: - version "4.10.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" - integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.2.0" - "@webpack-cli/info" "^1.5.0" - "@webpack-cli/serve" "^1.7.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" colorette "^2.0.14" - commander "^7.0.0" + commander "^10.0.1" cross-spawn "^7.0.3" + envinfo "^7.7.3" fastest-levenshtein "^1.0.12" import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" + interpret "^3.1.1" + rechoir "^0.8.0" webpack-merge "^5.7.3" -webpack-dev-middleware@^5.3.1: - version "5.3.4" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" - integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== +webpack-dev-middleware@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz#2af00538b6e4eda05f5afdd5d711dbebc05958f7" + integrity sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA== dependencies: colorette "^2.0.10" - memfs "^3.4.3" + memfs "^4.6.0" mime-types "^2.1.31" + on-finished "^2.4.1" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.7.4: - version "4.15.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7" - integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== - dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.5" +webpack-dev-server@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz#cb6ea47ff796b9251ec49a94f24a425e12e3c9b8" + integrity sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA== + dependencies: + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" + bonjour-service "^1.2.1" + chokidar "^3.6.0" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" express "^4.17.3" graceful-fs "^4.2.6" - html-entities "^2.3.2" + html-entities "^2.4.0" http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + rimraf "^5.0.5" + schema-utils "^4.2.0" + selfsigned "^2.4.1" serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.13.0" + webpack-dev-middleware "^7.1.0" + ws "^8.16.0" webpack-merge@^5.7.3: version "5.10.0" @@ -4481,26 +4707,26 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.69.1: - version "5.90.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac" - integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA== +webpack@^5.91.0: + version "5.91.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" + integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" acorn-import-assertions "^1.9.0" browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" + enhanced-resolve "^5.16.0" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" @@ -4508,7 +4734,7 @@ webpack@^5.69.1: schema-utils "^3.2.0" tapable "^2.1.1" terser-webpack-plugin "^5.3.10" - watchpack "^2.4.0" + watchpack "^2.4.1" webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: @@ -4542,6 +4768,15 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -4551,6 +4786,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4561,10 +4805,10 @@ ws@^7.3.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.13.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" - integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== +ws@^8.16.0: + version "8.17.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" + integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== ws@~7.4.2: version "7.4.6" diff --git a/backend/src/ConfigStorage.ts b/backend/src/ConfigStorage.ts index 7da131ca..0859c8f3 100644 --- a/backend/src/ConfigStorage.ts +++ b/backend/src/ConfigStorage.ts @@ -1,7 +1,7 @@ -import * as FileAsync from 'lowdb/adapters/FileAsync' -import * as fs from 'fs-extra' -import * as lowdb from 'lowdb' -import * as path from 'path' +import FileAsync from 'lowdb/adapters/FileAsync' +import fs from 'fs-extra' +import lowdb from 'lowdb' +import path from 'path' import { backendRpc } from '../../events' import { storageClearEvent, storageLoadEvent, storageStoreEvent } from '../../events/StorageEvents' diff --git a/backend/src/DataSource/MqttSource.ts b/backend/src/DataSource/MqttSource.ts index e53d5a25..bd55b6fd 100644 --- a/backend/src/DataSource/MqttSource.ts +++ b/backend/src/DataSource/MqttSource.ts @@ -98,7 +98,7 @@ export class MqttSource implements DataSource { public publish(msg: MqttMessage) { if (this.client) { - this.client.publish(msg.topic, msg.payload ? Base64Message.toUnicodeString(msg.payload) : '', { + this.client.publish(msg.topic, (msg.payload && new Base64Message(msg.payload))?.toBuffer() ?? '', { qos: msg.qos, retain: msg.retain, }) diff --git a/backend/src/Model/Base64Message.ts b/backend/src/Model/Base64Message.ts index 4bd005b0..096f5551 100644 --- a/backend/src/Model/Base64Message.ts +++ b/backend/src/Model/Base64Message.ts @@ -1,31 +1,93 @@ import { Base64 } from 'js-base64' -import { Decoder } from './Decoder' +import { TopicDataType } from './TreeNode' + +export type Base64MessageDTO = Pick export class Base64Message { - private base64Message: string - private unicodeValue: string - public decoder: Decoder - public length: number + public base64Message: string + private _unicodeValue: string | undefined + + // Todo: Rename to `encodedLength` + public get length(): number { + return this.base64Message.length + } + + private get unicodeValue(): string { + if (!this._unicodeValue) { + this._unicodeValue = Base64.decode(this.base64Message ?? '') + } + + return this._unicodeValue + } + + constructor(base64Str?: string | Base64MessageDTO, error?: string) { + if (typeof base64Str === 'string' || typeof base64Str === 'undefined') { + this.base64Message = base64Str ?? '' + } else { + if (typeof base64Str.base64Message !== 'string') { + throw new Error('Received unexpected type in copy constructor') + } + this.base64Message = base64Str.base64Message + } + } - private constructor(base64Str: string) { - this.base64Message = base64Str - this.unicodeValue = Base64.decode(base64Str) - this.length = base64Str.length - this.decoder = Decoder.NONE + /** + * Override default JSON serialization behavior to only return the DTO + * @returns + */ + public toJSON(): Base64MessageDTO { + return { base64Message: this.base64Message } } - public static toUnicodeString(message: Base64Message) { - return message.unicodeValue || '' + public toUnicodeString() { + return this.unicodeValue || '' } public static fromBuffer(buffer: Buffer) { return new Base64Message(buffer.toString('base64')) } + public toBuffer(): Buffer { + return Buffer.from(this.base64Message, 'base64') + } + public static fromString(str: string) { return new Base64Message(Base64.encode(str)) } + public format(type: TopicDataType = 'string'): [string, 'json' | undefined] { + try { + switch (type) { + case 'json': { + const json = JSON.parse(this.toUnicodeString()) + return [JSON.stringify(json, undefined, ' '), 'json'] + } + case 'hex': { + const hex = Base64Message.toHex(this) + return [hex, undefined] + } + default: { + const str = this.toUnicodeString() + return [str, undefined] + } + } + } catch (error) { + const str = this.toUnicodeString() + return [str, undefined] + } + } + + public static toHex(message: Base64Message) { + const buf = Buffer.from(message.base64Message, 'base64') + + let str: string = '' + buf.forEach(element => { + let hex = element.toString(16).toUpperCase() + str += `0x${hex.length < 2 ? '0' + hex : hex} ` + }) + return str.trimRight() + } + public static toDataUri(message: Base64Message, mimeType: string) { return `data:${mimeType};base64,${message.base64Message}` } diff --git a/backend/src/Model/ChangeBuffer.ts b/backend/src/Model/ChangeBuffer.ts index 018e5ba0..4310c736 100644 --- a/backend/src/Model/ChangeBuffer.ts +++ b/backend/src/Model/ChangeBuffer.ts @@ -15,7 +15,7 @@ export class ChangeBuffer { public push(val: MqttMessage) { if (!this.isFull()) { this.buffer.push({ message: val, received: new Date() }) - this.size += this.estimatedMessageOverhead + (val.payload ? val.payload.length : 0) + this.size += this.estimatedMessageOverhead + (val.payload?.base64Message.length ?? 0) this.length += 1 } } diff --git a/backend/src/Model/Destroyable.ts b/backend/src/Model/Destroyable.ts index 032bdd9b..30e1af91 100644 --- a/backend/src/Model/Destroyable.ts +++ b/backend/src/Model/Destroyable.ts @@ -1,3 +1,8 @@ export interface Destroyable { destroy(): void } + +export interface MemoryLifecycle { + retain(): void + release(): void +} diff --git a/backend/src/Model/Edge.ts b/backend/src/Model/Edge.ts index b7d87875..2455a559 100644 --- a/backend/src/Model/Edge.ts +++ b/backend/src/Model/Edge.ts @@ -1,8 +1,8 @@ -import { Destroyable } from './Destroyable' +import { Destroyable, MemoryLifecycle } from './Destroyable' import { Hashable, TreeNode } from './' const sha1 = require('sha1') -export class Edge implements Hashable { +export class Edge implements Hashable { public name: string public target!: TreeNode diff --git a/backend/src/Model/Message.ts b/backend/src/Model/Message.ts index 5b94304a..556861f9 100644 --- a/backend/src/Model/Message.ts +++ b/backend/src/Model/Message.ts @@ -1,7 +1,8 @@ import { Base64Message } from './Base64Message' import { QoS } from '../DataSource/MqttSource' +import { MemoryConsumptionExpressedByLength } from './RingBuffer' -export interface Message { +export interface Message extends MemoryConsumptionExpressedByLength { // mqtt based info payload: Base64Message | null messageId?: number diff --git a/backend/src/Model/Tree.ts b/backend/src/Model/Tree.ts index 2eeedef1..37eced81 100644 --- a/backend/src/Model/Tree.ts +++ b/backend/src/Model/Tree.ts @@ -1,10 +1,10 @@ import { ChangeBuffer } from './ChangeBuffer' -import { Destroyable } from './Destroyable' +import { Destroyable, MemoryLifecycle } from './Destroyable' import { EventDispatcher, makeConnectionMessageEvent, MqttMessage, EventBusInterface } from '../../../events' import { TreeNode } from './' import { TreeNodeFactory } from './TreeNodeFactory' -export class Tree extends TreeNode { +export class Tree extends TreeNode { public connectionId?: string public updateSource?: EventBusInterface public nodeFilter?: (node: TreeNode) => boolean diff --git a/backend/src/Model/TreeNode.ts b/backend/src/Model/TreeNode.ts index 1576b92b..f3e7a462 100644 --- a/backend/src/Model/TreeNode.ts +++ b/backend/src/Model/TreeNode.ts @@ -1,8 +1,11 @@ -import { Destroyable } from './Destroyable' +import { Destroyable, MemoryLifecycle } from './Destroyable' import { Edge, Message, RingBuffer, MessageHistory } from './' import { EventDispatcher } from '../../../events' +import { TopicViewModel } from '../../../app/src/model/TopicViewModel' -export class TreeNode { +export type TopicDataType = 'string' | 'json' | 'hex' + +export class TreeNode { public sourceEdge?: Edge public message?: Message public messageHistory: MessageHistory = new RingBuffer(20000, 100) @@ -17,6 +20,7 @@ export class TreeNode { public onMessage = new EventDispatcher() public onDestroy = new EventDispatcher>() public isTree = false + public type: TopicDataType = 'json' private cachedPath?: string private cachedChildTopics?: Array> @@ -45,6 +49,8 @@ export class TreeNode { this.onMessage.subscribe(() => { this.lastUpdate = Date.now() }) + this.viewModel = new TopicViewModel(this as any) as any + this.viewModel?.retain() } private previous(): TreeNode | undefined { @@ -114,7 +120,7 @@ export class TreeNode { for (const edge of this.edgeArray) { edge.target.destroy() } - this.viewModel && this.viewModel.destroy() + this.viewModel?.release() this.viewModel = undefined this.edgeArray = [] this.edges = {} @@ -144,7 +150,7 @@ export class TreeNode { } public hash(): string { - return `N${this.sourceEdge ? this.sourceEdge.hash() : ''}` + return `N${this.sourceEdge?.hash() ?? ''}` } public firstNode(): TreeNode { @@ -153,7 +159,7 @@ export class TreeNode { public path(): string { if (!this.cachedPath) { - return this.branch() + this.cachedPath = this.branch() .map(node => node.sourceEdge && node.sourceEdge.name) .filter(name => name !== undefined) .join('/') diff --git a/backend/src/Model/TreeNodeFactory.ts b/backend/src/Model/TreeNodeFactory.ts index d1b2c52c..01443610 100644 --- a/backend/src/Model/TreeNodeFactory.ts +++ b/backend/src/Model/TreeNodeFactory.ts @@ -1,10 +1,11 @@ -import { Destroyable } from './Destroyable' +import { Destroyable, MemoryLifecycle } from './Destroyable' import { Edge, Tree, TreeNode } from './' import { MqttMessage } from '../../../events' +import { Base64Message } from './Base64Message' export abstract class TreeNodeFactory { private static messageCounter = 0 - public static insertNodeAtPosition( + public static insertNodeAtPosition( edgeNames: Array, node: TreeNode ) { @@ -20,7 +21,7 @@ export abstract class TreeNodeFactory { node.sourceEdge!.target = node } - public static fromMessage( + public static fromMessage( mqttMessage: MqttMessage, receiveDate: Date = new Date() ): TreeNode { @@ -30,7 +31,8 @@ export abstract class TreeNodeFactory { mqttMessage.retain node.setMessage({ ...mqttMessage, - length: mqttMessage.payload?.length ?? 0, + payload: mqttMessage.payload && new Base64Message(mqttMessage.payload?.base64Message), + length: mqttMessage.payload?.base64Message.length ?? 0, received: receiveDate, messageNumber: this.messageCounter, }) diff --git a/backend/src/Model/index.ts b/backend/src/Model/index.ts index 047e633b..b0ac6735 100644 --- a/backend/src/Model/index.ts +++ b/backend/src/Model/index.ts @@ -1,5 +1,5 @@ export { Edge } from './Edge' -export { TreeNode } from './TreeNode' +export { TreeNode, TopicDataType } from './TreeNode' export { Message } from './Message' export { TreeNodeFactory } from './TreeNodeFactory' export { Tree } from './Tree' diff --git a/backend/src/Model/sparkplugb.ts b/backend/src/Model/sparkplugb.ts deleted file mode 100644 index d3625b8b..00000000 --- a/backend/src/Model/sparkplugb.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Base64Message } from './Base64Message' -import { Decoder } from './Decoder' -import { get } from 'sparkplug-payload' -var sparkplug = get("spBv1.0") - -export const SparkplugDecoder = { - decode(input: Buffer): Base64Message { - try { - const message = Base64Message.fromString(JSON.stringify( - // @ts-ignore - sparkplug.decodePayload(new Uint8Array(input))) - ) - message.decoder = Decoder.SPARKPLUG - return message - } catch { - const message = Base64Message.fromString("Failed to decode sparkplugb payload") - message.decoder = Decoder.NONE - return message - } - }, -} diff --git a/backend/src/Model/spec/TreeNode.ViewModel.spec.ts b/backend/src/Model/spec/TreeNode.ViewModel.spec.ts new file mode 100644 index 00000000..92be7512 --- /dev/null +++ b/backend/src/Model/spec/TreeNode.ViewModel.spec.ts @@ -0,0 +1,67 @@ +import 'mocha' + +import { expect } from 'chai' +import { makeTreeNode } from './makeTreeNode' + +describe('TreeNode', () => { + const leaf1 = makeTreeNode('foo/bar', 'foo') + const leaf2 = makeTreeNode('foo/bar/baz', 'bar') + const leaf3 = makeTreeNode('foo/biz/baz', 'bar') + const leaf4 = makeTreeNode('bar/biz', 'bar') + const root = leaf1.firstNode() + + root.updateWithNode(leaf2.firstNode()) + root.updateWithNode(leaf3.firstNode()) + root.updateWithNode(leaf4.firstNode()) + + describe('expanding the root should count the children', () => { + it('nothing expanded', () => { + expect(root?.viewModel?.visibleChildren()).to.eq(1) + }) + + it('root expanded', () => { + root.viewModel?.setExpanded(true) + expect(root?.viewModel?.visibleChildren()).to.eq(3) + }) + + it('root and "foo" expanded', () => { + root.viewModel?.setExpanded(true) + root.findNode('foo')!.viewModel!.setExpanded(true) + expect(root?.viewModel?.visibleChildren()).to.eq(5) + }) + }) + + describe('visibleChildAt', () => { + it('nothing expanded', () => { + expect(root?.viewModel?.visibleChildAt(0)?.[0].path()).to.eq('') + }) + + it('root expanded', () => { + root.viewModel?.setExpanded(true) + expect(root?.viewModel?.visibleChildAt(1)?.[0].path()).to.eq('foo') + }) + + it('root and "foo" expanded', () => { + root.viewModel?.setExpanded(true) + root.findNode('foo')!.viewModel!.setExpanded(true) + expect(root?.viewModel?.visibleChildAt(4)?.[0].path()).to.eq('bar') + }) + }) + + describe('getIndex', () => { + it('nothing expanded', () => { + expect(root?.viewModel?.getIndex()).to.eq(0) + }) + + it('root expanded', () => { + root.viewModel?.setExpanded(true) + expect(root?.viewModel?.visibleChildAt(1)?.[0].viewModel?.getIndex()).to.eq(1) + }) + + it('root and "foo" expanded', () => { + root.viewModel?.setExpanded(true) + root.findNode('foo')!.viewModel!.setExpanded(true) + expect(root?.viewModel?.visibleChildAt(4)?.[0].viewModel?.getIndex()).to.eq(4) + }) + }) +}) diff --git a/backend/src/Model/spec/TreeNode.spec.ts b/backend/src/Model/spec/TreeNode.spec.ts index 4a31ae12..bf01a390 100644 --- a/backend/src/Model/spec/TreeNode.spec.ts +++ b/backend/src/Model/spec/TreeNode.spec.ts @@ -1,7 +1,6 @@ import 'mocha' import { expect } from 'chai' -import { Base64Message } from '../Base64Message' import { makeTreeNode } from './makeTreeNode' describe('TreeNode', () => { @@ -14,7 +13,7 @@ describe('TreeNode', () => { it('updateWithNode should update value', () => { const topics = 'foo/bar'.split('/') const leaf = makeTreeNode('foo/bar', '3') - expect(Base64Message.toUnicodeString(leaf.message!.payload!)).to.eq('3') + expect(leaf.message!.payload!.toUnicodeString()).to.eq('3') const updateLeave = makeTreeNode('foo/bar', '5') @@ -22,13 +21,13 @@ describe('TreeNode', () => { root.updateWithNode(updateLeave.firstNode()) expect(root.sourceEdge).to.eq(undefined) - expect(Base64Message.toUnicodeString(leaf.message!.payload!)).to.eq('5') + expect(leaf.message!.payload!.toUnicodeString()).to.eq('5') }) it('updateWithNode should update intermediate nodes', () => { const topics1 = 'foo/bar/baz'.split('/') const leaf = makeTreeNode('foo/bar/baz', '3') - expect(Base64Message.toUnicodeString(leaf.message!.payload!)).to.eq('3') + expect(leaf.message!.payload!.toUnicodeString()).to.eq('3') const topics2 = 'foo/bar'.split('/') const updateLeave = makeTreeNode('foo/bar', '5') @@ -37,10 +36,10 @@ describe('TreeNode', () => { const barNode = leaf.firstNode().findNode('foo/bar') expect(barNode && barNode.sourceEdge && barNode.sourceEdge.name).to.eq('bar') - expect(Base64Message.toUnicodeString(barNode!.message!.payload!)).to.eq('5') + expect(barNode!.message!.payload!.toUnicodeString()).to.eq('5') expect(leaf.sourceEdge && leaf.sourceEdge.name).to.eq('baz') - expect(Base64Message.toUnicodeString(leaf.message!.payload!)).to.eq('3') + expect(leaf.message!.payload!.toUnicodeString()).to.eq('3') }) it('updateWithNode should add nodes to the tree', () => { diff --git a/backend/src/Model/spec/TreeNodeFactory.spec.ts b/backend/src/Model/spec/TreeNodeFactory.spec.ts index 5b69a8d4..87482388 100644 --- a/backend/src/Model/spec/TreeNodeFactory.spec.ts +++ b/backend/src/Model/spec/TreeNodeFactory.spec.ts @@ -1,6 +1,5 @@ import 'mocha' import { expect } from 'chai' -import { Base64Message } from '../Base64Message' import { makeTreeNode } from './makeTreeNode' describe('TreeNodeFactory', () => { @@ -20,7 +19,7 @@ describe('TreeNodeFactory', () => { expect(node).to.not.eq(undefined) expect(node.sourceEdge.name).to.eq('bar') - expect(Base64Message.toUnicodeString(node.message.payload!)).to.eq('5') + expect(node.message.payload!.toUnicodeString()).to.eq('5') const foo = node.firstNode().findNode('foo') expect(foo && foo.sourceEdge && foo.sourceEdge.name).to.eq('foo') @@ -34,7 +33,7 @@ describe('TreeNodeFactory', () => { return } - expect(Base64Message.toUnicodeString(node.message.payload!)).to.eq('5') + expect(node.message.payload!.toUnicodeString()).to.eq('5') expect(node.sourceEdge.name).to.eq('baz') const barNode = node.sourceEdge.source diff --git a/backend/src/index.ts b/backend/src/index.ts index 7e597e3d..3a322ba2 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -10,7 +10,6 @@ import { makePublishEvent, removeConnection, } from '../../events' -import { SparkplugDecoder } from './Model/sparkplugb' export class ConnectionManager { private connections: { [s: string]: DataSource } = {} @@ -48,12 +47,7 @@ export class ConnectionManager { } let decoded_payload = null - // spell-checker: disable-next-line - if (topic.match(/^spBv1\.0\/[^/]+\/[ND](DATA|CMD|DEATH|BIRTH)\/[^/]+(\/[^/]+)?$/u)) { - decoded_payload = SparkplugDecoder.decode(buffer) - } else { - decoded_payload = Base64Message.fromBuffer(buffer) - } + decoded_payload = Base64Message.fromBuffer(buffer) backendEvents.emit(messageEvent, { topic, diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..ff49d152 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,15 @@ +const eslint = require('@eslint/js') +const hooksPlugin = require('eslint-plugin-react-hooks') + +module.export = [ + // eslint.configs.recommended, + { + // files: ['app/src/**/*'], + plugins: { + 'react-hooks': hooksPlugin, + }, + ignores: ['build/**/*', 'dist/**/*', 'node_modules/**/*', 'app/build/**/*'], + ignorePatterns: ['build/**/*', 'dist/**/*', 'node_modules/**/*', 'app/build/**/*'], + rules: hooksPlugin.configs.recommended.rules, + }, +] diff --git a/events/Events.ts b/events/Events.ts index 69ce9544..418652bc 100644 --- a/events/Events.ts +++ b/events/Events.ts @@ -1,4 +1,4 @@ -import { Base64Message } from '../backend/src/Model/Base64Message' +import { Base64MessageDTO } from '../backend/src/Model/Base64Message' import { DataSourceState, MqttOptions } from '../backend/src/DataSource' import { UpdateInfo } from 'builder-util-runtime' import { RpcEvent } from './EventSystem/Rpc' @@ -32,7 +32,7 @@ export const updateAvailable: Event = { export interface MqttMessage { topic: string - payload: Base64Message | null + payload: Base64MessageDTO | null qos: 0 | 1 | 2 retain: boolean // Set if QoS is > 0 on received messages diff --git a/src/electron.ts b/src/electron.ts index 94118de8..7b4cf773 100644 --- a/src/electron.ts +++ b/src/electron.ts @@ -19,7 +19,8 @@ registerCrashReporter() // const electronTelemetry = electronTelemetryFactory('9b0c8ca04a361eb8160d98c5', buildOptions) // } -app.commandLine.appendSwitch('--no-sandbox') +// disable-dev-shm-usage is required to run the debug console +app.commandLine.appendSwitch('--no-sandbox --disable-dev-shm-usage') app.whenReady().then(() => { backendRpc.on(makeOpenDialogRpc(), async request => { return dialog.showOpenDialog(BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0], request) @@ -69,8 +70,6 @@ async function createWindow() { } }) - console.log('icon path', iconPath) - // Load the index.html of the app. if (isDev()) { mainWindow.loadURL('http://localhost:8080') diff --git a/src/spec/demoVideo.ts b/src/spec/demoVideo.ts index bec1b973..e907a18f 100644 --- a/src/spec/demoVideo.ts +++ b/src/spec/demoVideo.ts @@ -36,6 +36,14 @@ process.on('unhandledRejection', (error: Error | any) => { process.exit(1) }) +setTimeout( + () => { + console.error('Timeout reached') + process.exit(1) + }, + 60 * 10 * 1000 +) + const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi'] async function doStuff() { @@ -143,10 +151,17 @@ async function doStuff() { await sleep(3000) }) + setTimeout(() => { + console.log('Forced quit') + process.exit(0) + }, 10 * 1000) stopMqtt() console.log('Stopped mqtt client') cleanUp(scenes, electronApp) + + // Force exit since there appear to be open handles + process.exit(0) } doStuff() diff --git a/tsconfig.json b/tsconfig.json index 74813a89..db8a514c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,15 +9,11 @@ "moduleResolution": "node", "sourceRoot": "src/", "target": "ES2017", - "lib": [ - "es2017", - "dom" - ], + "lib": ["ES2017", "dom"], "sourceMap": true, - "types": [ - "node" - ], - "skipLibCheck": true + "types": ["node"], + "skipLibCheck": true, + "esModuleInterop": true }, "include": [ "src/electron.ts", @@ -26,7 +22,5 @@ "src/spec/leakTest.ts", "scripts/*.ts" ], - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "exclude": ["node_modules"] +} diff --git a/yarn.lock b/yarn.lock index bd3acaa3..167d7cc1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -659,6 +659,38 @@ minimatch "^3.0.4" plist "^3.0.4" +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.3.0.tgz#2e8f65c9c55227abc4845b1513c69c32c679d8fe" + integrity sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw== + "@fastify/busboy@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" @@ -683,6 +715,30 @@ reflect-metadata "^0.1.12" tslib "^1.8.1" +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== + dependencies: + "@humanwhocodes/object-schema" "^2.0.3" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" + integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" @@ -786,7 +842,7 @@ resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -1514,12 +1570,17 @@ about-window@^1.12.1: resolved "https://registry.npmjs.org/about-window/-/about-window-1.15.2.tgz" integrity sha512-31mDAnLUfKm4uShfMzeEoS6a3nEto2tUt4zZn7qyAKedaTV4p0dGiW1n+YG8vtRh78mZiewghWJmoxDY+lHyYg== +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-walk@^8.1.1: version "8.3.2" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.4.1: +acorn@^8.11.3, acorn@^8.4.1: version "8.11.3" resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -1559,7 +1620,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.0: +ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2475,7 +2536,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2674,6 +2735,11 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + default-require-extensions@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz" @@ -3069,16 +3135,112 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +eslint-plugin-react-hooks@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" + integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== + +eslint-scope@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" + integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + +eslint@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.3.0.tgz#36a96db84592618d6ed9074d677e92f4e58c08b9" + integrity sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.3.0" + "@humanwhocodes/config-array" "^0.13.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.3.0" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.0.1" + eslint-visitor-keys "^4.0.0" + espree "^10.0.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" + integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== + dependencies: + acorn "^8.11.3" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.0.0" + esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + esutils@^1.1.6: version "1.1.6" resolved "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz" integrity sha512-RG1ZkUT7iFJG9LSHr7KDuuMSlujfeTtMNIcInURxKAxhMtwQhI3NrQhz26gZQYlsYZQKzsnwtpKrFKj9K9Qu1A== +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + event-stream@=3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz" @@ -3161,7 +3323,7 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -3187,6 +3349,11 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + fastest-levenshtein@^1.0.16: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -3255,7 +3422,7 @@ find-up-simple@^1.0.0: resolved "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz" integrity sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw== -find-up@5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -3557,6 +3724,13 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" @@ -3626,6 +3800,11 @@ globals@^11.1.0: resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globalthis@^1.0.1, globalthis@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" @@ -3897,12 +4076,12 @@ ignore-walk@^6.0.4: dependencies: minimatch "^9.0.0" -ignore@^5.2.4: +ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== -import-fresh@^3.3.0: +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -4104,7 +4283,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4138,6 +4317,11 @@ is-obj@^2.0.0: resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" @@ -4438,6 +4622,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + json-stringify-nice@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" @@ -4509,6 +4698,14 @@ leven@^2.1.0: resolved "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz" integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA== +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + libnpmaccess@^8.0.1: version "8.0.5" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-8.0.5.tgz#ef14fecab8385669e91d6be27971ae448064211f" @@ -4703,6 +4900,11 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.uniqby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" @@ -4924,7 +5126,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -5126,6 +5328,11 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -5499,6 +5706,18 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + p-cancelable@^2.0.0: version "2.1.1" resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz" @@ -5908,6 +6127,11 @@ postcss-selector-parser@^6.0.10: cssesc "^3.0.0" util-deprecate "^1.0.2" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prettier@^3.2.5: version "3.2.5" resolved "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz" @@ -6892,7 +7116,7 @@ strip-final-newline@^4.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz#35a369ec2ac43df356e3edd5dcebb6429aa1fa5c" integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== -strip-json-comments@3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -7010,7 +7234,7 @@ text-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.4.0.tgz#a1cfcc50cf34da41bfd047cc744f804d1680ea34" integrity sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g== -text-table@~0.2.0: +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== @@ -7228,6 +7452,13 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" @@ -7534,6 +7765,11 @@ which@^4.0.0: dependencies: isexe "^3.1.1" +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"