ui: Fix JSON enqueue issue / code-editor render issue.

This fixes two issues:

- An error logged to the console when enqueueing a JSON downlink payload
(Q.Va is not a function).
- The codemirror editor has been replaced by ace, to solve a potential
rendering issue within ReactJS / Antd.

Closes #658.
This commit is contained in:
Orne Brocaar 2025-04-28 10:09:52 +01:00
parent 330f5dcae0
commit 1b5e5972f4
9 changed files with 100 additions and 87 deletions

View File

@ -4,13 +4,13 @@
"description": "Chirpstack gRPC-web API",
"license": "MIT",
"devDependencies": {
"grpc-tools": "^1.12.4",
"grpc-tools": "^1.13.0",
"ts-protoc-gen": "^0.15.0",
"typescript": "^5.1.6"
"typescript": "^5.8.3"
},
"dependencies": {
"@types/google-protobuf": "^3.15.12",
"google-protobuf": "^3.21.2",
"google-protobuf": "^3.21.4",
"grpc-web": "^1.5.0"
}
}

View File

@ -146,15 +146,20 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
google-protobuf@^3.15.5, google-protobuf@^3.21.2:
google-protobuf@^3.15.5:
version "3.21.2"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4"
integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==
grpc-tools@^1.12.4:
version "1.12.4"
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.12.4.tgz#a044c9e8157941033ea7a5f144c2dc9dc4501de4"
integrity sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==
google-protobuf@^3.21.4:
version "3.21.4"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9"
integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==
grpc-tools@^1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.13.0.tgz#a4fea8eebce51fb9fec00055a3e52016dfd5af89"
integrity sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
@ -376,10 +381,10 @@ ts-protoc-gen@^0.15.0:
dependencies:
google-protobuf "^3.15.5"
typescript@^5.1.6:
version "5.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
typescript@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
util-deprecate@^1.0.1:
version "1.0.2"

10
api/js/package.json vendored
View File

@ -4,14 +4,14 @@
"description": "Chirpstack JS and TS API",
"license": "MIT",
"devDependencies": {
"grpc-tools": "^1.12.4",
"grpc-tools": "^1.13.0",
"ts-protoc-gen": "^0.15.0",
"typescript": "^5.1.6"
"typescript": "^5.8.3"
},
"dependencies": {
"@grpc/grpc-js": "^1.10.4",
"@grpc/grpc-js": "^1.13.3",
"@mapbox/node-pre-gyp": "^1.0.11",
"@types/google-protobuf": "^3.15.6",
"google-protobuf": "^3.21.2"
"@types/google-protobuf": "^3.15.12",
"google-protobuf": "^3.21.4"
}
}

39
api/js/yarn.lock vendored
View File

@ -2,10 +2,10 @@
# yarn lockfile v1
"@grpc/grpc-js@^1.10.4":
version "1.10.9"
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.9.tgz#468cc1549a3fe37b760a16745fb7685d91f4f10c"
integrity sha512-5tcgUctCG0qoNyfChZifz2tJqbRbXVO9J7X6duFcOjY3HUNCxg5D0ZCK7EP9vIcZ0zRpLU9bWkyCqVCLZ46IbQ==
"@grpc/grpc-js@^1.13.3":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.13.3.tgz#6ad08d186c2a8651697085f790c5c68eaca45904"
integrity sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==
dependencies:
"@grpc/proto-loader" "^0.7.13"
"@js-sdsl/ordered-map" "^4.4.2"
@ -93,10 +93,10 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
"@types/google-protobuf@^3.15.6":
version "3.15.6"
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.6.tgz#674a69493ef2c849b95eafe69167ea59079eb504"
integrity sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==
"@types/google-protobuf@^3.15.12":
version "3.15.12"
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.12.tgz#eb2ba0eddd65712211a2b455dc6071d665ccf49b"
integrity sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==
"@types/node@>=13.7.0":
version "20.4.8"
@ -265,15 +265,20 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
google-protobuf@^3.15.5, google-protobuf@^3.21.2:
google-protobuf@^3.15.5:
version "3.21.2"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4"
integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==
grpc-tools@^1.12.4:
version "1.12.4"
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.12.4.tgz#a044c9e8157941033ea7a5f144c2dc9dc4501de4"
integrity sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==
google-protobuf@^3.21.4:
version "3.21.4"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9"
integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==
grpc-tools@^1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.13.0.tgz#a4fea8eebce51fb9fec00055a3e52016dfd5af89"
integrity sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
@ -523,10 +528,10 @@ ts-protoc-gen@^0.15.0:
dependencies:
google-protobuf "^3.15.5"
typescript@^5.1.6:
version "5.1.6"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
typescript@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
util-deprecate@^1.0.1:
version "1.0.2"

