From 156417a4ccc688e86b9be7750851c90309bcddae Mon Sep 17 00:00:00 2001 From: Enrico Del Fante Date: Mon, 13 Feb 2023 12:34:50 +0100 Subject: [PATCH] support standard fork choice format --- README.md | 2 +- package.json | 4 +- src/App.tsx | 537 +++++++++++++++++++++++++++++---------------------- yarn.lock | 275 +++----------------------- 4 files changed, 338 insertions(+), 480 deletions(-) diff --git a/README.md b/README.md index fe7b8c7..c4626de 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ProtoArray visualization tool -**Currently supporting TEKU data only** +**Currently supporting standard fork choice debug api format and old Teku, Prysm and Nimbus proprietary format** image diff --git a/package.json b/package.json index fa4dbc9..c1138e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "proto-vis", - "version": "0.1.2", + "version": "0.1.3", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.5", @@ -20,7 +20,7 @@ "react-range": "^1.8.14", "react-scripts": "5.0.1", "typescript": "^4.7.4", - "vis-network-react": "https://github.com/DinerIsmail/vis-network-react.git#2dd266e111b78d7f6f5424bd495a0eef8ab2dbf4", + "vis-network-react": "https://github.com/DinerIsmail/vis-network-react.git#7f5fd4bdd30f4a10cbc999d1e2ac4a431da97d33", "web-vitals": "^2.1.4" }, "overrides": { diff --git a/src/App.tsx b/src/App.tsx index d9945c9..45c288c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,15 +23,16 @@ const SLOT_PER_EPOCH: number = 32 const FAR_FUTURE_SLOT = '18446744073709551615' const DEFAULT_POLLING_PERIOD: number = 6000 -const DEFAULT_ENDPOINT: string = 'http://localhost:5051/teku/v1/debug/beacon/protoarray' +const DEFAULT_ENDPOINT: string = 'http://localhost:5051/eth/v1/debug/fork_choice' const DEFAULT_POLL_MAX_HISTORY: number = 50 const pollActiveAtStartup: boolean = false enum SourceType { - teku = 'Teku', - prysm = 'Prysm', - nimbus = 'Nimbus' + teku = 'Teku (22.12.0 or earlier)', + prysm = 'Prysm (deprecated)', + nimbus = 'Nimbus (deprecated)', + standard = 'Standard' } enum NodeSizeMode { @@ -80,7 +81,7 @@ type IdToNetworkNode = { const DEFAULT_NODE_SIZE_MODE: NodeSizeMode = NodeSizeMode.rootToHeadsCumulated -const DEFAULT_SOURCE_TYPE: SourceType = SourceType.teku +const DEFAULT_SOURCE_TYPE: SourceType = SourceType.standard const DEFAULT_DRAW_MISSING_SLOT_NODES: boolean = true const DEFAULT_PHYSICS: boolean = true @@ -234,6 +235,35 @@ function forkchoiceNodeToNetworkNode_Numbus(forkchoiceNode): NetworkNode | undef } } +function forkchoiceNodeToNetworkNode_Standard(forkchoiceNode): NetworkNode | undefined { + if (forkchoiceNode.slot === FAR_FUTURE_SLOT) return + let isMerge = forkchoiceNode.execution_block_hash !== '0x0000000000000000000000000000000000000000000000000000000000000000' + let label = isMerge ? '🐼 ' : '' + let cumulativeToRootWeight = BigNumber(forkchoiceNode.weight) + label += forkchoiceNode.block_root.substring(0, 8) + let validationStatus: ValidationStatus = forkchoiceNode.validity.toUpperCase() + return { + id: forkchoiceNode.block_root, + title: htmlTitle('single-click to copy blockRoot, double-click to copy all
' + JSON.stringify(forkchoiceNode, null, ' ') + '
'), + label: label, + level: parseInt(forkchoiceNode.slot), + value: 0, + color: validationStatusToColor(validationStatus, false), + forkchoiceNode: forkchoiceNode, + isMerge: isMerge, + isFirstPOS: false, + parentRoot: forkchoiceNode.parent_root, + isRoot: false, + isHead: false, + isMissingSlot: false, + validationStatus: validationStatus, + cumulativeToRootWeight: cumulativeToRootWeight, + cumulativeToHeadWeight: BigNumber(0), + weight: BigNumber(0), + childs: [] + } +} + function changeNodeSizeMode(node: ExistingNetworkNode, mode: NodeSizeMode) { @@ -287,6 +317,11 @@ function forkchoiceNodesToNetworkData(forckchoiceNodes, sourceType: SourceType, case SourceType.nimbus: rootBlockAttr = 'block_root' mapper = forkchoiceNodeToNetworkNode_Numbus + break; + case SourceType.standard: + rootBlockAttr = 'block_root' + mapper = forkchoiceNodeToNetworkNode_Standard + } forckchoiceNodes.forEach(forckchoiceNode => { @@ -379,6 +414,8 @@ function forkchoiceNodesToNetworkData(forckchoiceNodes, sourceType: SourceType, } function App() { + const [globalError, setGlobalError] = useState(); + const [showSettings, setShowSettings] = useState(false) const [forckchoiceDumpArray, setForckchoiceDumpArray] = useState([]) @@ -457,14 +494,18 @@ function App() { // render current data useEffect(() => { - if (forckchoiceDumpArray.length === 0 || currentForckchoiceDumpIdx >= forckchoiceDumpArray.length) return + try { + if (forckchoiceDumpArray.length === 0 || currentForckchoiceDumpIdx >= forckchoiceDumpArray.length) return - const { firstPOSNode, roots, heads, networkData } = forkchoiceNodesToNetworkData(forckchoiceDumpArray[currentForckchoiceDumpIdx].forkchoiceNodes, sourceType, nodeSizeMode, drawMissingSlotNodes) - setHeads(heads) - setRoots(roots) - setFirstPOSNode(firstPOSNode) - setData(networkData as any) - }, [currentForckchoiceDumpIdx, forckchoiceDumpArray, sourceType, nodeSizeMode, drawMissingSlotNodes, setData, setHeads, setRoots, setFirstPOSNode]) + const { firstPOSNode, roots, heads, networkData } = forkchoiceNodesToNetworkData(forckchoiceDumpArray[currentForckchoiceDumpIdx].forkchoiceNodes, sourceType, nodeSizeMode, drawMissingSlotNodes) + setHeads(heads) + setRoots(roots) + setFirstPOSNode(firstPOSNode) + setData(networkData as any) + } catch (e) { + setGlobalError("error loading data - verify source type in settings (" + e + ")"); + } + }, [currentForckchoiceDumpIdx, forckchoiceDumpArray, sourceType, nodeSizeMode, drawMissingSlotNodes, setData, setHeads, setRoots, setFirstPOSNode, setGlobalError]) // poll const togglePoll = useCallback((pollIsActive) => { @@ -637,7 +678,7 @@ function App() { // multiple protoarrays for (let dump of data) { dump.timestamp = moment(dump.timestamp) - if(dump.protoArray) { + if (dump.protoArray) { dump.forkchoiceNodes = dump.protoArray delete dump.protoArray } @@ -661,7 +702,7 @@ function App() { // multiple protoarrays for (let dump of data) { dump.timestamp = moment(dump.time) - if(dump.protoArray) { + if (dump.protoArray) { dump.forkchoiceNodes = dump.protoArray.filter(filter) delete dump.protoArray } @@ -674,6 +715,39 @@ function App() { } } + const parseStandardData = (input: any) => { + const filter = (node: any) => { return node.slot !== FAR_FUTURE_SLOT } + try { + let data: any = typeof input === 'string' ? JSON.parse(input) : input + if (!Array.isArray(data)) { + // single protoarray + return [{ + timestamp: moment(data.time), + justifiedCheckpoint: data.justified_checkpoint, + finalizedCheckpoint: data.finalized_checkpoint, + forkchoiceNodes: data.fork_choice_nodes.filter(filter) + } as ForckchoiceDump] + } else { + // multiple protoarrays + for (let dump of data) { + dump.timestamp = moment(dump.time) + if (dump.protoArray) { + dump.forkchoiceNodes = dump.fork_choice_nodes.filter(filter) + dump.justifiedCheckpoint = dump.justified_checkpoint + dump.finalizedCheckpoint = dump.finalized_checkpoint + delete dump.justified_checkpoint + delete dump.finalized_checkpoint + delete dump.protoArray + } + } + return data + } + } catch (e) { + alert("**Not valid Nimbus JSON file!**\nerror: " + e) + return [] + } + } + const parsePrysmData = (input: any): ForckchoiceDump[] => { try { let data: any = typeof input === 'string' ? JSON.parse(input) : input @@ -684,7 +758,7 @@ function App() { // multiple protoarrays for (let sample of data) { sample.timestamp = moment() - if(sample.forkchoice?.forkchoice_nodes) { + if (sample.forkchoice?.forkchoice_nodes) { sample.forkchoiceNodes = sample.forkchoice?.forkchoice_nodes delete sample.forkchoice.forkchoice_nodes } @@ -710,6 +784,9 @@ function App() { break; case SourceType.nimbus: data = parseNimbusData(fileReader.result) + break; + case SourceType.standard: + data = parseStandardData(fileReader.result) } if (data !== undefined) setForckchoiceDumpArray(data) @@ -870,238 +947,244 @@ function App() { }, [network, networkNodes, heads, roots, firstPOSNode]) return ( -
- - -

