add checkboxes for checks and add info for unavailable upstreams
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
VITE_DEV_SERVER_HOST=172.16.4.220
|
||||||
|
VITE_DEV_SERVER_PORT=4000
|
||||||
@@ -40,6 +40,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["eslint-plugin-react-hooks", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:7.1.1"],\
|
["eslint-plugin-react-hooks", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:7.1.1"],\
|
||||||
["eslint-plugin-react-refresh", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:0.5.2"],\
|
["eslint-plugin-react-refresh", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:0.5.2"],\
|
||||||
["globals", "npm:17.6.0"],\
|
["globals", "npm:17.6.0"],\
|
||||||
|
["jspdf", "npm:4.2.1"],\
|
||||||
["network-tools", "workspace:."],\
|
["network-tools", "workspace:."],\
|
||||||
["react", "npm:19.2.6"],\
|
["react", "npm:19.2.6"],\
|
||||||
["react-dom", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:19.2.6"],\
|
["react-dom", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:19.2.6"],\
|
||||||
@@ -215,6 +216,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@babel/runtime", [\
|
||||||
|
["npm:7.29.7", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/@babel-runtime-npm-7.29.7-423e8cd4b6-10c0.zip/node_modules/@babel/runtime/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@babel/runtime", "npm:7.29.7"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@babel/template", [\
|
["@babel/template", [\
|
||||||
["npm:7.28.6", {\
|
["npm:7.28.6", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/@babel-template-npm-7.28.6-bff3bc3923-10c0.zip/node_modules/@babel/template/",\
|
"packageLocation": "../../.yarn/berry/cache/@babel-template-npm-7.28.6-bff3bc3923-10c0.zip/node_modules/@babel/template/",\
|
||||||
@@ -769,6 +779,24 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/pako", [\
|
||||||
|
["npm:2.0.4", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/@types-pako-npm-2.0.4-ac100d59c9-10c0.zip/node_modules/@types/pako/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/pako", "npm:2.0.4"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["@types/raf", [\
|
||||||
|
["npm:3.4.3", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/@types-raf-npm-3.4.3-afd3c6d2bc-10c0.zip/node_modules/@types/raf/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/raf", "npm:3.4.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@types/react", [\
|
["@types/react", [\
|
||||||
["npm:19.2.15", {\
|
["npm:19.2.15", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/@types-react-npm-19.2.15-767accf7c6-10c0.zip/node_modules/@types/react/",\
|
"packageLocation": "../../.yarn/berry/cache/@types-react-npm-19.2.15-767accf7c6-10c0.zip/node_modules/@types/react/",\
|
||||||
@@ -799,6 +827,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/trusted-types", [\
|
||||||
|
["npm:2.0.7", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/@types-trusted-types-npm-2.0.7-a07fc44f59-10c0.zip/node_modules/@types/trusted-types/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/trusted-types", "npm:2.0.7"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@vitejs/plugin-react", [\
|
["@vitejs/plugin-react", [\
|
||||||
["npm:6.0.2", {\
|
["npm:6.0.2", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/@vitejs-plugin-react-npm-6.0.2-0f2620b1d7-10c0.zip/node_modules/@vitejs/plugin-react/",\
|
"packageLocation": "../../.yarn/berry/cache/@vitejs-plugin-react-npm-6.0.2-0f2620b1d7-10c0.zip/node_modules/@vitejs/plugin-react/",\
|
||||||
@@ -952,6 +989,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["base64-arraybuffer", [\
|
||||||
|
["npm:1.0.2", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/base64-arraybuffer-npm-1.0.2-18f4899892-10c0.zip/node_modules/base64-arraybuffer/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["base64-arraybuffer", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["baseline-browser-mapping", [\
|
["baseline-browser-mapping", [\
|
||||||
["npm:2.10.31", {\
|
["npm:2.10.31", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/baseline-browser-mapping-npm-2.10.31-11b5c14e52-10c0.zip/node_modules/baseline-browser-mapping/",\
|
"packageLocation": "../../.yarn/berry/cache/baseline-browser-mapping-npm-2.10.31-11b5c14e52-10c0.zip/node_modules/baseline-browser-mapping/",\
|
||||||
@@ -1005,6 +1051,23 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["canvg", [\
|
||||||
|
["npm:3.0.11", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/canvg-npm-3.0.11-0944b07da2-10c0.zip/node_modules/canvg/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@babel/runtime", "npm:7.29.7"],\
|
||||||
|
["@types/raf", "npm:3.4.3"],\
|
||||||
|
["canvg", "npm:3.0.11"],\
|
||||||
|
["core-js", "npm:3.49.0"],\
|
||||||
|
["raf", "npm:3.4.1"],\
|
||||||
|
["regenerator-runtime", "npm:0.13.11"],\
|
||||||
|
["rgbcolor", "npm:1.0.1"],\
|
||||||
|
["stackblur-canvas", "npm:2.7.0"],\
|
||||||
|
["svg-pathdata", "npm:6.0.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["chownr", [\
|
["chownr", [\
|
||||||
["npm:3.0.0", {\
|
["npm:3.0.0", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/chownr-npm-3.0.0-5275e85d25-10c0.zip/node_modules/chownr/",\
|
"packageLocation": "../../.yarn/berry/cache/chownr-npm-3.0.0-5275e85d25-10c0.zip/node_modules/chownr/",\
|
||||||
@@ -1033,6 +1096,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["core-js", [\
|
||||||
|
["npm:3.49.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/core-js-npm-3.49.0-0a974f48cc-10c0.zip/node_modules/core-js/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["core-js", "npm:3.49.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["cross-spawn", [\
|
["cross-spawn", [\
|
||||||
["npm:7.0.6", {\
|
["npm:7.0.6", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/cross-spawn-npm-7.0.6-264bddf921-10c0.zip/node_modules/cross-spawn/",\
|
"packageLocation": "../../.yarn/berry/cache/cross-spawn-npm-7.0.6-264bddf921-10c0.zip/node_modules/cross-spawn/",\
|
||||||
@@ -1045,6 +1117,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["css-line-break", [\
|
||||||
|
["npm:2.1.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/css-line-break-npm-2.1.0-a1fd810d69-10c0.zip/node_modules/css-line-break/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["css-line-break", "npm:2.1.0"],\
|
||||||
|
["utrie", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["csstype", [\
|
["csstype", [\
|
||||||
["npm:3.2.3", {\
|
["npm:3.2.3", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/csstype-npm-3.2.3-741053244e-10c0.zip/node_modules/csstype/",\
|
"packageLocation": "../../.yarn/berry/cache/csstype-npm-3.2.3-741053244e-10c0.zip/node_modules/csstype/",\
|
||||||
@@ -1104,6 +1186,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["dompurify", [\
|
||||||
|
["npm:3.4.7", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/dompurify-npm-3.4.7-440dacdb20-10c0.zip/node_modules/dompurify/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/trusted-types", "npm:2.0.7"],\
|
||||||
|
["dompurify", "npm:3.4.7"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["dunder-proto", [\
|
["dunder-proto", [\
|
||||||
["npm:1.0.1", {\
|
["npm:1.0.1", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/dunder-proto-npm-1.0.1-90eb6829db-10c0.zip/node_modules/dunder-proto/",\
|
"packageLocation": "../../.yarn/berry/cache/dunder-proto-npm-1.0.1-90eb6829db-10c0.zip/node_modules/dunder-proto/",\
|
||||||
@@ -1432,6 +1524,18 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["fast-png", [\
|
||||||
|
["npm:6.4.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/fast-png-npm-6.4.0-7871b2b5a5-10c0.zip/node_modules/fast-png/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/pako", "npm:2.0.4"],\
|
||||||
|
["fast-png", "npm:6.4.0"],\
|
||||||
|
["iobuffer", "npm:5.4.0"],\
|
||||||
|
["pako", "npm:2.1.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["fdir", [\
|
["fdir", [\
|
||||||
["npm:6.5.0", {\
|
["npm:6.5.0", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/fdir-npm-6.5.0-8814a0dec7-10c0.zip/node_modules/fdir/",\
|
"packageLocation": "../../.yarn/berry/cache/fdir-npm-6.5.0-8814a0dec7-10c0.zip/node_modules/fdir/",\
|
||||||
@@ -1454,6 +1558,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["fflate", [\
|
||||||
|
["npm:0.8.3", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/fflate-npm-0.8.3-35acaff861-10c0.zip/node_modules/fflate/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["fflate", "npm:0.8.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["file-entry-cache", [\
|
["file-entry-cache", [\
|
||||||
["npm:8.0.0", {\
|
["npm:8.0.0", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/file-entry-cache-npm-8.0.0-5b09d19a83-10c0.zip/node_modules/file-entry-cache/",\
|
"packageLocation": "../../.yarn/berry/cache/file-entry-cache-npm-8.0.0-5b09d19a83-10c0.zip/node_modules/file-entry-cache/",\
|
||||||
@@ -1686,6 +1799,17 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["html2canvas", [\
|
||||||
|
["npm:1.4.1", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/html2canvas-npm-1.4.1-fa13983145-10c0.zip/node_modules/html2canvas/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["css-line-break", "npm:2.1.0"],\
|
||||||
|
["html2canvas", "npm:1.4.1"],\
|
||||||
|
["text-segmentation", "npm:1.0.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["https-proxy-agent", [\
|
["https-proxy-agent", [\
|
||||||
["npm:5.0.1", {\
|
["npm:5.0.1", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/https-proxy-agent-npm-5.0.1-42d65f358e-10c0.zip/node_modules/https-proxy-agent/",\
|
"packageLocation": "../../.yarn/berry/cache/https-proxy-agent-npm-5.0.1-42d65f358e-10c0.zip/node_modules/https-proxy-agent/",\
|
||||||
@@ -1715,6 +1839,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["iobuffer", [\
|
||||||
|
["npm:5.4.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/iobuffer-npm-5.4.0-2cf4f91275-10c0.zip/node_modules/iobuffer/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["iobuffer", "npm:5.4.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["is-extglob", [\
|
["is-extglob", [\
|
||||||
["npm:2.1.1", {\
|
["npm:2.1.1", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/is-extglob-npm-2.1.1-0870ea68b5-10c0.zip/node_modules/is-extglob/",\
|
"packageLocation": "../../.yarn/berry/cache/is-extglob-npm-2.1.1-0870ea68b5-10c0.zip/node_modules/is-extglob/",\
|
||||||
@@ -1804,6 +1937,22 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["jspdf", [\
|
||||||
|
["npm:4.2.1", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/jspdf-npm-4.2.1-4a36558b77-10c0.zip/node_modules/jspdf/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@babel/runtime", "npm:7.29.7"],\
|
||||||
|
["canvg", "npm:3.0.11"],\
|
||||||
|
["core-js", "npm:3.49.0"],\
|
||||||
|
["dompurify", "npm:3.4.7"],\
|
||||||
|
["fast-png", "npm:6.4.0"],\
|
||||||
|
["fflate", "npm:0.8.3"],\
|
||||||
|
["html2canvas", "npm:1.4.1"],\
|
||||||
|
["jspdf", "npm:4.2.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["keyv", [\
|
["keyv", [\
|
||||||
["npm:4.5.4", {\
|
["npm:4.5.4", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/keyv-npm-4.5.4-4c8e2cf7f7-10c0.zip/node_modules/keyv/",\
|
"packageLocation": "../../.yarn/berry/cache/keyv-npm-4.5.4-4c8e2cf7f7-10c0.zip/node_modules/keyv/",\
|
||||||
@@ -2065,6 +2214,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["eslint-plugin-react-hooks", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:7.1.1"],\
|
["eslint-plugin-react-hooks", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:7.1.1"],\
|
||||||
["eslint-plugin-react-refresh", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:0.5.2"],\
|
["eslint-plugin-react-refresh", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:0.5.2"],\
|
||||||
["globals", "npm:17.6.0"],\
|
["globals", "npm:17.6.0"],\
|
||||||
|
["jspdf", "npm:4.2.1"],\
|
||||||
["network-tools", "workspace:."],\
|
["network-tools", "workspace:."],\
|
||||||
["react", "npm:19.2.6"],\
|
["react", "npm:19.2.6"],\
|
||||||
["react-dom", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:19.2.6"],\
|
["react-dom", "virtual:1bef36b42a34c769545e238167cf96a97395f203a4be67468ec9e7c364af0538d9297399544e3b7eb227555c0667de3f416c95893ffd698b011448edf0cd18b9#npm:19.2.6"],\
|
||||||
@@ -2147,6 +2297,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["pako", [\
|
||||||
|
["npm:2.1.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/pako-npm-2.1.0-78df11948c-10c0.zip/node_modules/pako/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["pako", "npm:2.1.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["path-exists", [\
|
["path-exists", [\
|
||||||
["npm:4.0.0", {\
|
["npm:4.0.0", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/path-exists-npm-4.0.0-e9e4f63eb0-10c0.zip/node_modules/path-exists/",\
|
"packageLocation": "../../.yarn/berry/cache/path-exists-npm-4.0.0-e9e4f63eb0-10c0.zip/node_modules/path-exists/",\
|
||||||
@@ -2165,6 +2324,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["performance-now", [\
|
||||||
|
["npm:2.1.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/performance-now-npm-2.1.0-45e3ce7e49-10c0.zip/node_modules/performance-now/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["performance-now", "npm:2.1.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["picocolors", [\
|
["picocolors", [\
|
||||||
["npm:1.1.1", {\
|
["npm:1.1.1", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/picocolors-npm-1.1.1-4fede47cf1-10c0.zip/node_modules/picocolors/",\
|
"packageLocation": "../../.yarn/berry/cache/picocolors-npm-1.1.1-4fede47cf1-10c0.zip/node_modules/picocolors/",\
|
||||||
@@ -2231,6 +2399,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["raf", [\
|
||||||
|
["npm:3.4.1", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/raf-npm-3.4.1-c25d48d76e-10c0.zip/node_modules/raf/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["performance-now", "npm:2.1.0"],\
|
||||||
|
["raf", "npm:3.4.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["react", [\
|
["react", [\
|
||||||
["npm:19.2.6", {\
|
["npm:19.2.6", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/react-npm-19.2.6-f326db5d50-10c0.zip/node_modules/react/",\
|
"packageLocation": "../../.yarn/berry/cache/react-npm-19.2.6-f326db5d50-10c0.zip/node_modules/react/",\
|
||||||
@@ -2263,6 +2441,24 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["regenerator-runtime", [\
|
||||||
|
["npm:0.13.11", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/regenerator-runtime-npm-0.13.11-90bf536060-10c0.zip/node_modules/regenerator-runtime/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["regenerator-runtime", "npm:0.13.11"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["rgbcolor", [\
|
||||||
|
["npm:1.0.1", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/rgbcolor-npm-1.0.1-5d8cee2258-10c0.zip/node_modules/rgbcolor/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["rgbcolor", "npm:1.0.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["rolldown", [\
|
["rolldown", [\
|
||||||
["npm:1.0.1", {\
|
["npm:1.0.1", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/rolldown-npm-1.0.1-8adafc3459-10c0.zip/node_modules/rolldown/",\
|
"packageLocation": "../../.yarn/berry/cache/rolldown-npm-1.0.1-8adafc3459-10c0.zip/node_modules/rolldown/",\
|
||||||
@@ -2366,6 +2562,24 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["stackblur-canvas", [\
|
||||||
|
["npm:2.7.0", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/stackblur-canvas-npm-2.7.0-69df5c1ce4-10c0.zip/node_modules/stackblur-canvas/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["stackblur-canvas", "npm:2.7.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["svg-pathdata", [\
|
||||||
|
["npm:6.0.3", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/svg-pathdata-npm-6.0.3-b9a9612535-10c0.zip/node_modules/svg-pathdata/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["svg-pathdata", "npm:6.0.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["tar", [\
|
["tar", [\
|
||||||
["npm:7.5.15", {\
|
["npm:7.5.15", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/tar-npm-7.5.15-f915901510-10c0.zip/node_modules/tar/",\
|
"packageLocation": "../../.yarn/berry/cache/tar-npm-7.5.15-f915901510-10c0.zip/node_modules/tar/",\
|
||||||
@@ -2380,6 +2594,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["text-segmentation", [\
|
||||||
|
["npm:1.0.3", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/text-segmentation-npm-1.0.3-634201c349-10c0.zip/node_modules/text-segmentation/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["text-segmentation", "npm:1.0.3"],\
|
||||||
|
["utrie", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["tinyglobby", [\
|
["tinyglobby", [\
|
||||||
["npm:0.2.16", {\
|
["npm:0.2.16", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/tinyglobby-npm-0.2.16-102914a73b-10c0.zip/node_modules/tinyglobby/",\
|
"packageLocation": "../../.yarn/berry/cache/tinyglobby-npm-0.2.16-102914a73b-10c0.zip/node_modules/tinyglobby/",\
|
||||||
@@ -2453,6 +2677,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["utrie", [\
|
||||||
|
["npm:1.0.2", {\
|
||||||
|
"packageLocation": "../../.yarn/berry/cache/utrie-npm-1.0.2-909cbd985c-10c0.zip/node_modules/utrie/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["base64-arraybuffer", "npm:1.0.2"],\
|
||||||
|
["utrie", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["vite", [\
|
["vite", [\
|
||||||
["npm:8.0.13", {\
|
["npm:8.0.13", {\
|
||||||
"packageLocation": "../../.yarn/berry/cache/vite-npm-8.0.13-f2ad0579c2-10c0.zip/node_modules/vite/",\
|
"packageLocation": "../../.yarn/berry/cache/vite-npm-8.0.13-f2ad0579c2-10c0.zip/node_modules/vite/",\
|
||||||
|
|||||||
Binary file not shown.
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
|
"jspdf": "^4.2.1",
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
"socket.io-client": "^4.6.1"
|
"socket.io-client": "^4.6.1"
|
||||||
|
|||||||
+170
-2
@@ -117,6 +117,36 @@ body {
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.results-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-export {
|
||||||
|
background: #fff;
|
||||||
|
color: var(--accent);
|
||||||
|
border: 1.5px solid var(--accent);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 6px 14px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
.btn-export:hover:not(:disabled) {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.btn-export:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── URL input ──────────────────────────────────────────────────────────────── */
|
/* ── URL input ──────────────────────────────────────────────────────────────── */
|
||||||
.host-editor { display: flex; flex-direction: column; gap: 8px; }
|
.host-editor { display: flex; flex-direction: column; gap: 8px; }
|
||||||
|
|
||||||
@@ -139,6 +169,70 @@ body {
|
|||||||
}
|
}
|
||||||
.url-input::placeholder { color: var(--muted); }
|
.url-input::placeholder { color: var(--muted); }
|
||||||
|
|
||||||
|
/* ── Checks ─────────────────────────────────────────────────────────────────── */
|
||||||
|
.checks-editor {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checks-toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checks-action {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--border2);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--muted);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.checks-action:hover:not(:disabled) {
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.checks-action:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checks-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 10px 12px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-item input {
|
||||||
|
accent-color: var(--accent);
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-item input:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Run button ─────────────────────────────────────────────────────────────── */
|
/* ── Run button ─────────────────────────────────────────────────────────────── */
|
||||||
.btn-run {
|
.btn-run {
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
@@ -380,11 +474,23 @@ pre {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-group-names {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-host-sub {
|
.server-host-sub {
|
||||||
font-size: 0.75rem;
|
font-family: var(--font-mono);
|
||||||
opacity: 0.6;
|
font-size: 10px;
|
||||||
|
color: var(--muted);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-status-dot {
|
.server-status-dot {
|
||||||
@@ -398,6 +504,68 @@ pre {
|
|||||||
|
|
||||||
.group-ok { border-color: #22c55e44; }
|
.group-ok { border-color: #22c55e44; }
|
||||||
.group-err { border-color: #ef444444; }
|
.group-err { border-color: #ef444444; }
|
||||||
|
.group-unavailable { border-color: #ef4444; border-left: 3px solid var(--err); }
|
||||||
|
|
||||||
|
.server-unavailable-badge {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
color: var(--err);
|
||||||
|
background: #fdeaee;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-unavailable {
|
||||||
|
border-left: 3px solid var(--err);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-unavailable-block {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-unavailable {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-head strong {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-status {
|
||||||
|
font-size: 10px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--err);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-line {
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 1.3;
|
||||||
|
color: var(--muted);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-meta {
|
||||||
|
color: #6a7490;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream-error {
|
||||||
|
color: var(--err);
|
||||||
|
}
|
||||||
|
|
||||||
.server-group-results {
|
.server-group-results {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|||||||
+329
-40
@@ -1,14 +1,29 @@
|
|||||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { jsPDF } from "jspdf";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
|
|
||||||
const BASE = (import.meta.env.BASE_URL ?? "/").replace(/\/$/, "");
|
const BASE = (import.meta.env.BASE_URL ?? "/").replace(/\/$/, "");
|
||||||
const API_BASE = `${BASE}/api`;
|
const IS_DEV = import.meta.env.DEV;
|
||||||
const SOCKET_IO_PATH = `${BASE}/socket.io`;
|
const DEV_HOST = import.meta.env.VITE_DEV_SERVER_HOST ?? "172.16.4.220";
|
||||||
|
const DEV_PORT = import.meta.env.VITE_DEV_SERVER_PORT ?? "4000";
|
||||||
|
const DEV_SERVER_URL = `http://${DEV_HOST}:${DEV_PORT}`;
|
||||||
|
|
||||||
|
const API_BASE = IS_DEV ? `${DEV_SERVER_URL}/api` : `${BASE}/api`;
|
||||||
|
const SOCKET_URL = IS_DEV ? DEV_SERVER_URL : undefined;
|
||||||
|
const SOCKET_IO_PATH = IS_DEV ? "/socket.io" : `${BASE}/socket.io`;
|
||||||
|
|
||||||
const DEFAULT_HOSTS = [{ url: "", method: "GET" }];
|
const DEFAULT_HOSTS = [{ url: "", method: "GET" }];
|
||||||
|
|
||||||
|
const CHECK_OPTIONS = [
|
||||||
|
{ id: "ping", label: "Ping" },
|
||||||
|
{ id: "curl", label: "Curl" },
|
||||||
|
{ id: "traceroute", label: "Traceroute" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const DEFAULT_CHECKS = CHECK_OPTIONS.map((c) => c.id);
|
||||||
|
|
||||||
function getToolBody(result) {
|
function getToolBody(result) {
|
||||||
if (!result) return null;
|
if (!result) return null;
|
||||||
const d = result.data;
|
const d = result.data;
|
||||||
@@ -40,6 +55,122 @@ function isResultError(result) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isUpstreamUnavailable(result) {
|
||||||
|
if (!result || result.type !== "error") return false;
|
||||||
|
if (result.code === "ECONNREFUSED") return true;
|
||||||
|
return /ECONNREFUSED|ENOTFOUND|ETIMEDOUT|EHOSTUNREACH/i.test(
|
||||||
|
result.error || "",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isToolError(result) {
|
||||||
|
return (
|
||||||
|
result?.type === "error" &&
|
||||||
|
(result.endpoint || result.serverName || result.host)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendResult(prev, entry, index) {
|
||||||
|
if (typeof index === "number") {
|
||||||
|
const next = prev.length ? [...prev] : [];
|
||||||
|
while (next.length <= index) next.push(null);
|
||||||
|
next[index] = entry;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
if (!prev.length) return [entry];
|
||||||
|
const emptyIdx = prev.findIndex((r) => r == null);
|
||||||
|
if (emptyIdx >= 0) {
|
||||||
|
const next = [...prev];
|
||||||
|
next[emptyIdx] = entry;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
return [...prev, entry];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getResultOutput(result) {
|
||||||
|
if (!result) return "";
|
||||||
|
if (result.type === "error") return result.error || "Error";
|
||||||
|
const body = getToolBody(result);
|
||||||
|
if (!body) return "";
|
||||||
|
const parts = [body.stdout, body.trace, body.body].filter(Boolean);
|
||||||
|
if (parts.length) {
|
||||||
|
const text = parts.join("\n");
|
||||||
|
return body.stderr ? `${text}\n\nstderr:\n${body.stderr}` : text;
|
||||||
|
}
|
||||||
|
if (body.stderr) return body.stderr;
|
||||||
|
return JSON.stringify(body, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportResultsToPdf(groupedResults, targetUrl) {
|
||||||
|
const doc = new jsPDF({ unit: "pt", format: "a4" });
|
||||||
|
const margin = 40;
|
||||||
|
const maxWidth = 515;
|
||||||
|
const pageHeight = doc.internal.pageSize.getHeight();
|
||||||
|
const lineHeight = 12;
|
||||||
|
let y = margin;
|
||||||
|
|
||||||
|
const ensureSpace = (needed = lineHeight) => {
|
||||||
|
if (y + needed > pageHeight - margin) {
|
||||||
|
doc.addPage();
|
||||||
|
y = margin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addLines = (text, { bold = false, size = 10, gap = 0 } = {}) => {
|
||||||
|
doc.setFont("helvetica", bold ? "bold" : "normal");
|
||||||
|
doc.setFontSize(size);
|
||||||
|
const lines = doc.splitTextToSize(String(text), maxWidth);
|
||||||
|
for (const line of lines) {
|
||||||
|
ensureSpace();
|
||||||
|
doc.text(line, margin, y);
|
||||||
|
y += lineHeight;
|
||||||
|
}
|
||||||
|
y += gap;
|
||||||
|
};
|
||||||
|
|
||||||
|
addLines("Network tools — diagnostic report", { bold: true, size: 14, gap: 4 });
|
||||||
|
addLines(`Generated: ${new Date().toLocaleString()}`, { size: 9, gap: 2 });
|
||||||
|
if (targetUrl) addLines(`Target URL: ${targetUrl}`, { size: 9, gap: 10 });
|
||||||
|
|
||||||
|
for (const { serverName, items, errors } of groupedResults) {
|
||||||
|
addLines(`${serverName} — ${errors} error(s) / ${items.length} total`, {
|
||||||
|
bold: true,
|
||||||
|
size: 11,
|
||||||
|
gap: 6,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const { result } of items) {
|
||||||
|
const failed = isResultError(result);
|
||||||
|
const status =
|
||||||
|
getToolBody(result)?.returncode ?? result.status ?? (failed ? "FAIL" : "OK");
|
||||||
|
const header = [
|
||||||
|
result.endpoint || "request",
|
||||||
|
result.elapsed != null ? `${result.elapsed}ms` : null,
|
||||||
|
`exit ${status}`,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" · ");
|
||||||
|
|
||||||
|
addLines(header, { bold: true, size: 10, gap: 4 });
|
||||||
|
|
||||||
|
doc.setFont("courier", "normal");
|
||||||
|
doc.setFontSize(9);
|
||||||
|
const output = getResultOutput(result) || "(no output)";
|
||||||
|
const lines = doc.splitTextToSize(output, maxWidth);
|
||||||
|
for (const line of lines) {
|
||||||
|
ensureSpace();
|
||||||
|
doc.text(line, margin, y);
|
||||||
|
y += lineHeight;
|
||||||
|
}
|
||||||
|
y += 8;
|
||||||
|
}
|
||||||
|
y += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stamp = new Date().toISOString().slice(0, 19).replace(/[:T]/g, "-");
|
||||||
|
doc.save(`diagnostic-report-${stamp}.pdf`);
|
||||||
|
}
|
||||||
|
|
||||||
// ─── StatusBadge ──────────────────────────────────────────────────────────────
|
// ─── StatusBadge ──────────────────────────────────────────────────────────────
|
||||||
function StatusBadge({ status, ok }) {
|
function StatusBadge({ status, ok }) {
|
||||||
if (status === undefined) return <span className="badge pending">PENDING</span>;
|
if (status === undefined) return <span className="badge pending">PENDING</span>;
|
||||||
@@ -51,6 +182,66 @@ function StatusBadge({ status, ok }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ─── ResultCard ───────────────────────────────────────────────────────────────
|
// ─── ResultCard ───────────────────────────────────────────────────────────────
|
||||||
|
function UpstreamUnavailableBlock({
|
||||||
|
serverName,
|
||||||
|
host,
|
||||||
|
metadata = {},
|
||||||
|
error,
|
||||||
|
code,
|
||||||
|
}) {
|
||||||
|
const meta = [
|
||||||
|
metadata.location,
|
||||||
|
metadata.provider,
|
||||||
|
metadata.country,
|
||||||
|
metadata.tags?.length && metadata.tags.join(", "),
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" · ");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card card-err card-unavailable upstream-unavailable-block">
|
||||||
|
<div className="upstream-unavailable">
|
||||||
|
<div className="upstream-head">
|
||||||
|
<strong>{serverName}</strong>
|
||||||
|
<span className="upstream-status">unavailable</span>
|
||||||
|
</div>
|
||||||
|
{host && <div className="upstream-line">{host}</div>}
|
||||||
|
{meta && <div className="upstream-line upstream-meta">{meta}</div>}
|
||||||
|
{(code || error) && (
|
||||||
|
<div className="upstream-line upstream-error">
|
||||||
|
{[code, error].filter(Boolean).join(": ")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ToolErrorCard({ result, index }) {
|
||||||
|
return (
|
||||||
|
<div className="card card-err">
|
||||||
|
<div className="card-header">
|
||||||
|
<span className="card-index">#{index + 1}</span>
|
||||||
|
<span className="card-url" title={result.endpoint}>
|
||||||
|
{result.endpoint || "request"}
|
||||||
|
</span>
|
||||||
|
<div className="card-meta">
|
||||||
|
{result.elapsed != null && (
|
||||||
|
<span className="elapsed">{result.elapsed}ms</span>
|
||||||
|
)}
|
||||||
|
<span className="badge err">ERROR</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card-body tool-output">
|
||||||
|
<div className="upstream-unavailable">
|
||||||
|
<strong>Request failed</strong>
|
||||||
|
<p>{result.error}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function ToolResultCard({ result, index }) {
|
function ToolResultCard({ result, index }) {
|
||||||
const body = getToolBody(result);
|
const body = getToolBody(result);
|
||||||
const processOk = body.returncode === 0;
|
const processOk = body.returncode === 0;
|
||||||
@@ -104,6 +295,10 @@ function ResultCard({ result, index }) {
|
|||||||
const isError = result?.type === "error";
|
const isError = result?.type === "error";
|
||||||
const isPending = !result;
|
const isPending = !result;
|
||||||
|
|
||||||
|
if (isToolError(result) && !isUpstreamUnavailable(result)) {
|
||||||
|
return <ToolErrorCard result={result} index={index} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (isToolResult(result)) {
|
if (isToolResult(result)) {
|
||||||
return <ToolResultCard result={result} index={index} />;
|
return <ToolResultCard result={result} index={index} />;
|
||||||
}
|
}
|
||||||
@@ -173,6 +368,53 @@ function HostEditor({ hosts, setHosts }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ChecksEditor({ checks, setChecks, disabled }) {
|
||||||
|
const toggle = (id) => {
|
||||||
|
setChecks((prev) =>
|
||||||
|
prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id],
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAll = () => setChecks(DEFAULT_CHECKS);
|
||||||
|
const clearAll = () => setChecks([]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="checks-editor">
|
||||||
|
<div className="checks-toolbar">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="checks-action"
|
||||||
|
onClick={selectAll}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
все
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="checks-action"
|
||||||
|
onClick={clearAll}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
снять
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="checks-list">
|
||||||
|
{CHECK_OPTIONS.map(({ id, label }) => (
|
||||||
|
<label key={id} className="check-item">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={checks.includes(id)}
|
||||||
|
onChange={() => toggle(id)}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<span>{label}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ─── App ──────────────────────────────────────────────────────────────────────
|
// ─── App ──────────────────────────────────────────────────────────────────────
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const socketRef = useRef(null);
|
const socketRef = useRef(null);
|
||||||
@@ -180,6 +422,7 @@ export default function App() {
|
|||||||
const [connected, setConnected] = useState(false);
|
const [connected, setConnected] = useState(false);
|
||||||
|
|
||||||
const [hosts, setHosts] = useState(DEFAULT_HOSTS);
|
const [hosts, setHosts] = useState(DEFAULT_HOSTS);
|
||||||
|
const [checks, setChecks] = useState(DEFAULT_CHECKS);
|
||||||
const [results, setResults] = useState([]);
|
const [results, setResults] = useState([]);
|
||||||
const [progress, setProgress] = useState(null); // { done, total }
|
const [progress, setProgress] = useState(null); // { done, total }
|
||||||
const [running, setRunning] = useState(false);
|
const [running, setRunning] = useState(false);
|
||||||
@@ -192,7 +435,7 @@ export default function App() {
|
|||||||
|
|
||||||
// ── Connect socket once ──────────────────────────────────────────────────
|
// ── Connect socket once ──────────────────────────────────────────────────
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const socket = io({ path: SOCKET_IO_PATH });
|
const socket = io(SOCKET_URL, { path: SOCKET_IO_PATH });
|
||||||
socketRef.current = socket;
|
socketRef.current = socket;
|
||||||
|
|
||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
@@ -227,22 +470,7 @@ export default function App() {
|
|||||||
socket.on("tool:response", (payload) => {
|
socket.on("tool:response", (payload) => {
|
||||||
console.log("[socket] tool:response", payload);
|
console.log("[socket] tool:response", payload);
|
||||||
const entry = { ...payload, type: "tool" };
|
const entry = { ...payload, type: "tool" };
|
||||||
setResults((prev) => {
|
setResults((prev) => appendResult(prev, entry, payload.index));
|
||||||
if (typeof payload.index === "number") {
|
|
||||||
const next = prev.length ? [...prev] : [];
|
|
||||||
while (next.length <= payload.index) next.push(null);
|
|
||||||
next[payload.index] = entry;
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
if (!prev.length) return [entry];
|
|
||||||
const emptyIdx = prev.findIndex((r) => r == null);
|
|
||||||
if (emptyIdx >= 0) {
|
|
||||||
const next = [...prev];
|
|
||||||
next[emptyIdx] = entry;
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
return [...prev, entry];
|
|
||||||
});
|
|
||||||
const idx = typeof payload.index === "number" ? payload.index : null;
|
const idx = typeof payload.index === "number" ? payload.index : null;
|
||||||
setProgress((p) => p && { ...p, done: Math.min((p.done ?? 0) + 1, p.total) });
|
setProgress((p) => p && { ...p, done: Math.min((p.done ?? 0) + 1, p.total) });
|
||||||
const body = getToolBody(payload);
|
const body = getToolBody(payload);
|
||||||
@@ -254,13 +482,14 @@ export default function App() {
|
|||||||
|
|
||||||
socket.on("tool:error", (payload) => {
|
socket.on("tool:error", (payload) => {
|
||||||
console.log("[socket] tool:error", payload);
|
console.log("[socket] tool:error", payload);
|
||||||
setResults((prev) => {
|
const entry = { ...payload, type: "error" };
|
||||||
const next = [...prev];
|
setResults((prev) => appendResult(prev, entry, payload.index));
|
||||||
next[payload.index] = { ...payload, type: "error" };
|
const idx = typeof payload.index === "number" ? payload.index : null;
|
||||||
return next;
|
setProgress((p) => p && { ...p, done: Math.min((p.done ?? 0) + 1, p.total) });
|
||||||
});
|
const label = payload.serverName || payload.host || payload.endpoint || "?";
|
||||||
setProgress((p) => p && { ...p, done: p.done + 1 });
|
pushLog(
|
||||||
pushLog(`#${payload.index + 1} ${payload.url} → ERROR: ${payload.error}`);
|
`${idx != null ? `#${idx + 1} ` : ""}${label} → ERROR: ${payload.error}`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("batch:done", (data) => {
|
socket.on("batch:done", (data) => {
|
||||||
@@ -278,13 +507,13 @@ export default function App() {
|
|||||||
if (!socketId || running) return;
|
if (!socketId || running) return;
|
||||||
|
|
||||||
const url = hosts[0]?.url?.trim();
|
const url = hosts[0]?.url?.trim();
|
||||||
if (!url) return;
|
if (!url || checks.length === 0) return;
|
||||||
|
|
||||||
setRunning(true);
|
setRunning(true);
|
||||||
setResults([]);
|
setResults([]);
|
||||||
setProgress(null);
|
setProgress(null);
|
||||||
|
|
||||||
const payload = { socketId, url };
|
const payload = { socketId, url, checks };
|
||||||
console.log("sending:", JSON.stringify(payload));
|
console.log("sending:", JSON.stringify(payload));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -308,8 +537,13 @@ export default function App() {
|
|||||||
});
|
});
|
||||||
return Array.from(groups.entries()).map(([serverName, data]) => ({
|
return Array.from(groups.entries()).map(([serverName, data]) => ({
|
||||||
serverName,
|
serverName,
|
||||||
|
host: data.items[0]?.result?.host || "",
|
||||||
|
metadata: data.items[0]?.result?.metadata || {},
|
||||||
items: data.items,
|
items: data.items,
|
||||||
errors: data.errors,
|
errors: data.errors,
|
||||||
|
unavailable: data.items.filter(({ result }) =>
|
||||||
|
isUpstreamUnavailable(result),
|
||||||
|
).length,
|
||||||
}));
|
}));
|
||||||
}, [results]);
|
}, [results]);
|
||||||
|
|
||||||
@@ -332,10 +566,17 @@ export default function App() {
|
|||||||
<h2 className="section-title">задаём URL</h2>
|
<h2 className="section-title">задаём URL</h2>
|
||||||
<HostEditor hosts={hosts} setHosts={setHosts} />
|
<HostEditor hosts={hosts} setHosts={setHosts} />
|
||||||
|
|
||||||
|
<h2 className="section-title">проверки</h2>
|
||||||
|
<ChecksEditor
|
||||||
|
checks={checks}
|
||||||
|
setChecks={setChecks}
|
||||||
|
disabled={running}
|
||||||
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={`btn-run ${running ? "running" : ""}`}
|
className={`btn-run ${running ? "running" : ""}`}
|
||||||
onClick={run}
|
onClick={run}
|
||||||
disabled={running || !connected}
|
disabled={running || !connected || checks.length === 0}
|
||||||
>
|
>
|
||||||
{running ? (
|
{running ? (
|
||||||
<>
|
<>
|
||||||
@@ -368,14 +609,26 @@ export default function App() {
|
|||||||
|
|
||||||
{/* ── Right panel ────────────────────────────────────────────────── */}
|
{/* ── Right panel ────────────────────────────────────────────────── */}
|
||||||
<section className="panel panel-right">
|
<section className="panel panel-right">
|
||||||
<h2 className="section-title">
|
<div className="results-toolbar">
|
||||||
Results
|
<h2 className="section-title">
|
||||||
{results.length > 0 && (
|
Results
|
||||||
<span className="result-count">
|
{results.length > 0 && (
|
||||||
{results.filter(Boolean).length}/{results.length}
|
<span className="result-count">
|
||||||
</span>
|
{results.filter(Boolean).length}/{results.length}
|
||||||
)}
|
</span>
|
||||||
</h2>
|
)}
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-export"
|
||||||
|
disabled={groupedResults.length === 0}
|
||||||
|
onClick={() =>
|
||||||
|
exportResultsToPdf(groupedResults, hosts[0]?.url?.trim() || "")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Export PDF
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{results.length === 0 && !running && (
|
{results.length === 0 && !running && (
|
||||||
<div className="empty-state">
|
<div className="empty-state">
|
||||||
@@ -385,12 +638,33 @@ export default function App() {
|
|||||||
|
|
||||||
<div className="results-list">
|
<div className="results-list">
|
||||||
{groupedResults.map((group) => {
|
{groupedResults.map((group) => {
|
||||||
const { serverName, items, errors } = group;
|
const { serverName, host, metadata, items, errors, unavailable } =
|
||||||
|
group;
|
||||||
|
const allUnavailable =
|
||||||
|
unavailable > 0 && unavailable === items.length;
|
||||||
|
|
||||||
|
if (allUnavailable) {
|
||||||
|
const sample = items.find(({ result: r }) =>
|
||||||
|
isUpstreamUnavailable(r),
|
||||||
|
)?.result;
|
||||||
|
return (
|
||||||
|
<UpstreamUnavailableBlock
|
||||||
|
key={serverName}
|
||||||
|
serverName={serverName}
|
||||||
|
host={host}
|
||||||
|
metadata={metadata}
|
||||||
|
error={sample?.error}
|
||||||
|
code={sample?.code}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const isCollapsed = collapsedGroups.has(serverName);
|
const isCollapsed = collapsedGroups.has(serverName);
|
||||||
const hasErrors = errors > 0;
|
const hasErrors = errors > 0;
|
||||||
const groupClass = `server-group ${
|
const groupClass = `server-group ${
|
||||||
hasErrors ? "group-err" : "group-ok"
|
hasErrors ? "group-err" : "group-ok"
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={groupClass} key={serverName}>
|
<div className={groupClass} key={serverName}>
|
||||||
<div
|
<div
|
||||||
@@ -408,7 +682,18 @@ export default function App() {
|
|||||||
<span className="group-chevron">
|
<span className="group-chevron">
|
||||||
{isCollapsed ? "▶" : "▼"}
|
{isCollapsed ? "▶" : "▼"}
|
||||||
</span>
|
</span>
|
||||||
<strong>{serverName}</strong>
|
<div className="server-group-names">
|
||||||
|
<strong>{serverName}</strong>
|
||||||
|
{host && (
|
||||||
|
<span className="server-host-sub">{host}</span>
|
||||||
|
)}
|
||||||
|
{metadata?.location && (
|
||||||
|
<span className="server-host-sub">
|
||||||
|
{metadata.location}
|
||||||
|
{metadata.provider ? ` · ${metadata.provider}` : ""}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="server-group-meta">
|
<div className="server-group-meta">
|
||||||
<span className="server-errors">
|
<span className="server-errors">
|
||||||
@@ -420,7 +705,11 @@ export default function App() {
|
|||||||
{!isCollapsed && (
|
{!isCollapsed && (
|
||||||
<div className="server-group-results">
|
<div className="server-group-results">
|
||||||
{items.map(({ result, index }) => (
|
{items.map(({ result, index }) => (
|
||||||
<ResultCard key={index} result={result} index={index} />
|
<ResultCard
|
||||||
|
key={index}
|
||||||
|
result={result}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,4 +9,7 @@ export default defineConfig({
|
|||||||
react(),
|
react(),
|
||||||
babel({ presets: [reactCompilerPreset()] })
|
babel({ presets: [reactCompilerPreset()] })
|
||||||
],
|
],
|
||||||
|
server: {
|
||||||
|
host: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -144,6 +144,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.28.6":
|
||||||
|
version: 7.29.7
|
||||||
|
resolution: "@babel/runtime@npm:7.29.7"
|
||||||
|
checksum: 10c0/ca11572f7146b21e0bde6a9ed4bb6a89eafbee5f0944c7eb54d0d8a2dac962c33638a1d611e14faa71dfbb92b4b5f9236232208568a6b7d5c6f3f39ddb91771e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@babel/template@npm:^7.28.6":
|
"@babel/template@npm:^7.28.6":
|
||||||
version: 7.28.6
|
version: 7.28.6
|
||||||
resolution: "@babel/template@npm:7.28.6"
|
resolution: "@babel/template@npm:7.28.6"
|
||||||
@@ -572,6 +579,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/pako@npm:^2.0.3":
|
||||||
|
version: 2.0.4
|
||||||
|
resolution: "@types/pako@npm:2.0.4"
|
||||||
|
checksum: 10c0/5765bf8bc7e77ee141c454118f03e544b8f6cb51eb257d82dc5830feeab8cd00818af3a1eabefdfbe8dd3ae9916ed5403937bf1031a0ee51deea27fdf4dccdfb
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/raf@npm:^3.4.0":
|
||||||
|
version: 3.4.3
|
||||||
|
resolution: "@types/raf@npm:3.4.3"
|
||||||
|
checksum: 10c0/dea835f0daa399c51db9137f5337dc08a2b4a5f61f645658966ecabaebbbd0fd59551f384a1141e14e22a1cc5a591da7d4d88c60a525ad1399108b6dd2641d75
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/react-dom@npm:^19.2.3":
|
"@types/react-dom@npm:^19.2.3":
|
||||||
version: 19.2.3
|
version: 19.2.3
|
||||||
resolution: "@types/react-dom@npm:19.2.3"
|
resolution: "@types/react-dom@npm:19.2.3"
|
||||||
@@ -590,6 +611,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/trusted-types@npm:^2.0.7":
|
||||||
|
version: 2.0.7
|
||||||
|
resolution: "@types/trusted-types@npm:2.0.7"
|
||||||
|
checksum: 10c0/4c4855f10de7c6c135e0d32ce462419d8abbbc33713b31d294596c0cc34ae1fa6112a2f9da729c8f7a20707782b0d69da3b1f8df6645b0366d08825ca1522e0c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@vitejs/plugin-react@npm:^6.0.1":
|
"@vitejs/plugin-react@npm:^6.0.1":
|
||||||
version: 6.0.2
|
version: 6.0.2
|
||||||
resolution: "@vitejs/plugin-react@npm:6.0.2"
|
resolution: "@vitejs/plugin-react@npm:6.0.2"
|
||||||
@@ -703,6 +731,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"base64-arraybuffer@npm:^1.0.2":
|
||||||
|
version: 1.0.2
|
||||||
|
resolution: "base64-arraybuffer@npm:1.0.2"
|
||||||
|
checksum: 10c0/3acac95c70f9406e87a41073558ba85b6be9dbffb013a3d2a710e3f2d534d506c911847d5d9be4de458af6362c676de0a5c4c2d7bdf4def502d00b313368e72f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"baseline-browser-mapping@npm:^2.10.12":
|
"baseline-browser-mapping@npm:^2.10.12":
|
||||||
version: 2.10.31
|
version: 2.10.31
|
||||||
resolution: "baseline-browser-mapping@npm:2.10.31"
|
resolution: "baseline-browser-mapping@npm:2.10.31"
|
||||||
@@ -753,6 +788,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"canvg@npm:^3.0.11":
|
||||||
|
version: 3.0.11
|
||||||
|
resolution: "canvg@npm:3.0.11"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.12.5"
|
||||||
|
"@types/raf": "npm:^3.4.0"
|
||||||
|
core-js: "npm:^3.8.3"
|
||||||
|
raf: "npm:^3.4.1"
|
||||||
|
regenerator-runtime: "npm:^0.13.7"
|
||||||
|
rgbcolor: "npm:^1.0.1"
|
||||||
|
stackblur-canvas: "npm:^2.0.0"
|
||||||
|
svg-pathdata: "npm:^6.0.3"
|
||||||
|
checksum: 10c0/03ea5b69e97a4a476ef5fc8455d0da2718bd68cd8ace3e42718176bf4b7dfd80eb1d0eba47dcd04b34ed9a0c5c8ed849ead0f364dad0e35369254a45d5e098c4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"chownr@npm:^3.0.0":
|
"chownr@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "chownr@npm:3.0.0"
|
resolution: "chownr@npm:3.0.0"
|
||||||
@@ -776,6 +827,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"core-js@npm:^3.6.0, core-js@npm:^3.8.3":
|
||||||
|
version: 3.49.0
|
||||||
|
resolution: "core-js@npm:3.49.0"
|
||||||
|
checksum: 10c0/2e42edb47eda38fd5368380131623c8aa5d4a6b42164125b17744bdc08fa5ebbbdd06b4b4aa6ca3663470a560b0f2fba48e18f142dfe264b0039df85bc625694
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cross-spawn@npm:^7.0.6":
|
"cross-spawn@npm:^7.0.6":
|
||||||
version: 7.0.6
|
version: 7.0.6
|
||||||
resolution: "cross-spawn@npm:7.0.6"
|
resolution: "cross-spawn@npm:7.0.6"
|
||||||
@@ -787,6 +845,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"css-line-break@npm:^2.1.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "css-line-break@npm:2.1.0"
|
||||||
|
dependencies:
|
||||||
|
utrie: "npm:^1.0.2"
|
||||||
|
checksum: 10c0/b2222d99d5daf7861ecddc050244fdce296fad74b000dcff6bdfb1eb16dc2ef0b9ffe2c1c965e3239bd05ebe9eadb6d5438a91592fa8648d27a338e827cf9048
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"csstype@npm:^3.2.2":
|
"csstype@npm:^3.2.2":
|
||||||
version: 3.2.3
|
version: 3.2.3
|
||||||
resolution: "csstype@npm:3.2.3"
|
resolution: "csstype@npm:3.2.3"
|
||||||
@@ -827,6 +894,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"dompurify@npm:^3.3.1":
|
||||||
|
version: 3.4.7
|
||||||
|
resolution: "dompurify@npm:3.4.7"
|
||||||
|
dependencies:
|
||||||
|
"@types/trusted-types": "npm:^2.0.7"
|
||||||
|
dependenciesMeta:
|
||||||
|
"@types/trusted-types":
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/b39940e95259bfaea658cb2bec819d47f271f9fe47e4e3cfff1fb7876089264d7c21e36ea09dad0d9a0f70add502ce6787ba9e7467f2c7b996382eb1d8daa375
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"dunder-proto@npm:^1.0.1":
|
"dunder-proto@npm:^1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "dunder-proto@npm:1.0.1"
|
resolution: "dunder-proto@npm:1.0.1"
|
||||||
@@ -1087,6 +1166,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"fast-png@npm:^6.2.0":
|
||||||
|
version: 6.4.0
|
||||||
|
resolution: "fast-png@npm:6.4.0"
|
||||||
|
dependencies:
|
||||||
|
"@types/pako": "npm:^2.0.3"
|
||||||
|
iobuffer: "npm:^5.3.2"
|
||||||
|
pako: "npm:^2.1.0"
|
||||||
|
checksum: 10c0/bca27a09d56a5ead536b11c1ddccf4fe44c7c0af88a8faefab6a397527d9c71b00c09b2055d0108807c438c50719dd2acbd7217ef88785b500888db26fa0358a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"fdir@npm:^6.5.0":
|
"fdir@npm:^6.5.0":
|
||||||
version: 6.5.0
|
version: 6.5.0
|
||||||
resolution: "fdir@npm:6.5.0"
|
resolution: "fdir@npm:6.5.0"
|
||||||
@@ -1099,6 +1189,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"fflate@npm:^0.8.1":
|
||||||
|
version: 0.8.3
|
||||||
|
resolution: "fflate@npm:0.8.3"
|
||||||
|
checksum: 10c0/eab181ca37f5348ae76d4b6f840e0026e30220e33153289ac942222d8b9638237d486507dbcc09878d724095bd354993a2ee48bbee99c8f2c6440d4448719aa7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"file-entry-cache@npm:^8.0.0":
|
"file-entry-cache@npm:^8.0.0":
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
resolution: "file-entry-cache@npm:8.0.0"
|
resolution: "file-entry-cache@npm:8.0.0"
|
||||||
@@ -1300,6 +1397,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"html2canvas@npm:^1.0.0-rc.5":
|
||||||
|
version: 1.4.1
|
||||||
|
resolution: "html2canvas@npm:1.4.1"
|
||||||
|
dependencies:
|
||||||
|
css-line-break: "npm:^2.1.0"
|
||||||
|
text-segmentation: "npm:^1.0.3"
|
||||||
|
checksum: 10c0/6de86f75762b00948edf2ea559f16da0a1ec3facc4a8a7d3f35fcec59bb0c5970463478988ae3d9082152e0173690d46ebf4082e7ac803dd4817bae1d355c0db
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"https-proxy-agent@npm:^5.0.1":
|
"https-proxy-agent@npm:^5.0.1":
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
resolution: "https-proxy-agent@npm:5.0.1"
|
resolution: "https-proxy-agent@npm:5.0.1"
|
||||||
@@ -1324,6 +1431,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"iobuffer@npm:^5.3.2":
|
||||||
|
version: 5.4.0
|
||||||
|
resolution: "iobuffer@npm:5.4.0"
|
||||||
|
checksum: 10c0/1b3f9a5ea158bc63f038b374b42832acdb9db13ea9cfa4ed78723f30894986442f6c033dff4ae2fdf34724bf0fe432e3b86c11ca82049568c58b8d7fb47a6ac2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"is-extglob@npm:^2.1.1":
|
"is-extglob@npm:^2.1.1":
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
resolution: "is-extglob@npm:2.1.1"
|
resolution: "is-extglob@npm:2.1.1"
|
||||||
@@ -1400,6 +1514,30 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"jspdf@npm:^4.2.1":
|
||||||
|
version: 4.2.1
|
||||||
|
resolution: "jspdf@npm:4.2.1"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.28.6"
|
||||||
|
canvg: "npm:^3.0.11"
|
||||||
|
core-js: "npm:^3.6.0"
|
||||||
|
dompurify: "npm:^3.3.1"
|
||||||
|
fast-png: "npm:^6.2.0"
|
||||||
|
fflate: "npm:^0.8.1"
|
||||||
|
html2canvas: "npm:^1.0.0-rc.5"
|
||||||
|
dependenciesMeta:
|
||||||
|
canvg:
|
||||||
|
optional: true
|
||||||
|
core-js:
|
||||||
|
optional: true
|
||||||
|
dompurify:
|
||||||
|
optional: true
|
||||||
|
html2canvas:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/d905809b374de1060ab39ba4b1603935fcced314bef8f63f7fd272d3f96eff0b50a96e48d3c2063ac8e51b84a1442464ff2b037af13f54b082e456416da470b7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"keyv@npm:^4.5.4":
|
"keyv@npm:^4.5.4":
|
||||||
version: 4.5.4
|
version: 4.5.4
|
||||||
resolution: "keyv@npm:4.5.4"
|
resolution: "keyv@npm:4.5.4"
|
||||||
@@ -1644,6 +1782,7 @@ __metadata:
|
|||||||
eslint-plugin-react-hooks: "npm:^7.1.1"
|
eslint-plugin-react-hooks: "npm:^7.1.1"
|
||||||
eslint-plugin-react-refresh: "npm:^0.5.2"
|
eslint-plugin-react-refresh: "npm:^0.5.2"
|
||||||
globals: "npm:^17.6.0"
|
globals: "npm:^17.6.0"
|
||||||
|
jspdf: "npm:^4.2.1"
|
||||||
react: "npm:^19.2.6"
|
react: "npm:^19.2.6"
|
||||||
react-dom: "npm:^19.2.6"
|
react-dom: "npm:^19.2.6"
|
||||||
socket.io-client: "npm:^4.6.1"
|
socket.io-client: "npm:^4.6.1"
|
||||||
@@ -1721,6 +1860,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pako@npm:^2.1.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "pako@npm:2.1.0"
|
||||||
|
checksum: 10c0/8e8646581410654b50eb22a5dfd71159cae98145bd5086c9a7a816ec0370b5f72b4648d08674624b3870a521e6a3daffd6c2f7bc00fdefc7063c9d8232ff5116
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-exists@npm:^4.0.0":
|
"path-exists@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "path-exists@npm:4.0.0"
|
resolution: "path-exists@npm:4.0.0"
|
||||||
@@ -1735,6 +1881,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"performance-now@npm:^2.1.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "performance-now@npm:2.1.0"
|
||||||
|
checksum: 10c0/22c54de06f269e29f640e0e075207af57de5052a3d15e360c09b9a8663f393f6f45902006c1e71aa8a5a1cdfb1a47fe268826f8496d6425c362f00f5bc3e85d9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"picocolors@npm:^1.1.1":
|
"picocolors@npm:^1.1.1":
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
resolution: "picocolors@npm:1.1.1"
|
resolution: "picocolors@npm:1.1.1"
|
||||||
@@ -1788,6 +1941,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"raf@npm:^3.4.1":
|
||||||
|
version: 3.4.1
|
||||||
|
resolution: "raf@npm:3.4.1"
|
||||||
|
dependencies:
|
||||||
|
performance-now: "npm:^2.1.0"
|
||||||
|
checksum: 10c0/337f0853c9e6a77647b0f499beedafea5d6facfb9f2d488a624f88b03df2be72b8a0e7f9118a3ff811377d534912039a3311815700d2b6d2313f82f736f9eb6e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-dom@npm:^19.2.6":
|
"react-dom@npm:^19.2.6":
|
||||||
version: 19.2.6
|
version: 19.2.6
|
||||||
resolution: "react-dom@npm:19.2.6"
|
resolution: "react-dom@npm:19.2.6"
|
||||||
@@ -1806,6 +1968,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"regenerator-runtime@npm:^0.13.7":
|
||||||
|
version: 0.13.11
|
||||||
|
resolution: "regenerator-runtime@npm:0.13.11"
|
||||||
|
checksum: 10c0/12b069dc774001fbb0014f6a28f11c09ebfe3c0d984d88c9bced77fdb6fedbacbca434d24da9ae9371bfbf23f754869307fb51a4c98a8b8b18e5ef748677ca24
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"rgbcolor@npm:^1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "rgbcolor@npm:1.0.1"
|
||||||
|
checksum: 10c0/13af06c523351bac2854b85a22d1dfafd9310efd898e9bd96c8706f9aa09a3ddc8392ab00ae03d12950782164a97677f21834ffd84ffebf76ae106add319f956
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"rolldown@npm:1.0.1":
|
"rolldown@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "rolldown@npm:1.0.1"
|
resolution: "rolldown@npm:1.0.1"
|
||||||
@@ -1934,6 +2110,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"stackblur-canvas@npm:^2.0.0":
|
||||||
|
version: 2.7.0
|
||||||
|
resolution: "stackblur-canvas@npm:2.7.0"
|
||||||
|
checksum: 10c0/df290d0629056d5bb43d37548d0b24cb8593c79d742650e68489abf61013db578c9980724c2508bb738d107204f2e2494ab94c3cf69d6b725caa9c63b8c7e272
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"svg-pathdata@npm:^6.0.3":
|
||||||
|
version: 6.0.3
|
||||||
|
resolution: "svg-pathdata@npm:6.0.3"
|
||||||
|
checksum: 10c0/1ba4ad2fa81e86df37d6e78d3be9e664bbedf97773b725a863a85db384285be32dc37d9c0d61e477d89594ee95b967d2c53d6bee2d76420aab670ab4124a38b9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tar@npm:^7.5.4":
|
"tar@npm:^7.5.4":
|
||||||
version: 7.5.15
|
version: 7.5.15
|
||||||
resolution: "tar@npm:7.5.15"
|
resolution: "tar@npm:7.5.15"
|
||||||
@@ -1947,6 +2137,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"text-segmentation@npm:^1.0.3":
|
||||||
|
version: 1.0.3
|
||||||
|
resolution: "text-segmentation@npm:1.0.3"
|
||||||
|
dependencies:
|
||||||
|
utrie: "npm:^1.0.2"
|
||||||
|
checksum: 10c0/8b9ae8524e3a332371060d0ca62f10ad49a13e954719ea689a6c3a8b8c15c8a56365ede2bb91c322fb0d44b6533785f0da603e066b7554d052999967fb72d600
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.16":
|
"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.16":
|
||||||
version: 0.2.16
|
version: 0.2.16
|
||||||
resolution: "tinyglobby@npm:0.2.16"
|
resolution: "tinyglobby@npm:0.2.16"
|
||||||
@@ -2003,6 +2202,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"utrie@npm:^1.0.2":
|
||||||
|
version: 1.0.2
|
||||||
|
resolution: "utrie@npm:1.0.2"
|
||||||
|
dependencies:
|
||||||
|
base64-arraybuffer: "npm:^1.0.2"
|
||||||
|
checksum: 10c0/eaffe645bd81a39e4bc3abb23df5895e9961dbdd49748ef3b173529e8b06ce9dd1163e9705d5309a1c61ee41ffcb825e2043bc0fd1659845ffbdf4b1515dfdb4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"vite@npm:^8.0.12":
|
"vite@npm:^8.0.12":
|
||||||
version: 8.0.13
|
version: 8.0.13
|
||||||
resolution: "vite@npm:8.0.13"
|
resolution: "vite@npm:8.0.13"
|
||||||
|
|||||||
Reference in New Issue
Block a user