View File

@ -18,12 +18,12 @@
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"ace-builds": "^1.36.4",
"antd": "^5.23.3",
"buffer": "^6.0.3",
"chart.js": "^4.4.7",
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-matrix": "^2.0.1",
"codemirror": "^5.65.16",
"date-fns": "^3.6.0",
"events": "^3.3.0",
"google-palette": "^1.1.1",
@ -32,8 +32,8 @@
"leaflet": "^1.9.4",
"leaflet.awesome-markers": "^2.0.5",
"react": "^18.3.1",
"react-ace": "^13.0.0",
"react-chartjs-2": "^5.2.0",
"react-codemirror2": "^8.0.0",
"react-dom": "^18.3.1",
"react-json-tree": "^0.19.0",
"react-leaflet": "^4.2.1",
@ -43,7 +43,6 @@
},
"devDependencies": {
"@testing-library/jest-dom": "^6.4.6",
"@types/codemirror": "^5.60.15",
"@types/events": "^3.0.3",
"@types/leaflet": "^1.9.12",
"@types/leaflet.awesome-markers": "^2.0.28",
@ -56,7 +55,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"prettier": "^3.3.2",
"typescript": "^5.2.2",
"typescript": "^5.8.3",
"vite": "^6.2.6"
}
}

View File

@ -1,10 +1,11 @@
import { useState, useEffect } from "react";
import { Controlled as CodeMirror } from "react-codemirror2";
import type { Editor, EditorChange } from "codemirror";
import { Form } from "antd";
import AceEditor from "react-ace";
import "codemirror/mode/javascript/javascript";
import "ace-builds/src-noconflict/mode-javascript";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-github";
interface IProps {
label?: string;
@ -12,6 +13,7 @@ interface IProps {
required?: boolean;
disabled?: boolean;
tooltip?: string;
mode?: string;
}
function CodeEditor(props: IProps) {
@ -24,28 +26,25 @@ function CodeEditor(props: IProps) {
setReloadKey(k => k + 1);
}, [form, props]);
const handleChange = (editor: Editor, data: EditorChange, newCode: string) => {
setValue(newCode);
const onChange = (newValue: string) => {
setValue(newValue);
form.setFieldsValue({
[props.name]: newCode,
[props.name]: newValue,
});
};
const codeMirrorOptions = {
lineNumbers: true,
mode: "javascript",
theme: "base16-light",
readOnly: props.disabled,
};
}
return (
<Form.Item label={props.label} name={props.name} tooltip={props.tooltip}>
<div style={{ border: "1px solid #cccccc" }}>
<CodeMirror
key={`code-editor-refresh-${reloadKey}`}
<AceEditor
mode={props.mode || "javascript"}
theme="github"
onChange={onChange}
value={value}
options={codeMirrorOptions}
onBeforeChange={handleChange}
name={`code-editor-refresh-${reloadKey}`}
width="100%"
height="600px"
editorProps={{ $blockScrolling: true }}
/>
</div>
</Form.Item>

View File

@ -12,8 +12,6 @@ import "antd/dist/reset.css";
import "leaflet/dist/leaflet.css";
import "leaflet.awesome-markers/dist/leaflet.awesome-markers.css";
import "@fortawesome/fontawesome-free/css/all.css";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/base16-light.css";
import "./index.css";
Chart.register(MatrixController, MatrixElement, ...registerables);

View File

@ -268,7 +268,7 @@ function DeviceQueue(props: IProps) {
</Form.Item>
</Tabs.TabPane>
<Tabs.TabPane tab="JSON" key="3">
<CodeEditor name="json" />
<CodeEditor name="json" mode="json" />
</Tabs.TabPane>
</Tabs>
<Button type="primary" htmlType="submit">

View File

@ -127,10 +127,10 @@
regenerator-runtime "^0.14.0"
"@chirpstack/chirpstack-api-grpc-web@file:../api/grpc-web":
version "4.12.0-test.3"
version "4.12.0"
dependencies:
"@types/google-protobuf" "^3.15.12"
google-protobuf "^3.21.2"
google-protobuf "^3.21.4"
grpc-web "^1.5.0"
"@ctrl/tinycolor@^3.4.0":
@ -667,13 +667,6 @@
lodash "^4.17.21"
redent "^3.0.0"
"@types/codemirror@^5.60.15":
version "5.60.15"
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.15.tgz#0f82be6f4126d1e59cf4c4830e56dcd49d3c3e8a"
integrity sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==
dependencies:
"@types/tern" "*"
"@types/debug@^4.0.0":
version "4.1.12"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
@ -764,13 +757,6 @@
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/tern@*":
version "0.23.9"
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.9.tgz#6f6093a4a9af3e6bb8dde528e024924d196b367c"
integrity sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==
dependencies:
"@types/estree" "*"
"@types/unist@*", "@types/unist@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c"
@ -884,6 +870,11 @@
dependencies:
"@swc/core" "^1.11.21"
ace-builds@^1.36.3, ace-builds@^1.36.4:
version "1.40.1"
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.40.1.tgz#68421283088f0e075f3375cb3d46bb86ad6ddc6e"
integrity sha512-32uwJNwmhqpnYtr6oq8RoO1D6F6tnxisv5f9w2XPX3vi4QruuHNikadHUiHvnxLAV1n5Azv4LFtpItQ5dD1eRw==
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
@ -1099,11 +1090,6 @@ classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classna
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
codemirror@^5.65.16:
version "5.65.19"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.19.tgz#71016c701d6a4b6e1982b0f6e7186be65e49653d"
integrity sha512-+aFkvqhaAVr1gferNMuN8vkTSrWIFvzlMV9I2KBLCWS2WpZ2+UAkZjlMZmEuT+gcXTi6RrGQCkWq1/bDtGqhIA==
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@ -1214,6 +1200,11 @@ devlop@^1.0.0, devlop@^1.1.0:
dependencies:
dequal "^2.0.0"
diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@ -1513,7 +1504,7 @@ google-palette@^1.1.1:
resolved "https://registry.yarnpkg.com/google-palette/-/google-palette-1.1.1.tgz#671b3b932c8393271b67da908ccd7f2c48e84cc7"
integrity sha512-yZiM5oLl8lCZzf06IMOGdDkxqvCMd9HNFcCiOMqWgGGiGzC22vWBVhKJNvykXXbeC0NAElNH97jA/y0bq6TCrA==
google-protobuf@^3.21.2:
google-protobuf@^3.21.4:
version "3.21.4"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9"
integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==
@ -1755,6 +1746,16 @@ lodash-es@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@ -2610,6 +2611,17 @@ rc-virtual-list@^3.14.2, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2:
rc-resize-observer "^1.0.0"
rc-util "^5.36.0"
react-ace@^13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-13.0.0.tgz#e69c2aa4ccf1a81c758adba9ba2b4b3e3d929a69"
integrity sha512-PPk2O/ArHzDtbnK82QImfHYXwuiitRgHJf5AxwMQh9zciojbWsPmKJm1tMgWOYLCtGEz8/Dh3MxRxrXe7QcstQ==
dependencies:
ace-builds "^1.36.3"
diff-match-patch "^1.0.5"
lodash.get "^4.4.2"
lodash.isequal "^4.5.0"
prop-types "^15.8.1"
react-base16-styling@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.10.0.tgz#5d5f019bd4dc5870c3e92fd9d5410533a0bbb0c6"
@ -2625,11 +2637,6 @@ react-chartjs-2@^5.2.0:
resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz#2d3286339a742bc7f77b5829c33ebab215f714cc"
integrity sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==
react-codemirror2@^8.0.0:
version "8.0.1"
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-8.0.1.tgz#a229c9dda2a6ee9ea18bdb8a4c33a1b2df823613"
integrity sha512-ZALowE5sGK1t66i0Fm1hoJLWT/iZHNjaAmcjwgYl9gyl2v1sqWwxzWHLmgq6K9KCk7p5+I+U3jMF1vsLaIkrmA==
react-dom@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
@ -2967,7 +2974,7 @@ type-fest@^0.20.2:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
typescript@^5.2.2:
typescript@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==