-

- -

-

- -

-

- -

-

- -

-

- -

-

- -
-
-
- - - - -
{'Heads: ' + heads.length}
- - - Cycle heads - -
- Node Size mode - -
- - readFileOnUpload(e.target.files[0])} ref={inputFile} style={{ display: 'none' }} /> -
-
- -
-
-
+ <> + {globalError &&

ASD: {globalError}

+
} + {!globalError && +
+ + +

+

-
-
+

+

+ +

+

+ +

+

+ +

+

-
-
+

+

-
-
{forckchoiceDumpArray?.length > 0 ? forckchoiceDumpArray[0].timestamp.toLocaleString() : 'N/A'}
-
- - ( -
+
+
+ + + + +
{'Heads: ' + heads.length}
+ + + Cycle heads + +
+ Node Size mode + +
+ + readFileOnUpload(e.target.files[0])} ref={inputFile} style={{ display: 'none' }} /> +
+
+ -
- {children} -
+ events={events} + getNodes={getNodes} + getNetwork={getNetwork} + /> +
+
+
+ +
+
+
- )} - renderThumb={({ props, isDragged }) => ( -
- {forckchoiceDumpArray.length > 0 && +
+ +
+
{forckchoiceDumpArray?.length > 0 ? forckchoiceDumpArray[0].timestamp.toLocaleString() : 'N/A'}
+
+ + ( +
+
+ {children} +
+
+ )} + renderThumb={({ props, isDragged }) => (
- {forckchoiceDumpArray[currentForckchoiceDumpIdx]?.timestamp.local().format('HH:mm:ss')} -
} -
-
- )} - renderMark={({ props, index }) => ( -
- )} - min={0} max={Math.max(1, forckchoiceDumpArray.length - 1)} - step={1} - values={[currentForckchoiceDumpIdx]} - onChange={handleSlide} /> + {forckchoiceDumpArray.length > 0 && +
+ {forckchoiceDumpArray[currentForckchoiceDumpIdx]?.timestamp.local().format('HH:mm:ss')} +
} +
+
+ )} + renderMark={({ props, index }) => ( +
+ )} + min={0} max={Math.max(1, forckchoiceDumpArray.length - 1)} + step={1} + values={[currentForckchoiceDumpIdx]} + onChange={handleSlide} /> -
+
-
{forckchoiceDumpArray?.length > 0 ? forckchoiceDumpArray[forckchoiceDumpArray.length - 1].timestamp.toLocaleString() : 'N/A'}
+
{forckchoiceDumpArray?.length > 0 ? forckchoiceDumpArray[forckchoiceDumpArray.length - 1].timestamp.toLocaleString() : 'N/A'}
+
+
-
-
+ } + ) } diff --git a/yarn.lock b/yarn.lock index 3cee61a..498c870 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2286,11 +2286,6 @@ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@zeit/schemas@2.21.0": - version "2.21.0" - resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.21.0.tgz#cd242c6551ffb51830049d68d9743ab65b45b820" - integrity sha512-/J4WBTpWtQ4itN1rb3ao8LfClmVcmz2pO6oYb7Qd4h7VSqUhIbJIvrykz9Ew1WMg6eFWsKdsMHc5uPbFxqlCpg== - abab@^2.0.3, abab@^2.0.5: version "2.0.6" resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" @@ -2385,16 +2380,6 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" -ajv@8.11.0, ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0: - version "8.11.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" @@ -2405,12 +2390,15 @@ ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-align@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== +ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0: + version "8.11.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== dependencies: - string-width "^4.1.0" + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: version "4.3.2" @@ -2453,11 +2441,6 @@ ansi-styles@^5.0.0: resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3" - integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ== - anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" @@ -2466,12 +2449,7 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -arch@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - -arg@5.0.2, arg@^5.0.2: +arg@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== @@ -2821,20 +2799,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -boxen@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-7.0.0.tgz#9e5f8c26e716793fc96edcf7cf754cdf5e3fbf32" - integrity sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg== - dependencies: - ansi-align "^3.0.1" - camelcase "^7.0.0" - chalk "^5.0.1" - cli-boxes "^3.0.0" - string-width "^5.1.2" - type-fest "^2.13.0" - widest-line "^4.0.1" - wrap-ansi "^8.0.1" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -2935,11 +2899,6 @@ camelcase@^6.2.0, camelcase@^6.2.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelcase@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.0.tgz#fd112621b212126741f998d614cbc2a8623fd174" - integrity sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ== - caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" @@ -2960,18 +2919,6 @@ case-sensitive-paths-webpack-plugin@^2.4.0: resolved "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz" integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== -chalk-template@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" - integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== - dependencies: - chalk "^4.1.2" - -chalk@5.0.1, chalk@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" - integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== - chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -3054,20 +3001,6 @@ clean-css@^5.2.2: dependencies: source-map "~0.6.0" -cli-boxes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" - integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== - -clipboardy@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-3.0.0.tgz#f3876247404d334c9ed01b6f269c11d09a5e3092" - integrity sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg== - dependencies: - arch "^2.2.0" - execa "^5.1.1" - is-wsl "^2.2.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" @@ -3174,7 +3107,7 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.43.0 < 2" -compression@1.7.4, compression@^1.7.4: +compression@^1.7.4: version "1.7.4" resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== @@ -3202,11 +3135,6 @@ connect-history-api-fallback@^2.0.0: resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz" integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== - content-disposition@0.5.4: version "0.5.4" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" @@ -3535,11 +3463,6 @@ dedent@^0.7.0: resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-extend@^0.6.0: - version "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, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" @@ -3768,11 +3691,6 @@ duplexer@^0.1.2: resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" 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.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" @@ -4212,7 +4130,7 @@ events@^3.2.0: resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -execa@^5.0.0, execa@^5.1.1: +execa@^5.0.0: version "5.1.1" resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -4310,13 +4228,6 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== - dependencies: - punycode "^1.3.2" - fastq@^1.6.0: version "1.13.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" @@ -4959,7 +4870,7 @@ inherits@2.0.3: resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -ini@^1.3.5, ini@~1.3.0: +ini@^1.3.5: version "1.3.8" resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -5088,11 +4999,6 @@ is-plain-obj@^3.0.0: resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== -is-port-reachable@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-port-reachable/-/is-port-reachable-4.0.0.tgz#dac044091ef15319c8ab2f34604d8794181f8c2d" - integrity sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig== - is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" @@ -6096,18 +6002,6 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" @@ -6551,11 +6445,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" @@ -6571,11 +6460,6 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -7259,11 +7143,6 @@ psl@^1.1.33: resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" @@ -7305,11 +7184,6 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== - range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" @@ -7325,16 +7199,6 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.0.1, rc@^1.1.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-app-polyfill@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz" @@ -7605,21 +7469,6 @@ regexpu-core@^5.1.0: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.0.0" -registry-auth-token@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA== - dependencies: - rc "^1.0.1" - regjsgen@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" @@ -7760,7 +7609,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -7901,20 +7750,6 @@ serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" -serve-handler@6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - serve-index@^1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" @@ -7938,23 +7773,6 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" -serve@^14.0.1: - version "14.0.1" - resolved "https://registry.yarnpkg.com/serve/-/serve-14.0.1.tgz#5b6ffc17e18e1a8e963cc392958d7df13e1ef9fd" - integrity sha512-tNGwxl27FwA8TbmMQqN0jTaSx8/trL532qZsJHX1VdiEIjjtMJHCs7AFS6OvtC7cTHOvmjXqt5yczejU6CV2Xg== - dependencies: - "@zeit/schemas" "2.21.0" - ajv "8.11.0" - arg "5.0.2" - boxen "7.0.0" - chalk "5.0.1" - chalk-template "0.4.0" - clipboardy "3.0.0" - compression "1.7.4" - is-port-reachable "4.0.0" - serve-handler "6.1.3" - update-check "1.5.4" - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" @@ -8154,15 +7972,6 @@ 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.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.7: version "4.0.7" resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz" @@ -8264,11 +8073,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - style-loader@^3.3.1: version "3.3.1" resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz" @@ -8575,11 +8379,6 @@ type-fest@^0.21.3: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-fest@^2.13.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" - integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== - type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" @@ -8673,14 +8472,6 @@ update-browserslist-db@^1.0.5: escalade "^3.1.1" picocolors "^1.0.0" -update-check@1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.4.tgz#5b508e259558f1ad7dbc8b4b0457d4c9d28c8743" - integrity sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ== - dependencies: - registry-auth-token "3.3.2" - registry-url "3.1.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" @@ -8737,30 +8528,30 @@ vary@~1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -vis-data@7.1.2: - version "7.1.2" - resolved "https://registry.npmjs.org/vis-data/-/vis-data-7.1.2.tgz" - integrity sha512-RPSegFxEcnp3HUEJSzhS2vBdbJ2PSsrYYuhRlpHp2frO/MfRtTYbIkkLZmPkA/Sg3pPfBlR235gcoKbtdm4mbw== +vis-data@7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/vis-data/-/vis-data-7.1.4.tgz#90e5e796a79e1901de14c0808fb32a1a0735c1dc" + integrity sha512-usy+ePX1XnArNvJ5BavQod7YRuGQE1pjFl+pu7IS6rCom2EBoG0o1ZzCqf3l5US6MW51kYkLR+efxRbnjxNl7w== -"vis-network-react@https://github.com/DinerIsmail/vis-network-react.git#2dd266e111b78d7f6f5424bd495a0eef8ab2dbf4": +"vis-network-react@https://github.com/DinerIsmail/vis-network-react.git#7f5fd4bdd30f4a10cbc999d1e2ac4a431da97d33": version "1.3.6" - resolved "git+ssh://git@github.com/DinerIsmail/vis-network-react.git#2dd266e111b78d7f6f5424bd495a0eef8ab2dbf4" + resolved "https://github.com/DinerIsmail/vis-network-react.git#7f5fd4bdd30f4a10cbc999d1e2ac4a431da97d33" dependencies: lodash "4.17.20" uuid "8.3.2" - vis-data "7.1.2" + vis-data "7.1.4" vis-network "9.1.2" - vis-util "5.0.2" + vis-util "5.0.3" vis-network@9.1.2: version "9.1.2" resolved "https://registry.npmjs.org/vis-network/-/vis-network-9.1.2.tgz" integrity sha512-BdapguKg7sk3NvdZaDsM7T6rNhOBFz0/F4ZScxctK4klRzQPLQPTEcmbioXaZhMkkgWymzBR3lFCxL1q+eYyAw== -vis-util@5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/vis-util/-/vis-util-5.0.2.tgz" - integrity sha512-oPDmPc4o0uQLoKpKai2XD1DjrhYsA7MRz75Wx9KmfX84e9LLgsbno7jVL5tR0K9eNVQkD6jf0Ei8NtbBHDkF1A== +vis-util@5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/vis-util/-/vis-util-5.0.3.tgz#6a9d67c6ed92f2bfa67e50c20166bb5f59ac07bf" + integrity sha512-Wf9STUcFrDzK4/Zr7B6epW2Kvm3ORNWF+WiwEz2dpf5RdWkLUXFSbLcuB88n1W6tCdFwVN+v3V4/Xmn9PeL39g== w3c-hr-time@^1.0.2: version "1.0.2" @@ -9004,13 +8795,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -widest-line@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" - integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== - dependencies: - string-width "^5.0.1" - word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" @@ -9194,15 +8978,6 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" - integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== - 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.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"