From 088d4f7beba46f016804b0e43710fc4585fac9c4 Mon Sep 17 00:00:00 2001 From: Dmitrii Shilov <6812525+bk201-@users.noreply.github.com> Date: Wed, 3 Jun 2026 10:59:41 +0200 Subject: [PATCH 1/3] chore(webview): align tRPC infra with documentdb package Snapshot of pre-extraction state. Brings cosmosdb's webview tRPC infrastructure to behavioural and API parity with @vscode-ext-react-webview from vscode-documentdb: - Split tRPC middleware into logging/telemetry with pluggable ProcedureLogger and TelemetryRunner adapters (azextTelemetryRunner, outputChannelLogger, consoleProcedureLogger fallback). - Generic BaseRouterContext = { signal?; telemetry? }; WithRequired + WithTelemetry helpers. - Abort-aware telemetry: ctx.signal?.aborted -> properties.aborted='true', result='Canceled'. - useTrpcClient migrated to options-object API; TrpcClient alias via non-deprecated TRPCClient. - WithWebviewContext provider helper with memoized value. - BaseTab gains onDisposed EventEmitter + isDisposed getter with idempotent dispose guard. - TypedEventSink: iterator.return() + idempotent close(); 15 tests covering edge cases. - setupTrpc: abort flow for query/mutation, iterator.return() on subscription.stop and panel.dispose, per-op context clone, undefined->null structured-clone coalesce, safer postMessage. - vscodeLink: abort flow with pre-aborted signal early-exit, sendSafe strips non-serializable signal, abort listener cleanup. - 18 tests for vscodeLink, 6 tests for errorLink. Sees plans/webview-vs-documentdb-package.md for full delta analysis. --- package-lock.json | 2285 +++++++++-------- package.json | 19 +- src/panels/BaseTab.ts | 44 + src/panels/trpc/appRouter.ts | 51 +- src/panels/trpc/baseRouterContext.ts | 119 + .../trpc/middleware/azextTelemetryRunner.ts | 94 + .../trpc/middleware/loggingMiddleware.ts | 150 ++ .../trpc/middleware/outputChannelLogger.ts | 68 + .../trpc/middleware/telemetryMiddleware.ts | 128 + src/panels/trpc/middleware/types.ts | 54 + src/panels/trpc/setupTrpc.ts | 188 +- src/panels/trpc/trpc.ts | 149 +- src/panels/trpc/vscodeProtocol.ts | 3 +- src/utils/TypedEventSink.test.ts | 81 + src/utils/TypedEventSink.ts | 46 + src/webviews/WebviewContext.tsx | 41 +- src/webviews/api/trpc/errorLink.test.ts | 131 + src/webviews/api/trpc/useTrpcClient.ts | 74 +- src/webviews/api/trpc/vscodeLink.test.ts | 430 ++++ src/webviews/api/trpc/vscodeLink.ts | 54 +- .../Document/state/DocumentContext.tsx | 2 +- .../QueryEditor/state/QueryEditorContext.tsx | 2 +- 22 files changed, 3002 insertions(+), 1211 deletions(-) create mode 100644 src/panels/trpc/baseRouterContext.ts create mode 100644 src/panels/trpc/middleware/azextTelemetryRunner.ts create mode 100644 src/panels/trpc/middleware/loggingMiddleware.ts create mode 100644 src/panels/trpc/middleware/outputChannelLogger.ts create mode 100644 src/panels/trpc/middleware/telemetryMiddleware.ts create mode 100644 src/panels/trpc/middleware/types.ts create mode 100644 src/webviews/api/trpc/errorLink.test.ts create mode 100644 src/webviews/api/trpc/vscodeLink.test.ts diff --git a/package-lock.json b/package-lock.json index 881f575c0..986812632 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@azure/arm-resources": "~7.0.0", "@azure/cosmos": "~4.9.0", "@azure/identity": "~4.13.0", - "@fluentui/react-components": "~9.73.0", + "@fluentui/react-components": "~9.74.1", "@fluentui/react-icons": "~2.0.313", "@microsoft/vscode-azext-azureauth": "~5.1.1", "@microsoft/vscode-azext-azureutils": "~4.2.0", @@ -31,7 +31,7 @@ "@vscode/l10n": "~0.0.18", "@vscode/prompt-tsx": "^0.4.0-alpha.7", "allotment": "~1.20.4", - "es-toolkit": "~1.46.0", + "es-toolkit": "~1.47.0", "monaco-editor": "~0.52.2", "react-data-grid": "~7.0.0-beta.59", "react-hotkeys-hook": "5.1.0", @@ -53,7 +53,7 @@ "@vscode/test-cli": "~0.0.12", "@vscode/test-electron": "~2.5.2", "@vscode/vsce": "~3.9.1", - "concurrently": "~9.2.1", + "concurrently": "~10.0.3", "cross-env": "~10.1.0", "diff": "~9.0.0", "eslint": "~10.4.0", @@ -65,16 +65,16 @@ "mocha": "~11.7.4", "mocha-junit-reporter": "~2.2.1", "mocha-multi-reporters": "~1.5.1", - "oxfmt": "~0.51.0", - "oxlint": "~1.66.0", + "oxfmt": "~0.53.0", + "oxlint": "~1.68.0", "oxlint-tsgolint": "~0.23.0", "react": "~19.2.1", "react-dom": "~19.2.1", "react-refresh": "~0.18.0", "rimraf": "~6.1.0", - "sass": "~1.99.0", + "sass": "~1.100.0", "typescript": "~6.0.2", - "typescript-eslint": "~8.59.0", + "typescript-eslint": "~8.60.1", "vite": "~8.0.10", "vite-bundle-analyzer": "~1.3.7", "vite-plugin-static-copy": "~4.1.0", @@ -599,33 +599,33 @@ "license": "MIT" }, "node_modules/@azure/msal-browser": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.10.1.tgz", - "integrity": "sha512-hTbvOi9Ko2Jvn+G/fSmjzHf9WbNcf/o3epMtbeGx/pMwMrVAbi6OgCJVeCfsAb8IybSRpaCSc4EDRlYAhgngUQ==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.11.0.tgz", + "integrity": "sha512-zkGNYS3TwY8lUpPIafAmsFCYZbgFixY9y/LZB9GUg0IILoHTqpN26j5OrkL1AQThh/YdZsawe4iWXfp85lFVxg==", "license": "MIT", "dependencies": { - "@azure/msal-common": "16.6.1" + "@azure/msal-common": "16.6.2" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.6.1.tgz", - "integrity": "sha512-VxKdEtUwDuLD0F1hOQP7kye0YadZxFJfv37Em440geEf/w9uggKnHpRrqwZJOdxmPUOdhZ9kyRtKuAJW8wUcRg==", + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.6.2.tgz", + "integrity": "sha512-hQjjsekAjB00cM1EmatWJlzhEoK2Qhz7Rj5gvM6tYf8iL7RM3tkxlpU9fG0+ofkulzg9AEEA6dIEnSmDr5ZqUA==", "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-node": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.1.tgz", - "integrity": "sha512-tmQiQ2HvtzaeLqYGy3BemiPOSGPY4wCy1IW5zDWITKSs/s35WEd7Zij/hCxvUdAOzj6U3qnyaGbYXY91ortFEQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.2.tgz", + "integrity": "sha512-toS+2AePxqyzb0YOKttDOOiSl3jrkK9aiqIvpurpis0O34QcIS5gToqrgT39p04Dpxw3YoUU0lxJKTpSFFfA6Q==", "license": "MIT", "dependencies": { - "@azure/msal-common": "16.6.1", + "@azure/msal-common": "16.6.2", "jsonwebtoken": "^9.0.0" }, "engines": { @@ -633,12 +633,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -647,18 +647,18 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/runtime": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -762,9 +762,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.43.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.0.tgz", - "integrity": "sha512-V7ZCLQO3Jus9hzh2jVCCPW3mO4IBMr43O37PqSUYautJSnnJF41YlgLw21x0fLJTYvJ+Vkm6Gp+qKGH9pltgXA==", + "version": "6.42.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", + "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", "dev": true, "license": "MIT", "dependencies": { @@ -971,9 +971,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", - "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1037,21 +1037,21 @@ } }, "node_modules/@fluentui/react-accordion": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.11.0.tgz", - "integrity": "sha512-mEy73hbJM53tMj3MWqm3ajbBxj48uubnJjumVKI8Z/eXHS8L3GzUy5rf/gUH26xSR2Tl+edpFhYB8PFbJDIKKw==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.12.0.tgz", + "integrity": "sha512-Ay1Cet3qTdpcHQErelG/6tSAhaNCkCojZzNzhpET25ukiMNFeJVK/j/kQbrcjbdClYdz35+8/3hI8q6hSIPD/Q==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1063,18 +1063,18 @@ } }, "node_modules/@fluentui/react-alert": { - "version": "9.0.0-beta.139", - "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.139.tgz", - "integrity": "sha512-R9r4dwwpWpgFmB8wVeWqipjUh/e6lyacnerX39HtVdgcG/PE+kpdHjKGiy8MAD+BGYCzrUxKNhXTQDlpXasJ1Q==", + "version": "9.0.0-beta.140", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.140.tgz", + "integrity": "sha512-IYrS7qNyN6FFya+FBdyHZU3jA+6xcU7SD1FjFbthZMx2QTYN7wnZGUdIRQQc3BQRRwRNWtH2BEF4RZY20TvfWQ==", "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.239", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1086,16 +1086,16 @@ } }, "node_modules/@fluentui/react-aria": { - "version": "9.17.11", - "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.17.11.tgz", - "integrity": "sha512-K9nz+Wn5JliCpG6bIYYPXvKmpOql+w9uyzmYNYkYQ6QHgoCpph7XUFx1HCtsJm2PPNi8WO8g0ZV9jojdGKl1Tg==", + "version": "9.17.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.17.12.tgz", + "integrity": "sha512-Nrgj9ND3nqtr33w0ICXs3/VrtSBZNBoFl9FkeWz3SCUeUcC8A9eFIH2HpHjbgwENs9BV+aUPi2J2vZhX1+yqQg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1106,21 +1106,21 @@ } }, "node_modules/@fluentui/react-avatar": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.11.1.tgz", - "integrity": "sha512-y1T67rVQQ/D4FAod8F4crXo9funaptscRIiW81LAsbN82fFVexMPQ9GmXooQQvn6ILvjJtf9IyvSJ195qDsyag==", + "version": "9.11.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.11.2.tgz", + "integrity": "sha512-OGGrpQBKbIfbX5ZDfZezCR2i1TErNopam0rUowuUl/etaiXv6Q8+1qdDPisJUR3OJJkSIXmiDhjdgJ+z/f7nFA==", "license": "MIT", "dependencies": { - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1132,16 +1132,16 @@ } }, "node_modules/@fluentui/react-badge": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.5.2.tgz", - "integrity": "sha512-+UPAK9dCD6Gx+LWr6vqKMIbYOPf7oXX+GXRtCJ5fekCTHD0VgIWuIMuEtxVrHpJQdb2VNaZadY8/dMomk2JaXw==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.5.3.tgz", + "integrity": "sha512-pMvzFTrMP/CvgDzne281pXyrBjSeiFwKRYuAa9Y1NkqK+H5wI0U/SsZu81mAuUA7vRxxqHkqtp5J2/huVK1yEQ==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1153,20 +1153,20 @@ } }, "node_modules/@fluentui/react-breadcrumb": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.4.1.tgz", - "integrity": "sha512-XgUB1yv04GdcL/6kUo6kh+BaN4df1A/Ds/fL1QxNrm5E26Vmvvlc0LN0WV/qb5qhKx0NwhtIXgOZHjfzyt7iCA==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.4.2.tgz", + "integrity": "sha512-IpLlrQkvFnQ7kMzRaVn6lmfb6gDUwRtnMDfhLTfUiJkisvuqdZGeilGTH1Yx4JLqBzCQGnRHMjcYm1DcrwX4aQ==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-link": "^9.8.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-link": "^9.8.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1178,19 +1178,19 @@ } }, "node_modules/@fluentui/react-button": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.9.1.tgz", - "integrity": "sha512-WNzpseiVbqEKKevTkAnyHNoK/8ktYPE6rvf31gGvSDnBBclqfrn4PSYG2ppi+Z7abmClnaNFxpp1OHuOoVQ8Bg==", + "version": "9.9.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.9.2.tgz", + "integrity": "sha512-zQ6EuJCb3hQ7d62lrn+wI3C9ugbi3M1d98SjOmj4WW/xG9gOKIZ+xjg6AYtAm7L94I/6JZbe5al2NvtejQWsHw==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", + "@fluentui/react-aria": "^9.17.12", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1202,18 +1202,18 @@ } }, "node_modules/@fluentui/react-card": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.6.1.tgz", - "integrity": "sha512-KBijjAxi0mBDSgnA1OCglqAVWc+Q0L7A2wCokszX/53oqfJPSvWxWFma7esz9b5MF/kdRrAR0vmy7MiosepNLQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.7.0.tgz", + "integrity": "sha512-OWfkDlCNbxbap5W5TIc+fpSEWnArug2+47yYx2DnSiUkJ+/bSdqBvGAPlQjlONV/fuA/HPWBpsni4Ao9nZicqg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-text": "^9.6.16", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-text": "^9.6.17", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1225,21 +1225,21 @@ } }, "node_modules/@fluentui/react-carousel": { - "version": "9.9.7", - "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.9.7.tgz", - "integrity": "sha512-lummYk+tASL/rM/SXWruoqhUAyJjTiOMgiCz55ncE3q2pSZe/EbsV5WfRw5B3y7pHX8xLusN831TBgUthj/sUw==", + "version": "9.9.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.9.8.tgz", + "integrity": "sha512-NaC7SVZF+dk1xV9FU9hsqQvoXrAzP6KMEcbzW7HLrQfM/qDyA2ERyYPZXeho24mvg4KXDalzEBwHxctASsA8iw==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "embla-carousel": "^8.5.1", @@ -1254,19 +1254,19 @@ } }, "node_modules/@fluentui/react-checkbox": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.6.1.tgz", - "integrity": "sha512-Rsf3TmcNrzLuHan9lyUFUmMZnNyvS7DV8C4Vc9lZnZTFRBo94GRMGzu0BcWKFbr3cCDT/r5RmIyQYz0kc7Jd2w==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.6.2.tgz", + "integrity": "sha512-ONIvYhhIdwAuPD4V5CZYXXjeq0lAtpiwU0PSFP5JAabYrmPVnBALe8km1QFTSnz2pN70AfQsOm92n6PCUFbyrg==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1278,18 +1278,18 @@ } }, "node_modules/@fluentui/react-color-picker": { - "version": "9.2.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.16.tgz", - "integrity": "sha512-+H8Ea8dwoSeUCTLRpUiGLrRsNvBnlHplnwJPU0isp8jdAfrIM/savZTLj6o4rqNFpNHQqAXxGwNuUV9YfHoJuQ==", + "version": "9.2.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.17.tgz", + "integrity": "sha512-cp9WdlrP2miMVNn5s1vjNqJCumezP/OWwGI0TV9tRMO0DvGQ8R1xwbVxxTH/C/wsMYrVIHiJaagQ5U6nzk6XLw==", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^3.3.4", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1301,23 +1301,23 @@ } }, "node_modules/@fluentui/react-combobox": { - "version": "9.17.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.17.1.tgz", - "integrity": "sha512-ezgt6tfOKd3wlG6IHvWl0TPNPpfHRtnEwC2kuqHYH/r1nMNp9edFi8Ya3+1eM7oxai19XW0swt69GPwRu51FVQ==", + "version": "9.17.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.17.2.tgz", + "integrity": "sha512-uYFelRhb+3BOwAIm4lvCfvrIBBi2Q5A66jzTXwZaH4rg5wrTWkpv+eSVkHF5gfcxzoEYRy1Ze2Tf1B2DtYYJyQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1329,71 +1329,71 @@ } }, "node_modules/@fluentui/react-components": { - "version": "9.73.8", - "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.73.8.tgz", - "integrity": "sha512-JG4KQjEvRRfPlh4yt6Rv1/k87ydM2y49r5XPNCnuYHahA7kEM+dY8JdOI7n7FW8bdcvZ7qt4smDrQ2XcPfmxlA==", - "license": "MIT", - "dependencies": { - "@fluentui/react-accordion": "^9.11.0", - "@fluentui/react-alert": "9.0.0-beta.139", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-breadcrumb": "^9.4.1", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-card": "^9.6.1", - "@fluentui/react-carousel": "^9.9.7", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-color-picker": "^9.2.16", - "@fluentui/react-combobox": "^9.17.1", - "@fluentui/react-dialog": "^9.18.0", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-drawer": "^9.12.0", - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-image": "^9.4.1", - "@fluentui/react-infobutton": "9.0.0-beta.115", - "@fluentui/react-infolabel": "^9.4.20", - "@fluentui/react-input": "^9.8.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-link": "^9.8.1", - "@fluentui/react-list": "^9.6.14", - "@fluentui/react-menu": "^9.24.1", - "@fluentui/react-message-bar": "^9.7.0", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-nav": "^9.3.24", - "@fluentui/react-overflow": "^9.7.2", - "@fluentui/react-persona": "^9.7.3", - "@fluentui/react-popover": "^9.14.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", - "@fluentui/react-progress": "^9.5.1", - "@fluentui/react-provider": "^9.22.16", - "@fluentui/react-radio": "^9.6.2", - "@fluentui/react-rating": "^9.4.1", - "@fluentui/react-search": "^9.4.2", - "@fluentui/react-select": "^9.5.1", + "version": "9.74.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.74.1.tgz", + "integrity": "sha512-N7BDd3g3A/ngxq8LKLD9ovd+3eHlOgo6R6QFPxA5pVYvznGSQlg00zQ2WxMz7jxQ8ADdPZYIsc7cfg80og3ckw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-accordion": "^9.12.0", + "@fluentui/react-alert": "9.0.0-beta.140", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-breadcrumb": "^9.4.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-card": "^9.7.0", + "@fluentui/react-carousel": "^9.9.8", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-color-picker": "^9.2.17", + "@fluentui/react-combobox": "^9.17.2", + "@fluentui/react-dialog": "^9.18.1", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-drawer": "^9.13.0", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-image": "^9.4.2", + "@fluentui/react-infobutton": "9.0.0-beta.116", + "@fluentui/react-infolabel": "^9.4.21", + "@fluentui/react-input": "^9.8.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-link": "^9.8.2", + "@fluentui/react-list": "^9.6.15", + "@fluentui/react-menu": "^9.25.0", + "@fluentui/react-message-bar": "^9.7.1", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-nav": "^9.4.0", + "@fluentui/react-overflow": "^9.8.0", + "@fluentui/react-persona": "^9.7.4", + "@fluentui/react-popover": "^9.14.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", + "@fluentui/react-progress": "^9.5.2", + "@fluentui/react-provider": "^9.22.17", + "@fluentui/react-radio": "^9.6.3", + "@fluentui/react-rating": "^9.4.2", + "@fluentui/react-search": "^9.4.3", + "@fluentui/react-select": "^9.5.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-skeleton": "^9.7.2", - "@fluentui/react-slider": "^9.6.2", - "@fluentui/react-spinbutton": "^9.6.2", - "@fluentui/react-spinner": "^9.8.2", - "@fluentui/react-swatch-picker": "^9.5.2", - "@fluentui/react-switch": "^9.7.2", - "@fluentui/react-table": "^9.19.15", - "@fluentui/react-tabs": "^9.12.1", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-tag-picker": "^9.8.6", - "@fluentui/react-tags": "^9.8.1", - "@fluentui/react-teaching-popover": "^9.6.21", - "@fluentui/react-text": "^9.6.16", - "@fluentui/react-textarea": "^9.7.2", + "@fluentui/react-skeleton": "^9.7.3", + "@fluentui/react-slider": "^9.6.3", + "@fluentui/react-spinbutton": "^9.6.3", + "@fluentui/react-spinner": "^9.8.3", + "@fluentui/react-swatch-picker": "^9.5.3", + "@fluentui/react-switch": "^9.7.3", + "@fluentui/react-table": "^9.19.16", + "@fluentui/react-tabs": "^9.12.2", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-tag-picker": "^9.8.8", + "@fluentui/react-tags": "^9.9.1", + "@fluentui/react-teaching-popover": "^9.7.0", + "@fluentui/react-text": "^9.6.17", + "@fluentui/react-textarea": "^9.7.3", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-toast": "^9.7.17", - "@fluentui/react-toolbar": "^9.8.0", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-tree": "^9.16.0", - "@fluentui/react-utilities": "^9.26.3", - "@fluentui/react-virtualizer": "9.0.0-alpha.112", + "@fluentui/react-toast": "^9.8.0", + "@fluentui/react-toolbar": "^9.8.1", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-tree": "^9.16.1", + "@fluentui/react-utilities": "^9.26.4", + "@fluentui/react-virtualizer": "9.0.0-alpha.113", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1405,12 +1405,12 @@ } }, "node_modules/@fluentui/react-context-selector": { - "version": "9.2.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.16.tgz", - "integrity": "sha512-D+/X2liT+eZe0rzXbwddPH333ml2SXz71biR13aeyGJQr8+W+icMAIsYhpwk0CC3KtJ3f1/CLTm7vcIrvqsJ4g==", + "version": "9.2.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.17.tgz", + "integrity": "sha512-pZGIz8vjK9nxHKmztV7y5T8yHseoTjm3a43TdPN6fhup0tlrGE/JUmVFEwulI3j4fMWqa0P2OhJoe+HrDMs44Q==", "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1422,23 +1422,23 @@ } }, "node_modules/@fluentui/react-dialog": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.18.0.tgz", - "integrity": "sha512-i+V2o0NJ1itjVADJFov5AR/JetpD2hCMiLye0vfi3/XsFMgEPZnGzILVxPCO/ovULTiCyThcL1UvY0d/PYrZfA==", + "version": "9.18.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.18.1.tgz", + "integrity": "sha512-tvi5MgUXY6yOySfKSEJobeBNwK3BOXVjRInxDz3ZM7g7FMMyzuf9HrXK/7caqMNRA9uQEQKFXKI9zD03L0kyPA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1450,15 +1450,15 @@ } }, "node_modules/@fluentui/react-divider": { - "version": "9.7.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.7.1.tgz", - "integrity": "sha512-ptymE6iADb/ugezulaMeoAfGxKSwOjHEHBh8N1ydOR3AoOxsSUPkvoPC0mReO/yV5Nas7pz5s5VuJTspmFz0hA==", + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.7.2.tgz", + "integrity": "sha512-rfzGQoGKtLBF5vxiJH2KhRiJGosozdql3d6eS7j11oRczgc5W/h38iLhiXuQzZHpkGaAOd3sY6sq4uGHJheOjA==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1470,20 +1470,20 @@ } }, "node_modules/@fluentui/react-drawer": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.12.0.tgz", - "integrity": "sha512-PUXeXUH6JqwpjqYphHesHl75UAFSvxQJQqrevMFHE78ZF0Cqn59Xpa+8hGwRSuoRcYa90jjfHzJOOjN0iNM2iA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.13.0.tgz", + "integrity": "sha512-Xeh9kW8SiNXobx+5AUb4UVYsaqpE9uqrqFwsb5Z47oupX3zRLw7UCh5rVbJoXowZRc7z6K1FViyORqpsOXnzJw==", "license": "MIT", "dependencies": { - "@fluentui/react-dialog": "^9.18.0", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-dialog": "^9.18.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1495,18 +1495,18 @@ } }, "node_modules/@fluentui/react-field": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.5.1.tgz", - "integrity": "sha512-u8J2d3AWb4yZXvy/mQd95y2lTon890RfybBTCbeBUzApGMI/77WqT5pRJ+zTM3lOMToPHVKylchNFusMpJaX9w==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.5.2.tgz", + "integrity": "sha512-5pZXGtDVXCkoL3/sRMyhCcPd6+TDR9/wYG7/mK82BDuX4viuoSr5llcQ1PkdcXMixFFU+nXa39l7/BLP3f6W8g==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1518,9 +1518,9 @@ } }, "node_modules/@fluentui/react-icons": { - "version": "2.0.326", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.326.tgz", - "integrity": "sha512-iSN6YggrrQyZ46Jxk998Umm9jehWs6mrqCsrAvr7+uZWY6IwfYcoz94NCJ2SDiMO8Jompl4Y4Yu73SwljuUULQ==", + "version": "2.0.328", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.328.tgz", + "integrity": "sha512-HAotR2QQjff1WJmm+QeSIU+3m1SOiz9D2M+u8M+8FWyRsyHjbOpBV9QUrABBH9z9JxyYYOvzLamjHEkIgGKLUA==", "license": "MIT", "dependencies": { "@griffel/react": "^1.6.1", @@ -1531,15 +1531,15 @@ } }, "node_modules/@fluentui/react-image": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.4.1.tgz", - "integrity": "sha512-yNd2Wq2xq952UUEVBkWeEmM7bTKdWx6BnsHPYRf0kdTADox2PquApYXsI1xw2pnAh3GSjARrGi9Eto0qxouLqA==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.4.2.tgz", + "integrity": "sha512-E7bOTFds8qoMiT/YDe2+ZL5h13u7M1bm8yoGFfeTw0fmE9Q0gtrx2WzJB/1ZV/4MTmjnaO9Dgx7ysTYxc3RWRw==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1551,18 +1551,18 @@ } }, "node_modules/@fluentui/react-infobutton": { - "version": "9.0.0-beta.115", - "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.115.tgz", - "integrity": "sha512-b+4B0ODzPEb4jNaW9HdT6VVt3CL5FgPL2yuKzALBsYVl3udJdFpyxHsZEPf3JrVTBL/rgF2fRI1iAioX6Fl7DA==", + "version": "9.0.0-beta.116", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.116.tgz", + "integrity": "sha512-bnL8hRs9K8xCKvJU49F0UxcRankGb2sr+KYezdrcrgfbePrh8kyJTFGmxKQSgka8P+SySE5DxFwb2RbfpTjmnw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.237", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-popover": "^9.14.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-popover": "^9.14.3", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1574,19 +1574,19 @@ } }, "node_modules/@fluentui/react-infolabel": { - "version": "9.4.20", - "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.20.tgz", - "integrity": "sha512-w4FOnNP+CtbVdKBEO6wXAcmOuPZWvmB/BJj+7J/8cLAQm7+4kQgitFHncU6rtFhPdGbikVoBf707/0R1mA4aIg==", + "version": "9.4.21", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.21.tgz", + "integrity": "sha512-FDpbxwdEztarJ63NmHCQP5n2XXKvyVgkdIVQIbkVslYqfooy2kql8Q0+5brRN2IsjQJRZ0MpSFRoJSNVT8rJEg==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1598,16 +1598,16 @@ } }, "node_modules/@fluentui/react-input": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.8.2.tgz", - "integrity": "sha512-t9zmqZR4bqeRjpWuCGfI4yrtPoCXFiK2XO4BoV5nNwAesglgz4+Vtso4YXst9QYEAazHtKI73YFJf1mn55hCuA==", + "version": "9.8.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.8.3.tgz", + "integrity": "sha512-nnApEcsPXVXCZZl9qRpS9hc2hy18btUtbG188TYM1FAynqjx5zZC9Ww5/6IOrGT8d12nDxxTu9dp/xqMZtUbbw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1619,12 +1619,12 @@ } }, "node_modules/@fluentui/react-jsx-runtime": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.4.2.tgz", - "integrity": "sha512-y3o0PBg2qzSdvgxDm7rH9BWq7E1h/eUWS+IhjQhd9dRpme6Py01+OLOglHojM5Tc9QjIp2Rjy2mFWBHXOR+8mw==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.4.3.tgz", + "integrity": "sha512-1QwEgITME+X24lnS68pQlU/b4BBdeS7oPdApwwoYQuAGKvImDY2nLAJt8BoHYKs9VFeX5ySEKPRM0rKXGq3EWQ==", "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1633,15 +1633,15 @@ } }, "node_modules/@fluentui/react-label": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.4.1.tgz", - "integrity": "sha512-4O3cPX6dSJVBKlIEbznjJ08utEc98lKbZz/6MZTTQfFgYl0TxAhxEDsIIIyNjj0Xy9eJpqubJsaswucWXTG/qg==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.4.2.tgz", + "integrity": "sha512-FfbOQf5caDA3yc/wukbKY0p6Pv8wkzre7E480VxqTgKrMm12KUoT+0+2S7vi0eCQJCW3pL8XjzVTbGIn8KDE8A==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1653,17 +1653,17 @@ } }, "node_modules/@fluentui/react-link": { - "version": "9.8.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.8.1.tgz", - "integrity": "sha512-ZxrCeX4pMWHujdmYV8b0QW0ztLtu0rHHvRNx67Y3WqSijVyij8QtNNiZ/nab+UDNlz9t8QIXKdWQgYj1uKDpMg==", + "version": "9.8.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.8.2.tgz", + "integrity": "sha512-PDziHdvp717LFc7BgxXDVldnq8UFtyqWM4ZWr0772XtuEc08jVU3MxKMUEsGOclqLRKGyjd0nG7IWKREuSETcg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1675,19 +1675,19 @@ } }, "node_modules/@fluentui/react-list": { - "version": "9.6.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.6.14.tgz", - "integrity": "sha512-B1mUQFvJOUlZysSduVnATNZggrGpgEWnW9ZSJAZ17LM0+9nWEQRi40jpUGI/d3PGKHt5O2df78s+1nEPAk0L6A==", + "version": "9.6.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.6.15.tgz", + "integrity": "sha512-mb2yVQC2gfILLFOZAxsYwo70YgoyacR52Qy2EGuB4wZOQtZ9KMZIOUFlQIztJBSxNIfo869/bF8EUWsVDaTeYg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1699,24 +1699,24 @@ } }, "node_modules/@fluentui/react-menu": { - "version": "9.24.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.24.1.tgz", - "integrity": "sha512-NLB5EhzKFiwax3O5JTRTtsqdEFDGEXzEuP/suyxNAaaQsIuXygo//Rmdq6dSn7GybTpEOZHKxYDyyG7dj+a4YA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.25.0.tgz", + "integrity": "sha512-aoBlNLv8Ngr9wBiOEhvYVOSLfeen2vvdAdZM10OjJ+mo9uhdRxF4m0Uqd8mcp0bpGf5/Cnz9FIZjdgc5krdwyA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1728,20 +1728,20 @@ } }, "node_modules/@fluentui/react-message-bar": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.7.0.tgz", - "integrity": "sha512-ICFDxZ62r5OG97/FcfK1EfJPxGlyDNyFixLD/a3gOREvEcT/hyZgnlUM9Y30u92HjxChx2SwGWnv3iaQPsvToQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.7.1.tgz", + "integrity": "sha512-8ImzffgVF/DJacOCiP1x75GQHE0wdB+3QoRkGKsgOZcqn6JOXzCEYvM0JplietUsNczmXRtXx9ZE+Otl6HPOHQ==", "license": "MIT", "dependencies": { - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-link": "^9.8.1", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-link": "^9.8.2", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1753,13 +1753,13 @@ } }, "node_modules/@fluentui/react-motion": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.15.0.tgz", - "integrity": "sha512-ZNQHYzE6MRbLQFT08/mrcqQ9k7F5niktRP93X1v/kmwKfPjvdDofySfbhQXQs3zQw600690C9rfJTKUd3h+zlg==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.16.0.tgz", + "integrity": "sha512-ZhbeRfir3V6+2kQjRqF2Bp8jwZd6TfmA9y1c6IlglsB8aNAbhnewYJsYXLrbZ+gwloiDdf46cVDqWYv5VFAgpg==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1770,9 +1770,9 @@ } }, "node_modules/@fluentui/react-motion-components-preview": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.15.4.tgz", - "integrity": "sha512-gAHPlyEYylZzUSGwc68VaB+vO8CTX6tgIA3d2+jFrpcwvXZjsdCpF1w1zK1+hTuiipmEaZLZyBz0e0CKH2+3XQ==", + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.15.5.tgz", + "integrity": "sha512-AhDw4/6fjIDWPwx8L1vNDYu3GBJYkyAazNHNrowoRsuxZHn0vK5TMUacT4UW6/QbByCk1x76TLv+CxmwU75FPA==", "license": "MIT", "dependencies": { "@fluentui/react-motion": "*", @@ -1787,25 +1787,25 @@ } }, "node_modules/@fluentui/react-nav": { - "version": "9.3.24", - "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.3.24.tgz", - "integrity": "sha512-OlB5k5Zev5VNjSRfJvJLO09Hjcv2UHAjLpSVa6gKHx+1NqqSJWZeDLSF7r+/nyZ4CWP5jWZYq7whEu3WvzdVZw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.4.0.tgz", + "integrity": "sha512-gyrXwT1NFfRT4WoVXrz7656tuFOmhFgCw1OBmb+0igftXmSxz6XMIj8MlwfUv2/VUymAU4Hs0p3rZwE4l81KKA==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-drawer": "^9.12.0", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-drawer": "^9.13.0", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1817,15 +1817,16 @@ } }, "node_modules/@fluentui/react-overflow": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.7.2.tgz", - "integrity": "sha512-5PA67LgnVmbbOzBN2H5gH3OvSVy1373VJfsHq2+6TLCfm+LXAkWBoFwvBuFI7HsMYae9A0FVlgX7gTsKVfMddw==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.8.0.tgz", + "integrity": "sha512-6lHvfcRNFSnOIrKHUzWc/WCKvSp5ivH8QP/stzyCUyzJpDde8uAbRMfg2iDFgJ8wlySP29BoPiepaH9bHgVLdQ==", "license": "MIT", "dependencies": { "@fluentui/priority-overflow": "^9.3.0", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1837,17 +1838,17 @@ } }, "node_modules/@fluentui/react-persona": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.7.3.tgz", - "integrity": "sha512-OY3xpSD6l4NDdeKihriC+H0q6P1CA2xyZ+pe/WwfKPnatxs2BALoRFtDQduMO7AK/j0w7UAxnaZrvEeftLen2g==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.7.4.tgz", + "integrity": "sha512-CtYA3aElMwTrhZcvdtrSIHWOzZqFcpJlfjchNNFTtvvFvrLGw65/1UPzLf/IUVBD1JO0XLGyQFRLUg/g+rtBfg==", "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1859,23 +1860,23 @@ } }, "node_modules/@fluentui/react-popover": { - "version": "9.14.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.14.2.tgz", - "integrity": "sha512-EDvzLkT98/vcCSGrcZWUACGsvLjrHin0Xf9eowMQKiiHFWbu8HNRmr7W2XB9Eja1W5HSIK6+mV8ro9zrLibG4w==", + "version": "9.14.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.14.3.tgz", + "integrity": "sha512-wR73yLdMm3/pJ92xJEeRnBAJ8tNvNv0LTSmaZvwbTgdcMT1zqfSyNO37qE7a8z+4bcp8kjyM8FR9NRqkr8OYdA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1887,14 +1888,14 @@ } }, "node_modules/@fluentui/react-portal": { - "version": "9.8.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.8.12.tgz", - "integrity": "sha512-+WH0wH/5lsodGP6Mam1alHXpkMCYA5uMcnF98RVOs7/GR69KiFcza1mCnvPJUaJ55AfwLuz/xLxuWdWgQnUdMQ==", + "version": "9.8.13", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.8.13.tgz", + "integrity": "sha512-a4EEt3KMzvW6qMk97K/8TQegmO8Ba4C2TdR7ke7g1SsEDmJGwwOD34hCwVxGi8LtxLcpAEdOx++brXnPsk5+Zw==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1906,16 +1907,16 @@ } }, "node_modules/@fluentui/react-positioning": { - "version": "9.22.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.22.1.tgz", - "integrity": "sha512-/r1BHQKr/WCjEM8UGloiq7bWWBSYB/Uqt7D1sAF9EHd968VH07cAN3RMVKmWWjeJO31rstOZHdgcz0WHhFF+2Q==", + "version": "9.22.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.22.2.tgz", + "integrity": "sha512-Pmio9+lDN+rF4k0mHVXqX6W0+A0ym0dje92UVfXeuassuIuJpKfvQg1xLpgQPrGRbgERr8KgA04xQVoJKaZQmA==", "license": "MIT", "dependencies": { "@floating-ui/devtools": "^0.2.3", "@floating-ui/dom": "^1.6.12", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "use-sync-external-store": "^1.2.0" @@ -1928,17 +1929,17 @@ } }, "node_modules/@fluentui/react-progress": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.5.1.tgz", - "integrity": "sha512-EXJ/Bp67d5+bXPNpPabxdtXUgCMTtvYrBoKtIS6wE5KeUzaek/rgQ3v5wnGfbuLnJ4J/kj+n7XQEc9fhoFPy9w==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.5.2.tgz", + "integrity": "sha512-H2t9Q9qYPm5gGb68RiIukFAZn/IxgoxcpKwZ+AjXKCly0C8x8EWCpyQSdfvswaGbcx7H6fe3SpKytBAAuvOOtA==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1950,17 +1951,17 @@ } }, "node_modules/@fluentui/react-provider": { - "version": "9.22.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.16.tgz", - "integrity": "sha512-S77n5ASUWE/V1I6lX09CrHm4TAKSGENhIrKz9qMKDv2Vrq44/j3eGBLz12k8IW4TJVu9nwGwst9kBpCT+3WHpA==", + "version": "9.22.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.17.tgz", + "integrity": "sha512-VIguLw2Ez9qxYCzrwKe3ttIcIbRdi7qpafImLNdpIAWRacIHw1AXSiDKcL6VFfE1+NxfQEy655wqYABi+7pJfw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/core": "^1.16.0", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" @@ -1973,18 +1974,18 @@ } }, "node_modules/@fluentui/react-radio": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.6.2.tgz", - "integrity": "sha512-Sp2us4eWRopUKOMCQw5/iks7euPKY6FeesBCCUIVGBg5VKZf2/CfEtbCa9hMjn4D4PCHGivnUTf23t238mvvnw==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.6.3.tgz", + "integrity": "sha512-U+funQQvlcOe3BQevUlkxsCoTQKFjw3Z/wnoAXNaNr1lTLIZnB+nesLA3ovZFWyOGTTJ2Mfa+vYpLbyyEpS8eA==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1996,17 +1997,17 @@ } }, "node_modules/@fluentui/react-rating": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.4.1.tgz", - "integrity": "sha512-DfWipzrT44j+yaShtfHz96/vHEa5ut5IR1kobrO0bSqAcpetOn327gFeY+sG/W6xzork/STcy/T836yK8A2+DQ==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.4.2.tgz", + "integrity": "sha512-jVHv9GFKKhzH1fai4/1ArG1xjFAU/PFsY8UkBikt3LQDL5Cuw2S2uIBanso0AllNwmwaImsd5xb1Uo8mfMayBw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2018,17 +2019,17 @@ } }, "node_modules/@fluentui/react-search": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.4.2.tgz", - "integrity": "sha512-PIb50euHoMsKWLqFymf8wo/+z1jrx1MB7uNuhjNT5DvwTP4VYAy5EtRCSwVRyxWNSaWSL6iy6dDy517EQE96mA==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.4.3.tgz", + "integrity": "sha512-wKRakuodG76MTu2v/8PZiXA3SUFaMJhdJ5OjoVh5TpFtoYnzwJmiyW2TlgDuod2rk2fpJ3v34C6wkdx6tW8oZw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-input": "^9.8.2", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-input": "^9.8.3", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2040,17 +2041,17 @@ } }, "node_modules/@fluentui/react-select": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.5.1.tgz", - "integrity": "sha512-8GocQKiUHEUlAks6zA0HbGGSF2lpjuSZuxPzIBqTyuWof8vFiK6eFAcSXb0hTYIVH3RsTihhfc6G3NRnHoBrzg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.5.2.tgz", + "integrity": "sha512-kbLbF8DAXsbb2UwJxVzV5tS9fpSX2RZdFPZYosvQly6+h5kTojVFeZRrSkyMPYRCkTMVENdAeyahdx4ESa5qHw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2076,16 +2077,16 @@ } }, "node_modules/@fluentui/react-skeleton": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.7.2.tgz", - "integrity": "sha512-PrUgdSGDAZw9FIP5NyvPoPfHDe2N9VxMyBfyTwWfZVg03dzRfnE3vEqr7N5xyfv4JsRs6u1xSqVn/0jdS0IEMQ==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.7.3.tgz", + "integrity": "sha512-4YhAux0OaYs/91xz/K25pNQxFbdQ2FcDRnwTpgsCDFH4XGQtA+rxBsLA5il3chIf++bNWr/78c5PHp6tZQuCDw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2097,17 +2098,17 @@ } }, "node_modules/@fluentui/react-slider": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.6.2.tgz", - "integrity": "sha512-lVavtTg8eqovfRokeYDk4popwCi8nuicacJ/HZdF3ni5e3y/2WT/bVP0eErS/GvC7+90ACQQ8uxdr4sjjY/HWA==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.6.3.tgz", + "integrity": "sha512-r0AP/ZqyMpVEEniIMjQ6AH5DZeCZ/XypBw+21D6mtjiy9vCg0A9lU8U+ay2Y1RyQY4PCShsUVSOb3bNTSTVUxQ==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2119,18 +2120,18 @@ } }, "node_modules/@fluentui/react-spinbutton": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.6.2.tgz", - "integrity": "sha512-P4vvJH7P5yHPFAv6aSo3dZxtErN62DiRJN+nEKS+/XBoRGsOGQdqyyx5Q/PQKOmyQrtwuZdXNHUjcyv8b50T2w==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.6.3.tgz", + "integrity": "sha512-wc3GjEB3vBz8uO+Jmdch9gk5effGz6ld2SrfmpHjfTGgww9qIj5S+WbSPZjAKgtqZw/f597DMpiplRE1kvqn/A==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2142,16 +2143,16 @@ } }, "node_modules/@fluentui/react-spinner": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.8.2.tgz", - "integrity": "sha512-0LxykLJGUD/I3XEeIXAWznwdg9XRe0piaByR0nLFOOV3UPwkVc2w5UdPhy2Y0NZDvtPHbNaMCuQAq82+bxg/0w==", + "version": "9.8.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.8.3.tgz", + "integrity": "sha512-knnL3Yx/qC+YoYPLCQLE5iHeNMwj3bLBQrksk85lQK0AFy1rOs8rTQuxUtjg9icn5BOFExhSDOYVwp3diSt1ug==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2163,19 +2164,19 @@ } }, "node_modules/@fluentui/react-swatch-picker": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.5.2.tgz", - "integrity": "sha512-DK6UU9OJY9XaGBPU2ROx+B5/7XdwVtHBdVthOAptyKSsYGOdQt5AQqg3ZOXH6r5WYbMRQDuP2OZ2iKtwidFCVQ==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.5.3.tgz", + "integrity": "sha512-AiybFcvA6in1piIsPn83Wm+w5bOnLlWmqrHiTDFnt6bYb8j2MJZ+dratJVZRtidqlEyfcMS3SByLooaVzwLRLQ==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2187,19 +2188,19 @@ } }, "node_modules/@fluentui/react-switch": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.7.2.tgz", - "integrity": "sha512-j3e5se+3d+befV9MytkxxvJ9nHZOeZ7thKDTF4YVSYf6kcNx9eOlLvPgDjhGO08gzngO4B7aaprhDN7DJc3W1g==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.7.3.tgz", + "integrity": "sha512-/eCYAtaoyUF//6F/OdOGj+GhLtkeJMXJUxaRPiDa6d18DX2eyoGaQ10175ysOjv4CbzIg8xH15flgpB4qUUstQ==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2211,23 +2212,23 @@ } }, "node_modules/@fluentui/react-table": { - "version": "9.19.15", - "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.19.15.tgz", - "integrity": "sha512-OdQ2Nwx2nAlPMlJeyAFrKa3Zy5Ya/H87OU8MvtFJhabM/FkHiZoli/DO1mavVI+jqavOlJuQWmJ55D6jjuGa7g==", + "version": "9.19.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.19.16.tgz", + "integrity": "sha512-SdwpJIHwCGg+ALOhZRvixkQhWSakXDgpDGe/OWwv1PiLDPxnBh+gUd+MtveryFaX+WvJvLWzx3u9O1ogQXKx3g==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2239,17 +2240,17 @@ } }, "node_modules/@fluentui/react-tabs": { - "version": "9.12.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.12.1.tgz", - "integrity": "sha512-WvzOtpC6C/7Mo5X+xmE+3stpCbx2iH9BqrEN5KuGrsHJ78DjMDeabYeL90vlrHBdP4VlTpwdORBui/jtWkxnmQ==", + "version": "9.12.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.12.2.tgz", + "integrity": "sha512-k2WsKmNQvFtNSywAb/VxXXlFdLC9fjRaRV4Ha7qDXucXuTCI1eKJuaAteePZiMAByv+AbRqRHevv5k2KMabxrw==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2261,18 +2262,18 @@ } }, "node_modules/@fluentui/react-tabster": { - "version": "9.26.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.14.tgz", - "integrity": "sha512-WibgoF67hl6BXfmsY6RSIWSHadeMP/6EDG9gAacfHlwKvK0+FiHp5ernwuXTPAmu2kiHicn2qUZ8EteCFiFryg==", + "version": "9.26.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.15.tgz", + "integrity": "sha512-SugQlqXsMueTojtvPU/RIoZg6WaV4bw++NhLjnF7dFvD61/w5pPsVSLCPsLJBD+oU5Kbgx2x3KFbI69kb+kNmQ==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", - "keyborg": "^2.6.0", - "tabster": "^8.5.5" + "keyborg": "^2.14.1", + "tabster": "^8.8.0" }, "peerDependencies": { "@types/react": ">=16.14.0 <20.0.0", @@ -2282,25 +2283,25 @@ } }, "node_modules/@fluentui/react-tag-picker": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.8.6.tgz", - "integrity": "sha512-sOZ+wBA3hgGhKrOP7wbjB2yRvAxjcRXtcj1jDTrtSkaDPXb3K0nGmjiqp2mve995ps3wvCGnNKK4EurX842ZbA==", + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.8.8.tgz", + "integrity": "sha512-GkBqUMAxJtOGRNFmkoi6Js4jxvQEc3JScUok1/UKThPHZeMfk4vAKT8aGVx9Sa/Ab4Akr5LhcjOt4TXHPQ2IvQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-combobox": "^9.17.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-combobox": "^9.17.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-tags": "^9.8.1", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-tags": "^9.9.1", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2312,20 +2313,20 @@ } }, "node_modules/@fluentui/react-tags": { - "version": "9.8.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.8.1.tgz", - "integrity": "sha512-6ZTW78fu5eWByKHIM3i+raDrX3hwfZ67ONfZ8wEUXfZHowskxqpMHI8Gw7IAMWkC1scgLqEnht8TnHvZgjo7Ug==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.9.1.tgz", + "integrity": "sha512-WY6Ye5TblwHnMIlRd0DgnPTCH+UyJBafr8bIOszi13KOkN3HFswY5syb4lbQUzP+EslAC5M5cPnJXe89TUXV+Q==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2337,21 +2338,21 @@ } }, "node_modules/@fluentui/react-teaching-popover": { - "version": "9.6.21", - "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.6.21.tgz", - "integrity": "sha512-V86zLB1B8xu3U/02FvvMdsJP+ZC9l3vT9bQ2Gr7hZHxJ4/0NLpVcrYSBFHpON9e/WK3p+A5b5V96p86b5Pavlg==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.7.0.tgz", + "integrity": "sha512-8oKts1w33JbLAgVNt7Ad5vidXsIpXyVkrPwo5aZW6oqEASJGEooAOx1od+bKgwZb2wyjq5/RXxdV22r13nqajg==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "use-sync-external-store": "^1.2.0" @@ -2364,15 +2365,15 @@ } }, "node_modules/@fluentui/react-text": { - "version": "9.6.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.16.tgz", - "integrity": "sha512-ZzCSJWQ6LrVuPqA6sqNEZaXbLvhi2NxBOtlMudWlqYzidLQp038d7mMGSzNnhyeblg+gj+bOVE2eOgWFuVHGYw==", + "version": "9.6.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.17.tgz", + "integrity": "sha512-SqWXOKJNF6EgG4/vZeurl7MqO9OckRwK6tvk9JJVs7kbqOky+d+t1gITaqk9yIOw6LJtb76vm8cZUvKUb0WSqA==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2384,16 +2385,16 @@ } }, "node_modules/@fluentui/react-textarea": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.7.2.tgz", - "integrity": "sha512-awlkZoW81WaOqSoXTT9rZs3mTAzCCHnC9eAm6J8ZxI5+ASX07BTolBfZ82it5wxOHI5GMDfbFOl+xIy8uAMdzA==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.7.3.tgz", + "integrity": "sha512-BNStqBKO2fe3h5VAIPs33/7xj8EAr5msmb9krq02XAmvDndt3aLrQdz25vVEMvbcuUCNQoFsPtN/PrR6nXTIHw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2415,22 +2416,22 @@ } }, "node_modules/@fluentui/react-toast": { - "version": "9.7.17", - "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.7.17.tgz", - "integrity": "sha512-DWA5EARWSo1k19iWAulLpKrcUHT+Dq/Bw9zfdpoQEWWybrAZwyN7WiYFkBjKCQRxSp10OjLASSQK91CXfb1wJA==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.8.0.tgz", + "integrity": "sha512-GsLeEjLCLZ+SM2yL4G/hsypecXPn4FK73sH3KXer7Q0MST+ldulcaW8nsppCwqBB6Zf5pwcRU4qnkWwFMQd66Q==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", + "@fluentui/react-aria": "^9.17.12", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2442,20 +2443,20 @@ } }, "node_modules/@fluentui/react-toolbar": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.8.0.tgz", - "integrity": "sha512-EIe+QWOaFR1pZzENefsFTmjxGa2yJb4A/by3kGuGqSjx7isqPUllPq0/kFQzfoUYgPDJbJtQ+KyuRDekTL0QpQ==", + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.8.1.tgz", + "integrity": "sha512-ZzjFwFElF3bCsHXgl6YfmHzfZn2gUDe7NoYl4qloHhGacrSStvOt0h94WRz0a5ur/VIG2PDROeBLkcI2MIZQJQ==", "license": "MIT", "dependencies": { - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2467,19 +2468,19 @@ } }, "node_modules/@fluentui/react-tooltip": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.10.1.tgz", - "integrity": "sha512-IPHBFjqGhaaMDhLt5NSNOE9LEpDOpT7qgEqNz+Mlflo0A4qI2LW/EnkNop7IRmX/bC88A+wUtEONTjjR87dNBw==", + "version": "9.10.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.10.2.tgz", + "integrity": "sha512-1qewqiTNKpbRuoINhytyaMoUsBLE4TRPXf9ilJnvN3UtN5TYtS/8Oe6zMocHEnCLETsFOyCn8sAlufWOo5efpQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2491,26 +2492,26 @@ } }, "node_modules/@fluentui/react-tree": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.16.0.tgz", - "integrity": "sha512-c+Q4AVaYk9U69aGDgmJVNne+CtWKS75YIfGoxs6+9+wE2Wqz4T0E+gE1ng7ARCQQgI7E2NEJlot6DuI6nYYrRw==", + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.16.1.tgz", + "integrity": "sha512-e87Fa+8ttbYh0XY4qxJ9NcmIWSfYouw8Rc68c10UczK2TcsWSII84cV9fHrbL7FtX8DlyncZuSjukoJYm5LD7w==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2522,9 +2523,9 @@ } }, "node_modules/@fluentui/react-utilities": { - "version": "9.26.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.26.3.tgz", - "integrity": "sha512-bXB3jMm/RroT8c5eGZkijkPbLd4MqMI6biBHjavo0e7OkZHv9IPfH2nDkGhSn5Sh8e6kRcX0IjYhbM10WUK2iQ==", + "version": "9.26.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.26.4.tgz", + "integrity": "sha512-Rg1kg0ZPFOBi6VtQNkgV+K3z3O7PY5QFJQ4Y+qkZv7a8fUSNkEK151coaGOLps4P77fY2DiHhqKqeOehN7vFOA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", @@ -2537,14 +2538,14 @@ } }, "node_modules/@fluentui/react-virtualizer": { - "version": "9.0.0-alpha.112", - "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.112.tgz", - "integrity": "sha512-dao/mQssaPFxCXMx7K+G/DrRoZg28kXcE1NGbJ1RPtbkVCzJgwrEEeDhM5/wyOXO/Z5EZ31FIerDDVOyr6FAaw==", + "version": "9.0.0-alpha.113", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.113.tgz", + "integrity": "sha512-MGmdlm+0HwwMypCpUCpddQjgKvZkL9oGvjXNcoIHYhMVy4WSc5ha8XqOxAo2cfWvKGN0jMiW3H3IebLdcFpd7Q==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2565,26 +2566,26 @@ } }, "node_modules/@griffel/core": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.21.0.tgz", - "integrity": "sha512-QqMoewiNTT0DmLM7OY607c7yhg18SuKfzovTO3hPXGQvtdu/StnjvuBAs+1B1kYSVGReAo6s/dJVeLnPuHjE7Q==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.21.2.tgz", + "integrity": "sha512-vDvEdbIe7OhU15UkvUHe+Ut2sgCZ5PBj/RYLFwjUtkXS4ewNK9P6b4YRFNI2zgaNYI7GOuZqG7DLyaQbUP3+jg==", "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.0", - "@griffel/style-types": "^1.4.0", - "csstype": "^3.1.3", + "@griffel/style-types": "^1.4.2", + "csstype": "^3.2.3", "rtl-css-js": "^1.16.1", "stylis": "^4.4.0", "tslib": "^2.1.0" } }, "node_modules/@griffel/react": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.7.2.tgz", - "integrity": "sha512-/+N+81e9ibNsh2wNlhGf2PcimEFrx8VbtWiLCmI6lsrTV5eBcQrIIDVQq737KPIJFtD4v6Txu9n0PXbN3hedNg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.7.4.tgz", + "integrity": "sha512-XsB+YOC4MOBg6GF5CJWJLf8ZI2AtXE8EvQdwJEmFNKX0cQu/An0azl3v9+sjA73zsIG2Wayo2pkT0JANYnKauA==", "license": "MIT", "dependencies": { - "@griffel/core": "^1.21.0", + "@griffel/core": "^1.21.2", "tslib": "^2.1.0" }, "peerDependencies": { @@ -2592,12 +2593,12 @@ } }, "node_modules/@griffel/style-types": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.4.0.tgz", - "integrity": "sha512-vNDfOGV7RN/XkA7vxgf7Z5HgW8eiBm5cHT9wQPhsKB4pxWom5u6eQ9CkYE5mCCTSPl9H6Nd1NBai04d4P6BD7Q==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.4.2.tgz", + "integrity": "sha512-MsSghfpyxR2MpTrYdcCozISsSLkmFjNw94wNPi4bDBRLW8W43718W/ZjmUdVkoM0KXMtJPYuEkx8Mzibqb03qA==", "license": "MIT", "dependencies": { - "csstype": "^3.1.3" + "csstype": "^3.2.3" } }, "node_modules/@humanfs/core": { @@ -2693,6 +2694,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@lezer/common": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", @@ -2826,12 +2838,12 @@ } }, "node_modules/@microsoft/dynamicproto-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", - "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.5.tgz", + "integrity": "sha512-V+Zr7PDKIEaItVwF/OyWQlKeugNRYg7KJJ+RhEIL2FMW6NlG8FN2l4XA9Z42hNtsjwJFlcUiF38pmM/AaXsF7g==", "license": "MIT", "dependencies": { - "@nevware21/ts-utils": ">= 0.10.4 < 2.x" + "@nevware21/ts-utils": ">= 0.14.0 < 2.x" } }, "node_modules/@microsoft/vscode-azext-azureauth": { @@ -3026,18 +3038,28 @@ } }, "node_modules/@nevware21/ts-async": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.5.tgz", - "integrity": "sha512-vwqaL05iJPjLeh5igPi8MeeAu10i+Aq7xko1fbo9F5Si6MnVN5505qaV7AhSdk5MCBJVT/UYMk3kgInNjDb4Ig==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.6.1.tgz", + "integrity": "sha512-W2kFiT5oPuxTrB3NrxUId/U+1AuAhIaiDQkLC4HcxkjNc+85GfELYdPQXnsDWDG8yji24F5qk6QpBDxZX3/0+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nevware21" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/nevware21" + } + ], "license": "MIT", "dependencies": { - "@nevware21/ts-utils": ">= 0.12.2 < 2.x" + "@nevware21/ts-utils": ">= 0.15.0 < 2.x" } }, "node_modules/@nevware21/ts-utils": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.14.0.tgz", - "integrity": "sha512-WoeqTIXQ8WPhl+lD2NbMHoAQ4sJl0n7EoRoDmVJui//Usg512enl9q1fdbVobuZt3omnxnmVsDrNIvPBvFgddQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.15.0.tgz", + "integrity": "sha512-+bUMKIiKAgoW5uNEb5xxzBzdwdLS9SKRcOy8SxLE+KqSlIdUYV5O9nxJVq1RUYcO2DtL5DlrK1GbgcVEHv6GVA==", "funding": [ { "type": "github", @@ -3089,9 +3111,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.130.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", - "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", "dev": true, "license": "MIT", "funding": { @@ -3099,9 +3121,9 @@ } }, "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.51.0.tgz", - "integrity": "sha512-Ni0sCqg5CIHaLIYFGj+ncbcumylvNC6FE4rfD0KfdmnWHbPJ+zev0qZCXKxy2hFVa0fYRK0yPzf5nzPbkZou7g==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.53.0.tgz", + "integrity": "sha512-XfVM8AmIovBTKXCt14Op5wbfcoM8418nttd+nhMgM3RAVaJg1MtJc73FyWfUt0oxLyBGVwfniNVUsbV/b3VmPg==", "cpu": [ "arm" ], @@ -3116,9 +3138,9 @@ } }, "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.51.0.tgz", - "integrity": "sha512-eu5lAZjuo0KAkp+M24EhDqfOwA8owQ8d7wyBlOUUGRbDLHpU3IRlDHp8Dif+YqGlxs6jra7yS6WQu/NkPhAxeg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.53.0.tgz", + "integrity": "sha512-btHDfXckwdf9zgyAVznfZkf+GVyB0I1m1hlvaOMRx2xoyz3hphfPX97s89J3wfCN8QBETLtk4lQUaeOkrMuQOg==", "cpu": [ "arm64" ], @@ -3133,9 +3155,9 @@ } }, "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.51.0.tgz", - "integrity": "sha512-6LsUNIdURhhcIfIn8+xsOb61mSTa9msAHTeSGx9Jf4rsP/gN8PGCF+SKWPAQZbND2w/WBkqQ6303jqEEIXzMdQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.53.0.tgz", + "integrity": "sha512-k2RjMcSTkHjoOlsVGbL35JVzXL+oQco3GHPl/5kjebVF4oHNfE24In8F5isqBh9LBJucycWHKDXdGrCchdWcHQ==", "cpu": [ "arm64" ], @@ -3150,9 +3172,9 @@ } }, "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.51.0.tgz", - "integrity": "sha512-9aUMGmVxdHjYMsEAW1tNRoieTJXlVNDFkRvIR1J7LttJXWjVYCu2ekclLij2KJtxBxSQOYSHd12ME/adVGVbZg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.53.0.tgz", + "integrity": "sha512-65jIBE2H1l5SSs16fmv6/7b6sAx/WpvnsgDhVWK9qSjNFDUro7MPQ6q5UhpY7kl46yltfR046iAnxy/Bzqbiew==", "cpu": [ "x64" ], @@ -3167,9 +3189,9 @@ } }, "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.51.0.tgz", - "integrity": "sha512-mkY1nhZTqYb+NHaAWxOCKISN6FwdrwMNsu17vTUA3wzUV2VJ+Paq15ZokRcsMU/2PUdHO73prxyeJpjXQ3MPpQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.53.0.tgz", + "integrity": "sha512-oYe1gkz7U49PCYrS9147d2fJZj8mDI4Di6AvlsU5fu9p+Tq8S7qqOMSZjUiVTLX8bXuSA9Lk/tIxuegVjkNYRA==", "cpu": [ "x64" ], @@ -3184,9 +3206,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.51.0.tgz", - "integrity": "sha512-wtFwNwE4+YCNuPaWoGDZeGsKvD6D1YSUNBJNn/rJBh7CrDBThFE+TBI5kY7vRW9rIOQRsbW2IpyyL3Du4Zqwiw==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.53.0.tgz", + "integrity": "sha512-ailB2vLzGi629tymdAb2VYJyEHref7oqGxP+tRBrtRBxQrb6NV55JMT7xtGZ8uTeG2+Y9zojqW4LhJYxQnz9Pg==", "cpu": [ "arm" ], @@ -3201,9 +3223,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.51.0.tgz", - "integrity": "sha512-rnOaNx86G7iRKM6lsCIQMux0SMGNC/TEbFR+r7lpruJ12bnrIWgxd5w1PLqOvgR9r8ZJbpK/zfRKctJnh8/Jfg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.53.0.tgz", + "integrity": "sha512-abh4mWBvOvD966sobqF7r103y2yYx7Rb4WGHLOS4+5igGqLbbPxS9aK5+45D6iUY7dWMsk3Muz9a8gUtufvqJA==", "cpu": [ "arm" ], @@ -3218,9 +3240,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.51.0.tgz", - "integrity": "sha512-jOgDzSqWcICGRjsp4mc08FxKMN8vzP2Kgs4E0d2HUP99F+nJDQKklRV4Zuj+0gcBgjrzx2CbpqaIdUVPepCojA==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.53.0.tgz", + "integrity": "sha512-z73PvuhJ8qA+cDbaiqbtopHglA91U4+y5wn2sTJJrnpB957d5P33FEuyP3DQIFd7ofljmDmfVT4G0CVGHZaJWg==", "cpu": [ "arm64" ], @@ -3238,9 +3260,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.51.0.tgz", - "integrity": "sha512-KBUCdrH5bwVrAvI9gU/1S55oH6fzXjr++J/oVocdu7bYTks1l7DNNT+rLd/1TDdAEjObGwmfWamn7LC1m8A0DQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.53.0.tgz", + "integrity": "sha512-I6bhOTroqc3ThrwZ89l2k3ivKuELhdPLbAcJhRNyjWvlgwb0vjRgEnVL1XLx5Jud04/ypNRZBykAWrSk6l/D+g==", "cpu": [ "arm64" ], @@ -3258,9 +3280,9 @@ } }, "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.51.0.tgz", - "integrity": "sha512-NapfjYsABFqTJ1Dn9Efq6sN5esaHconVKwVLbDGNQLrwpOx/g17mkwErHzU72PutL67nf3wNAkbq122H+zLxag==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.53.0.tgz", + "integrity": "sha512-w0p3JzB/PkkQjXALMJMqP9YfP3yq4w6zGsu5kezQmUnxRkN3b/Theg2l/nDgBsOcczxS3gL6Gam5XNAVrO6QJQ==", "cpu": [ "ppc64" ], @@ -3278,9 +3300,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.51.0.tgz", - "integrity": "sha512-5dlDt1dUZCVi6elIhiK1PWg9wpTzTcIuj0IZnSurvIoMrhOWqqTcc1dSTxcSkNaBZhfsNqRZdINI1zAgbKkJNQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.53.0.tgz", + "integrity": "sha512-mzBhF6k1Yq1K/dqDmVe/AAafnlJfEpx7yfUiksyeWXJk5iSzZqBSxcsa02zIytYgQFRZ7h6WPZfwHg/DoOE1Kw==", "cpu": [ "riscv64" ], @@ -3298,9 +3320,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.51.0.tgz", - "integrity": "sha512-pgdWUJn0S5nulyiVdlFV8DzCUnGXkU99W5PSkkmbaZW+LrZBPxpezun4G0DDHbQaVYuJeCuKsXsGKGo77CkUTQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.53.0.tgz", + "integrity": "sha512-AlFCpnRQhogQFzZXWbO6xB6/Udy745L+eQNmDPGg7G/OeWsYmJc4jZYfUN5pQg0reOPWSED2mOQqKZOJM1U8cA==", "cpu": [ "riscv64" ], @@ -3318,9 +3340,9 @@ } }, "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.51.0.tgz", - "integrity": "sha512-2XTFUe97CbDGAI8vjwDfZ1HdakO0XIADyJ24idEg64SC4/K4in/OisXVnrW4NMK7I6TgC7EqRhC0Ln/nKhAemA==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.53.0.tgz", + "integrity": "sha512-XD4ulY4f1DWbuuZXAqxhVn+gdPmrhnmojWtFN78ctVoupmS845fGhsUrk1HZXKQI+iymbaiz9vAjPsghHNQ7Ag==", "cpu": [ "s390x" ], @@ -3338,9 +3360,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.51.0.tgz", - "integrity": "sha512-kQ1OuCqqt/yyf0ZN9VFxW1/JnlgJgii3Dr7pWf9vNBvrX1hv6g39/+mc5oGRHRGJFZtl3zsGDWR9c5N2B/gwBw==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.53.0.tgz", + "integrity": "sha512-xg8KWX0QnxmYWRe60CgHYWXI0ZOtBbqTsXvWiWrcl2XUHJ3fht2QerOk2iWvylzX3zNT2GpvBRxGoR4d3sxPRQ==", "cpu": [ "x64" ], @@ -3358,9 +3380,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.51.0.tgz", - "integrity": "sha512-ARTYqxHF475o96Gbn41hvSWSSRygPlRDXZZgZ9I2scU1y0qiWpCQyZCoefaQa0mwv+wwtZ+luS4YOzsRzM/izg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.53.0.tgz", + "integrity": "sha512-MWExpYBGvl+pIvVB/gj/CcWlN2al8AizT7rUbtaYaWNoQkhWARM6W3qpgoCr72CYSN9PborzPmM5MIRe2BrNdA==", "cpu": [ "x64" ], @@ -3378,9 +3400,9 @@ } }, "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.51.0.tgz", - "integrity": "sha512-QiC1XrCl6a6BmqMzduO8hdIRMf1m44hCkt2Q68KWkTvUB/E7fd2iomyNh6KnnRca5w6eBrRAAtLFqTh+xjsjJA==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.53.0.tgz", + "integrity": "sha512-u4sajgO4nxgmJIgc/y2AqPhkdbOkQH8WugXpA1+pW0ESQhvGZ1oGq61Q4xMbJHJU1hFgtO18QNrcFYDPYH0gwQ==", "cpu": [ "arm64" ], @@ -3395,9 +3417,9 @@ } }, "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.51.0.tgz", - "integrity": "sha512-NC/hJb9dtU23Zf8L7IVK95xnFjiQ7AfcLO2l5pb69TDEr958qxrtnB2CveeeNSCBFNIkgaTCfd/vHNSoG78l9g==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.53.0.tgz", + "integrity": "sha512-Yq9sOZoIOJ5xPjO0qOyHJS4CiPuTkB2en9auxZz7Ar2p5RaC7BzLyVVmAA7zz9/L9YnjjY1DwNxN+ivKXimN/A==", "cpu": [ "arm64" ], @@ -3412,9 +3434,9 @@ } }, "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.51.0.tgz", - "integrity": "sha512-2C45za4Rj36n8YIbhRL1PQbxmXJYf81WEcAgvj5I4ptRROG+A+81hREEN5bmCHADE1UfYaN312U6tkILoZZy6w==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.53.0.tgz", + "integrity": "sha512-es1fVNZEkBqEcQtBpn19SYFgZF7FawlkCjkT/iImfEAus4gun8fBwB1E9hpV5LcR9B0DBNvRIXhW8BQk3JaE+Q==", "cpu": [ "ia32" ], @@ -3429,9 +3451,9 @@ } }, "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.51.0.tgz", - "integrity": "sha512-73RqdAuVKQTkjZIDw08JaDHUM4lav5Qu+CaPwg4QbbA7k8o7LEW0p3UsfZ/F8dsO/pwVYh3RzFcanwLRTTahbQ==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.53.0.tgz", + "integrity": "sha512-QFmJs2bEu9AO4O6qsmEaZNGi6dFq8N+rT8EHAAnZIq/B9SeJDUbc4DzVxQ48MfDsL7D3sCZzo37zuTuspcURgg==", "cpu": [ "x64" ], @@ -3530,9 +3552,9 @@ ] }, "node_modules/@oxlint/binding-android-arm-eabi": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.66.0.tgz", - "integrity": "sha512-f7kq8N51T4phpzqfBpA2qaVTI/KrkCmNwaj3t/97I/WLTDI+UhlP5GL9eER+zVxBhtlx5rKXWByJU1/zDAvyaw==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.68.0.tgz", + "integrity": "sha512-wEdsIspexXLLMCPAEOcCuFLMt6aE3AzTuA/nQKLPRnoJ+EQTturmGheDkhHuuVHx0GbutjQ3JKmEn+Gz6Ag28Q==", "cpu": [ "arm" ], @@ -3547,9 +3569,9 @@ } }, "node_modules/@oxlint/binding-android-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.66.0.tgz", - "integrity": "sha512-xu6QO71tdDS9mjmLZ3AqhtaVHBvdmsOKkYnReNNDgh+XiwnsipeQOIxbiYOOO0iAXycJ+GK0wdMSZP/2j/AmSg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.68.0.tgz", + "integrity": "sha512-6aZRNNXQTsYtgaus8HTb9nuCcsrQTlKXGnktwvwW0n/SooRWNxNb3925grDkC63aEYZuCIyOVLV16IdYIoC2aQ==", "cpu": [ "arm64" ], @@ -3564,9 +3586,9 @@ } }, "node_modules/@oxlint/binding-darwin-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.66.0.tgz", - "integrity": "sha512-HZ24VimSOC7mxuEA99e0H2FS0C1yO3+iW13jPRAk+e2njsUs3QeAXsafCDyaIrV/MirdOVez+etQNQsJE43zNQ==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.68.0.tgz", + "integrity": "sha512-lVTbsE3kO4bLpZELgjRZuAJc8kP98wb83yMXWH8gaPaFZ+cM2IDeZto4ByoUAYj0Mxv2rvw+A1ssZequSepVSg==", "cpu": [ "arm64" ], @@ -3581,9 +3603,9 @@ } }, "node_modules/@oxlint/binding-darwin-x64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.66.0.tgz", - "integrity": "sha512-awhj8ZvJrrRSnXj7V++rpZvTmnl99L6mi0B7gg7Cp7BN6cKpzuI481bHNLvXGA9GB1/oEgA3ponuyoAc6Md12A==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.68.0.tgz", + "integrity": "sha512-nCmw2XrmQskjBUh/sfP5yKs93V68LijQgjd1cuuZ/q4SCARngLYs60/qqyzuMsg8QQ9KArDI98hxs/RDGE4KRQ==", "cpu": [ "x64" ], @@ -3598,9 +3620,9 @@ } }, "node_modules/@oxlint/binding-freebsd-x64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.66.0.tgz", - "integrity": "sha512-KQF0oVV21/FjIqkRuL8Q1vh8ECsE5+ocdH5tcqTQ4ZnYuDVoYibQUNfqBjQaUsP6UIIda5Y75Wpm5p4RgQWiWw==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.68.0.tgz", + "integrity": "sha512-TI4ovQJliYE9V6e06cEv+qEI9uj7Ao65fmif4er4HD+aouyYyh0P31q2jh3KtqsOHHcQqv2PZ61TjJFLpBDGWQ==", "cpu": [ "x64" ], @@ -3615,9 +3637,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-gnueabihf": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.66.0.tgz", - "integrity": "sha512-9u1rgwZSEXWb30vbFZzQ78HVXBo0WCKNwJ3a2InRUTNMRng+PUDIoSFmA+m4HdUfBaIqftShq8J8qHc+eE/Vig==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.68.0.tgz", + "integrity": "sha512-LcNnEi9g71Cmry5ZpLbKT+oVv+/zYG3hYVAbBBB5X85nOQZSk8l92CnDkxJMcxUg0NCnMCOFZuaVDlMyv4tYJw==", "cpu": [ "arm" ], @@ -3632,9 +3654,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-musleabihf": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.66.0.tgz", - "integrity": "sha512-Ynot2HR1bHxUaNWoC280MVTDfZuaWuP3XfSMRDhyuZrVjhzoaBCVFlw8h8qeZjWKVUBhPWFIxB7AQTlK8Z2WWg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.68.0.tgz", + "integrity": "sha512-OovHahL3FX4UaK+hgSf11llUx2vszqjSdQQ61Ck9InOEI/ptZoC4XSQJurITqItVvd53JSlmkLMeaNjM1PoQew==", "cpu": [ "arm" ], @@ -3649,9 +3671,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.66.0.tgz", - "integrity": "sha512-xCbgzciGgo+A4aQZEknsNrNiIwY7sU5SfRuMmRjPIvZAgdF34cIHiKvwOsS5XRLjlTVSFwitmq6YclTtHTfU+g==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.68.0.tgz", + "integrity": "sha512-YbzTglnHLzzi9zv5or8Ztz5fykAoZE8W9iM42/bOrF4HBSB6rJTqdLQWuoP76EHQw9DuKl76K1QmFlG29sPJXQ==", "cpu": [ "arm64" ], @@ -3669,9 +3691,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.66.0.tgz", - "integrity": "sha512-hmo+ZB/lHkR1HdDmnziNpzSLmulnUSu10VEqX2Yex7OwvoBAbjJQLvy4gIBRV3AAwWnCvAxKp5Nv1GE6LU1QMg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.68.0.tgz", + "integrity": "sha512-qVKtCZNic+OoNnOr/hCQAu22HSQzflI7Fsq/Blzkw02SnLuv163k3kfmrVpZjSBlUHgsRKj6WgQiw30d3SX02Q==", "cpu": [ "arm64" ], @@ -3689,9 +3711,9 @@ } }, "node_modules/@oxlint/binding-linux-ppc64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.66.0.tgz", - "integrity": "sha512-2Invd4Uyy81mVooQC5FBtfxSNrvcX1OxbMlVQ6M2erRrNI2awFYF26YNW2yFxdVFZ4ffNOWKghtMjhnUPsXsVA==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.68.0.tgz", + "integrity": "sha512-zExyZ8ZOUuAyQ0y9jpTcyjKUz62YY9JhKPyVxzvjTpXzZ3ujdqiVwfPWDdnA1SsIOrxdtxHn7KErDHLWskFjXg==", "cpu": [ "ppc64" ], @@ -3709,9 +3731,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.66.0.tgz", - "integrity": "sha512-s0iXPDQVdgayE3RGa/N2DZF7tjgg0TwEtD1sGoDxqPDGrIXgo45H0yHknT0f9A0yteASsweYZtDyTuVlM4aSag==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.68.0.tgz", + "integrity": "sha512-6C4MPuwewyDavA7sxM14wzgRi5GGL68HPIxRCdVyS75U4MDbpFVYzKO9WNR6KLKTMPq2pcz3THwo1sK2uiqngw==", "cpu": [ "riscv64" ], @@ -3729,9 +3751,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.66.0.tgz", - "integrity": "sha512-OekL4XFiu7RPK0JIZi8VeHgtIXPREf42t8Cy/rKEsC+P3gcqDgNAAGiyuUOpdbG4wwbfue1q4CHcCO7spSve6w==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.68.0.tgz", + "integrity": "sha512-bnZooVeHAcvA+dH0EDLgx+7HY/DRi6e0hFszg3P+OBatuUjV6EvfIyNIzWOusmqAVh4L6r21GGTZtiKE4iqM4Q==", "cpu": [ "riscv64" ], @@ -3749,9 +3771,9 @@ } }, "node_modules/@oxlint/binding-linux-s390x-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.66.0.tgz", - "integrity": "sha512-Ga1D0kj1SFslm34ThA/BdkUlyAYEnTsXyRC4pF0C5agZSwtGdHYWMTQWemUfBGp4RCG4QWXgdO+HmmmKqOtlBg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.68.0.tgz", + "integrity": "sha512-dIqnZnJSmHCMOUpUcWQOiV14o3DDPVx1DSsMaSzvdhNjC1tB1iEPZbdiMSCIEYbkgbsYznHXWqFdKL8WUB3F8g==", "cpu": [ "s390x" ], @@ -3769,9 +3791,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.66.0.tgz", - "integrity": "sha512-p5jfP1wUZe/IC3qpQO84n9DRnf9g3lKRtLBlQq23ykyrDglHcVx7sWmVTlPuU6SBw8mNnPzyOn022G3XZHnlww==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.68.0.tgz", + "integrity": "sha512-zc9lEnfV/HreDTY6gdMlZe+irkwHSxQ4/B1pS9GyK7RVaA5LxhoZY/w6/o2vIwLLEYiXQ5ujGxOM1ZazeFAAIA==", "cpu": [ "x64" ], @@ -3789,9 +3811,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.66.0.tgz", - "integrity": "sha512-vUB/sYlYZorDL1ZD+o9mRv7zbsykrrFRtmgS6R8musZqLtrPRQn1gc1eGpuX+sfdccz42STl/AqldY6XRb2upQ==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.68.0.tgz", + "integrity": "sha512-Dl5QEX0TCo/40Cdh1o1JdPS//+YiWqjC+Hrrya5OQmStZZr4svAFtdlqcpCrU9yq2Mo3vRVyO9B3h0dzD8s36Q==", "cpu": [ "x64" ], @@ -3809,9 +3831,9 @@ } }, "node_modules/@oxlint/binding-openharmony-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.66.0.tgz", - "integrity": "sha512-yde+6p/F59xRkGR9H1HfngWRif1QRJjynZK349l+UI0H6w9hL3G8/AVaTHFyTtLVQ56qtNbX2/5Dc77n1ovnOg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.68.0.tgz", + "integrity": "sha512-/qy6dOvi4S3/LeXq0l5BT5pRKPYA7oj3uKwJOAZOr5HRLL+HK6jdBynvWuXIA2wwfE01RzNYmbBdM7vwYx00sA==", "cpu": [ "arm64" ], @@ -3826,9 +3848,9 @@ } }, "node_modules/@oxlint/binding-win32-arm64-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.66.0.tgz", - "integrity": "sha512-O9GLucgoTdmOrbBX+EjzNe7o/Ze5TFOvXcib6bzUOtBOmj6cV+zw18NgB+cGKAkDw1Pdqs8vGkfHbbsLuDtXWg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.68.0.tgz", + "integrity": "sha512-fHNtVqPHSYE7UFDSLVFUjxQjnSVXxseNJmRW+XuP4pXXDwePdPda43NL7/BBCFTxHjycOc44JNDaOPtFDNui9A==", "cpu": [ "arm64" ], @@ -3843,9 +3865,9 @@ } }, "node_modules/@oxlint/binding-win32-ia32-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.66.0.tgz", - "integrity": "sha512-m3Pjwc2MfTcom4E4gOv7DyuGyt7OfGNCbmqDHd+N7EzXmP+ppHuudm2NjcA3AjV5TSeGxaguVF4SbTKHe1USYA==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.68.0.tgz", + "integrity": "sha512-NnKXr4Wgo4nps3erhrE0f8shBvBPZMHg72nDsvX0JyrRvsNiP3f1JNvbCKh+A6VFvpF7ZoJxu904P3cKMhvZnA==", "cpu": [ "ia32" ], @@ -3860,9 +3882,9 @@ } }, "node_modules/@oxlint/binding-win32-x64-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.66.0.tgz", - "integrity": "sha512-/DbBvw8UFBhja6PqudUjV4UtfsJr0Oa7jUjWVKB0g86lj/VwnPrkngn0sFql3c9RDA0O16dh7ozsXb6GjNAzBQ==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.68.0.tgz", + "integrity": "sha512-zg5pA+84AlU6XHJ3ruiRxziO71QTrz8nLsk6u01JGS5+tL9/bnlakFiklFrcy4R1/V7ktWtaNitN3JZWmKnf6g==", "cpu": [ "x64" ], @@ -4005,6 +4027,9 @@ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4026,6 +4051,9 @@ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4047,6 +4075,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4068,6 +4099,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4089,6 +4123,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4110,6 +4147,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4240,9 +4280,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz", - "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", "cpu": [ "arm64" ], @@ -4257,9 +4297,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz", - "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", "cpu": [ "arm64" ], @@ -4274,9 +4314,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz", - "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", "cpu": [ "x64" ], @@ -4291,9 +4331,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz", - "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", "cpu": [ "x64" ], @@ -4308,9 +4348,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz", - "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", "cpu": [ "arm" ], @@ -4325,13 +4365,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz", - "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4342,13 +4385,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz", - "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4359,13 +4405,16 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz", - "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4376,13 +4425,16 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz", - "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4393,13 +4445,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz", - "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4410,13 +4465,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz", - "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4427,9 +4485,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz", - "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", "cpu": [ "arm64" ], @@ -4444,9 +4502,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz", - "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", "cpu": [ "wasm32" ], @@ -4463,9 +4521,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz", - "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", "cpu": [ "arm64" ], @@ -4480,9 +4538,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", - "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", "cpu": [ "x64" ], @@ -4711,9 +4769,9 @@ "license": "MIT" }, "node_modules/@swc/helpers": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", - "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -4916,9 +4974,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.15", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", - "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", + "version": "19.2.16", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.16.tgz", + "integrity": "sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==", "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -4979,17 +5037,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz", - "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", + "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/type-utils": "8.59.4", - "@typescript-eslint/utils": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/type-utils": "8.60.1", + "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -5002,7 +5060,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.59.4", + "@typescript-eslint/parser": "^8.60.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -5018,16 +5076,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.4.tgz", - "integrity": "sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", + "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", "debug": "^4.4.3" }, "engines": { @@ -5043,14 +5101,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.4.tgz", - "integrity": "sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", + "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.4", - "@typescript-eslint/types": "^8.59.4", + "@typescript-eslint/tsconfig-utils": "^8.60.1", + "@typescript-eslint/types": "^8.60.1", "debug": "^4.4.3" }, "engines": { @@ -5065,14 +5123,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz", - "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", + "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4" + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5083,9 +5141,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.4.tgz", - "integrity": "sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", + "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", "dev": true, "license": "MIT", "engines": { @@ -5100,15 +5158,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.4.tgz", - "integrity": "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", + "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/utils": "8.60.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -5125,9 +5183,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", - "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", + "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", "dev": true, "license": "MIT", "engines": { @@ -5139,16 +5197,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz", - "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", + "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.4", - "@typescript-eslint/tsconfig-utils": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/project-service": "8.60.1", + "@typescript-eslint/tsconfig-utils": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -5206,16 +5264,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.4.tgz", - "integrity": "sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", + "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4" + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5230,13 +5288,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.4.tgz", - "integrity": "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", + "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/types": "8.60.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5288,16 +5346,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz", - "integrity": "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.7", - "@vitest/utils": "4.1.7", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -5306,13 +5364,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.7.tgz", - "integrity": "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.7", + "@vitest/spy": "4.1.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -5333,9 +5391,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.7.tgz", - "integrity": "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", "dev": true, "license": "MIT", "dependencies": { @@ -5346,13 +5404,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.7.tgz", - "integrity": "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.7", + "@vitest/utils": "4.1.8", "pathe": "^2.0.3" }, "funding": { @@ -5360,14 +5418,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.7.tgz", - "integrity": "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.7", - "@vitest/utils": "4.1.7", + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -5376,9 +5434,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.7.tgz", - "integrity": "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", "dev": true, "license": "MIT", "funding": { @@ -5386,13 +5444,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.7.tgz", - "integrity": "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.7", + "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -5684,9 +5742,9 @@ ] }, "node_modules/@vscode/vsce/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -6035,9 +6093,9 @@ "license": "BSD-2-Clause" }, "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -6494,44 +6552,140 @@ "license": "MIT" }, "node_modules/concurrently": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", - "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.3.tgz", + "integrity": "sha512-hc3LH4UaKWd/bbyDK/IGVa4RB6PtQ3CUYwtrkzqHn+wIG3Hr5fhpRlk0L/gCa8ZE1L/Ufj50Zho69cI5w8SQBA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "4.1.2", + "chalk": "5.6.2", "rxjs": "7.8.2", - "shell-quote": "1.8.3", - "supports-color": "8.1.1", + "shell-quote": "1.8.4", + "supports-color": "10.2.2", "tree-kill": "1.2.2", - "yargs": "17.7.2" + "yargs": "18.0.0" }, "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" + "conc": "dist/bin/index.js", + "concurrently": "dist/bin/index.js" }, "engines": { - "node": ">=18" + "node": ">=22" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "dev": true, + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=10" + "node": ">=20" + } + }, + "node_modules/concurrently/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concurrently/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/convert-source-map": { @@ -6684,9 +6838,9 @@ "license": "MIT" }, "node_modules/dayjs": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", "license": "MIT" }, "node_modules/debug": { @@ -7011,9 +7165,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.21.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.4.tgz", - "integrity": "sha512-wE4fDO8OjJhrPFH69HUQStq5oKvGRTNXEyW+k5C/pUQLASSsTu7obd2V3GvCDgPcY9AWjhJ4jz9Kh7iRvrxhJg==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, "license": "MIT", "dependencies": { @@ -7095,9 +7249,9 @@ "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -7124,9 +7278,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", - "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", + "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", "license": "MIT", "workspaces": [ "docs", @@ -7157,9 +7311,9 @@ } }, "node_modules/eslint": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.0.tgz", - "integrity": "sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.1.tgz", + "integrity": "sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==", "dev": true, "license": "MIT", "dependencies": { @@ -7168,7 +7322,7 @@ "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.1", + "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -7939,9 +8093,9 @@ } }, "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -8128,9 +8282,9 @@ "license": "MIT" }, "node_modules/immutable": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", "dev": true, "license": "MIT" }, @@ -8460,9 +8614,19 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8801,6 +8965,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8822,6 +8989,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8843,6 +9013,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8864,6 +9037,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8926,10 +9102,20 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" @@ -9076,15 +9262,25 @@ } }, "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", - "linkify-it": "^5.0.0", + "linkify-it": "^5.0.1", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -9278,9 +9474,9 @@ "optional": true }, "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "version": "11.7.6", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", + "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", "dev": true, "license": "MIT", "dependencies": { @@ -9886,9 +10082,9 @@ } }, "node_modules/oxfmt": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.51.0.tgz", - "integrity": "sha512-l/AoAnaEOV7Q5/Z9kHOMDehVJnCgYN7wRoooWCTUMBMi16BJhLZqd9cmCnwcVFfVlzkt53zK2KLPFNp8vSsoDg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.53.0.tgz", + "integrity": "sha512-9cB5glS3Ip6NMuZ+6NYTao9FCWkDhRtPYCtR3QBu/NxHoFbgzzTvi41N4jxz/GqGfuLKspui1qb/LlSu2IbMcw==", "dev": true, "license": "MIT", "dependencies": { @@ -9904,39 +10100,43 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.51.0", - "@oxfmt/binding-android-arm64": "0.51.0", - "@oxfmt/binding-darwin-arm64": "0.51.0", - "@oxfmt/binding-darwin-x64": "0.51.0", - "@oxfmt/binding-freebsd-x64": "0.51.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.51.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.51.0", - "@oxfmt/binding-linux-arm64-gnu": "0.51.0", - "@oxfmt/binding-linux-arm64-musl": "0.51.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-musl": "0.51.0", - "@oxfmt/binding-linux-s390x-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-musl": "0.51.0", - "@oxfmt/binding-openharmony-arm64": "0.51.0", - "@oxfmt/binding-win32-arm64-msvc": "0.51.0", - "@oxfmt/binding-win32-ia32-msvc": "0.51.0", - "@oxfmt/binding-win32-x64-msvc": "0.51.0" + "@oxfmt/binding-android-arm-eabi": "0.53.0", + "@oxfmt/binding-android-arm64": "0.53.0", + "@oxfmt/binding-darwin-arm64": "0.53.0", + "@oxfmt/binding-darwin-x64": "0.53.0", + "@oxfmt/binding-freebsd-x64": "0.53.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.53.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.53.0", + "@oxfmt/binding-linux-arm64-gnu": "0.53.0", + "@oxfmt/binding-linux-arm64-musl": "0.53.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.53.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.53.0", + "@oxfmt/binding-linux-riscv64-musl": "0.53.0", + "@oxfmt/binding-linux-s390x-gnu": "0.53.0", + "@oxfmt/binding-linux-x64-gnu": "0.53.0", + "@oxfmt/binding-linux-x64-musl": "0.53.0", + "@oxfmt/binding-openharmony-arm64": "0.53.0", + "@oxfmt/binding-win32-arm64-msvc": "0.53.0", + "@oxfmt/binding-win32-ia32-msvc": "0.53.0", + "@oxfmt/binding-win32-x64-msvc": "0.53.0" }, "peerDependencies": { - "svelte": "^5.0.0" + "svelte": "^5.0.0", + "vite-plus": "*" }, "peerDependenciesMeta": { "svelte": { "optional": true + }, + "vite-plus": { + "optional": true } } }, "node_modules/oxlint": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.66.0.tgz", - "integrity": "sha512-N4LLxYLd94KEBqXDMDM5f+2PUpItTjDLreXe2Gn5KhjhCK4Qp2YUXaBi8Yu325ryOgKwt22m45fpD7nPOn69Yw==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.68.0.tgz", + "integrity": "sha512-dXcbq+xsmLrMy6T8d0euf3IYUfLmjHIE11pOxiUSi5LHkFZaYPv568R6sEjcavVpUxoaQe66UBuK4HEi74NxpA==", "dev": true, "license": "MIT", "bin": { @@ -9949,32 +10149,36 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxlint/binding-android-arm-eabi": "1.66.0", - "@oxlint/binding-android-arm64": "1.66.0", - "@oxlint/binding-darwin-arm64": "1.66.0", - "@oxlint/binding-darwin-x64": "1.66.0", - "@oxlint/binding-freebsd-x64": "1.66.0", - "@oxlint/binding-linux-arm-gnueabihf": "1.66.0", - "@oxlint/binding-linux-arm-musleabihf": "1.66.0", - "@oxlint/binding-linux-arm64-gnu": "1.66.0", - "@oxlint/binding-linux-arm64-musl": "1.66.0", - "@oxlint/binding-linux-ppc64-gnu": "1.66.0", - "@oxlint/binding-linux-riscv64-gnu": "1.66.0", - "@oxlint/binding-linux-riscv64-musl": "1.66.0", - "@oxlint/binding-linux-s390x-gnu": "1.66.0", - "@oxlint/binding-linux-x64-gnu": "1.66.0", - "@oxlint/binding-linux-x64-musl": "1.66.0", - "@oxlint/binding-openharmony-arm64": "1.66.0", - "@oxlint/binding-win32-arm64-msvc": "1.66.0", - "@oxlint/binding-win32-ia32-msvc": "1.66.0", - "@oxlint/binding-win32-x64-msvc": "1.66.0" + "@oxlint/binding-android-arm-eabi": "1.68.0", + "@oxlint/binding-android-arm64": "1.68.0", + "@oxlint/binding-darwin-arm64": "1.68.0", + "@oxlint/binding-darwin-x64": "1.68.0", + "@oxlint/binding-freebsd-x64": "1.68.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.68.0", + "@oxlint/binding-linux-arm-musleabihf": "1.68.0", + "@oxlint/binding-linux-arm64-gnu": "1.68.0", + "@oxlint/binding-linux-arm64-musl": "1.68.0", + "@oxlint/binding-linux-ppc64-gnu": "1.68.0", + "@oxlint/binding-linux-riscv64-gnu": "1.68.0", + "@oxlint/binding-linux-riscv64-musl": "1.68.0", + "@oxlint/binding-linux-s390x-gnu": "1.68.0", + "@oxlint/binding-linux-x64-gnu": "1.68.0", + "@oxlint/binding-linux-x64-musl": "1.68.0", + "@oxlint/binding-openharmony-arm64": "1.68.0", + "@oxlint/binding-win32-arm64-msvc": "1.68.0", + "@oxlint/binding-win32-ia32-msvc": "1.68.0", + "@oxlint/binding-win32-x64-msvc": "1.68.0" }, "peerDependencies": { - "oxlint-tsgolint": ">=0.22.1" + "oxlint-tsgolint": ">=0.22.1", + "vite-plus": "*" }, "peerDependenciesMeta": { "oxlint-tsgolint": { "optional": true + }, + "vite-plus": { + "optional": true } } }, @@ -10209,9 +10413,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.4.0.tgz", - "integrity": "sha512-W+R+kFL4HgVxONq2bhXPi3bGpzGe/yEhVOp233qw9wCRtgncJ15P3bC+e4zZMu4Cq7d+WAJjXGW0uUkifhcatA==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -10284,9 +10488,9 @@ } }, "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -10304,7 +10508,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10523,9 +10727,9 @@ } }, "node_modules/react": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", - "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10542,15 +10746,15 @@ } }, "node_modules/react-dom": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", - "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.6" + "react": "^19.2.7" } }, "node_modules/react-hotkeys-hook": { @@ -10772,13 +10976,13 @@ } }, "node_modules/rolldown": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", - "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.130.0", + "@oxc-project/types": "=0.133.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -10788,21 +10992,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.1", - "@rolldown/binding-darwin-arm64": "1.0.1", - "@rolldown/binding-darwin-x64": "1.0.1", - "@rolldown/binding-freebsd-x64": "1.0.1", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", - "@rolldown/binding-linux-arm64-gnu": "1.0.1", - "@rolldown/binding-linux-arm64-musl": "1.0.1", - "@rolldown/binding-linux-ppc64-gnu": "1.0.1", - "@rolldown/binding-linux-s390x-gnu": "1.0.1", - "@rolldown/binding-linux-x64-gnu": "1.0.1", - "@rolldown/binding-linux-x64-musl": "1.0.1", - "@rolldown/binding-openharmony-arm64": "1.0.1", - "@rolldown/binding-wasm32-wasi": "1.0.1", - "@rolldown/binding-win32-arm64-msvc": "1.0.1", - "@rolldown/binding-win32-x64-msvc": "1.0.1" + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" } }, "node_modules/rtl-css-js": { @@ -10888,13 +11092,13 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.99.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", - "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", + "chokidar": "^5.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, @@ -10902,36 +11106,36 @@ "sass": "sass.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" } }, "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14.18.0" + "node": ">= 20.19.0" }, "funding": { "type": "individual", @@ -11006,9 +11210,9 @@ } }, "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -11058,9 +11262,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", "dev": true, "license": "MIT", "engines": { @@ -11720,9 +11924,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", - "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { @@ -11730,9 +11934,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -11937,16 +12141,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.4.tgz", - "integrity": "sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz", + "integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.4", - "@typescript-eslint/parser": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4" + "@typescript-eslint/eslint-plugin": "8.60.1", + "@typescript-eslint/parser": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/utils": "8.60.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11975,9 +12179,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", - "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.0.tgz", + "integrity": "sha512-+t2Z/GwkZQDtu00813aP66ygViGtPHKhhoFZpQKpKrE+9jIgES+Zw+mFNaDWOVRKiuJjuqKHzD3B1sfGg8+ZOQ==", "dev": true, "license": "MIT", "engines": { @@ -12076,17 +12280,6 @@ "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -12112,17 +12305,17 @@ } }, "node_modules/vite": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", - "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", - "postcss": "^8.5.14", - "rolldown": "1.0.1", - "tinyglobby": "^0.2.16" + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" @@ -12236,19 +12429,19 @@ } }, "node_modules/vitest": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.7.tgz", - "integrity": "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.7", - "@vitest/mocker": "4.1.7", - "@vitest/pretty-format": "4.1.7", - "@vitest/runner": "4.1.7", - "@vitest/snapshot": "4.1.7", - "@vitest/spy": "4.1.7", - "@vitest/utils": "4.1.7", + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -12276,12 +12469,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.7", - "@vitest/browser-preview": "4.1.7", - "@vitest/browser-webdriverio": "4.1.7", - "@vitest/coverage-istanbul": "4.1.7", - "@vitest/coverage-v8": "4.1.7", - "@vitest/ui": "4.1.7", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -12677,13 +12870,12 @@ } }, "node_modules/yauzl": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", - "integrity": "sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.2.tgz", + "integrity": "sha512-Md9ankxxN23wncAN8s7+Tn3Co52zLUPMtnrLAbVCnfG5d2tKBFfmygYSgXlqFgXObtzIgqkx7aNgDBpso9+4qA==", "dev": true, "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3", "pend": "~1.2.0" }, "engines": { @@ -12772,19 +12964,6 @@ } } }, - "packages/nosql-language-service/node_modules/@codemirror/view": { - "version": "6.42.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", - "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.6.0", - "crelt": "^1.0.6", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, "packages/schema-analyzer": { "name": "@cosmosdb/schema-analyzer", "version": "0.1.0", diff --git a/package.json b/package.json index 6d23b9b5f..4df5b7ce1 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@vscode/test-cli": "~0.0.12", "@vscode/test-electron": "~2.5.2", "@vscode/vsce": "~3.9.1", - "concurrently": "~9.2.1", + "concurrently": "~10.0.3", "cross-env": "~10.1.0", "diff": "~9.0.0", "eslint": "~10.4.0", @@ -125,16 +125,16 @@ "mocha": "~11.7.4", "mocha-junit-reporter": "~2.2.1", "mocha-multi-reporters": "~1.5.1", - "oxfmt": "~0.51.0", - "oxlint": "~1.66.0", + "oxfmt": "~0.53.0", + "oxlint": "~1.68.0", "oxlint-tsgolint": "~0.23.0", "react": "~19.2.1", "react-dom": "~19.2.1", "react-refresh": "~0.18.0", "rimraf": "~6.1.0", - "sass": "~1.99.0", + "sass": "~1.100.0", "typescript": "~6.0.2", - "typescript-eslint": "~8.59.0", + "typescript-eslint": "~8.60.1", "vite": "~8.0.10", "vite-bundle-analyzer": "~1.3.7", "vite-plugin-static-copy": "~4.1.0", @@ -147,7 +147,7 @@ "@azure/arm-resources": "~7.0.0", "@azure/cosmos": "~4.9.0", "@azure/identity": "~4.13.0", - "@fluentui/react-components": "~9.73.0", + "@fluentui/react-components": "~9.74.1", "@fluentui/react-icons": "~2.0.313", "@microsoft/vscode-azext-azureauth": "~5.1.1", "@microsoft/vscode-azext-azureutils": "~4.2.0", @@ -160,7 +160,7 @@ "@vscode/l10n": "~0.0.18", "@vscode/prompt-tsx": "^0.4.0-alpha.7", "allotment": "~1.20.4", - "es-toolkit": "~1.46.0", + "es-toolkit": "~1.47.0", "monaco-editor": "~0.52.2", "react-data-grid": "~7.0.0-beta.59", "react-hotkeys-hook": "5.1.0", @@ -952,5 +952,10 @@ "label": "Cosmos DB Shell MCP Server Provider" } ] + }, + "allowScripts": { + "@parcel/watcher": false, + "@vscode/vsce-sign": false, + "keytar": false } } diff --git a/src/panels/BaseTab.ts b/src/panels/BaseTab.ts index fdf05d6d3..ff1071fa7 100644 --- a/src/panels/BaseTab.ts +++ b/src/panels/BaseTab.ts @@ -21,6 +21,35 @@ export class BaseTab { protected disposables: vscode.Disposable[] = []; + /** + * Fires once when the tab has been disposed (after the panel is gone + * and the disposables chain has been drained, but before the closed + * telemetry event is reported). + * + * Subscribe to react to tab lifecycle from outside the disposables + * chain — e.g. a controller holding a `Map` that + * needs to remove its entry, or a parent that owns resources whose + * lifetime is tied to a specific tab instance and which cannot be + * routed through `this.disposables` (because they outlive a single + * tab, or because they belong to a different ownership graph). + * + * For everything that *is* tied to the tab's own lifetime, prefer + * `this.disposables.push(...)` — it's simpler and runs in the same + * pass without a round-trip through the event-emitter. + * + * The emitter is itself part of `this.disposables`, so subscribers + * automatically get unhooked when the tab goes away. There is no + * need (and no harm) to dispose the returned subscription manually. + */ + private readonly _onDisposed = new vscode.EventEmitter(); + public readonly onDisposed: vscode.Event = this._onDisposed.event; + + private _isDisposed = false; + /** `true` once {@link dispose} has run (or has been entered). */ + public get isDisposed(): boolean { + return this._isDisposed; + } + protected constructor(panel: vscode.WebviewPanel, viewType: string, telemetryProperties?: Record) { this.id = crypto.randomUUID(); this.start = Date.now(); @@ -29,6 +58,10 @@ export class BaseTab { this.panel = panel; this.viewType = viewType; + // Ensure the event emitter is torn down with the tab. Listeners + // are released automatically by `EventEmitter.dispose()`. + this.disposables.push(this._onDisposed); + this.panel.onDidDispose(() => this.dispose(), null, this.disposables); this.panel.webview.html = this.getWebviewContent(); @@ -40,6 +73,17 @@ export class BaseTab { } public dispose(): void { + if (this._isDisposed) { + return; + } + this._isDisposed = true; + + // Notify subscribers *before* the disposables chain runs, so that + // listeners see a consistent "tab is going away" view of the world. + // The emitter itself sits inside `this.disposables` and is torn + // down in the loop below. + this._onDisposed.fire(); + this.panel.dispose(); while (this.disposables.length) { diff --git a/src/panels/trpc/appRouter.ts b/src/panels/trpc/appRouter.ts index 8c395c7c6..d7846b232 100644 --- a/src/panels/trpc/appRouter.ts +++ b/src/panels/trpc/appRouter.ts @@ -22,6 +22,7 @@ import { type TelemetryContext } from '../../Telemetry'; import { openSurvey, promptAfterActionEventually } from '../../utils/survey'; import { ExperienceKind, UsageImpact } from '../../utils/surveyTypes'; import { type TypedEventSink } from '../../utils/TypedEventSink'; +import { type BaseRouterContext } from './baseRouterContext'; import { documentRouterDef } from './routers/documentRouter'; import { migrationEventsRouterDef, type MigrationEvent } from './routers/migrationEventsRouter'; import { migrationRouterDef } from './routers/migrationRouter'; @@ -43,16 +44,35 @@ import { // ─── Context Types ────────────────────────────────────────────────────────── -export type BaseRouterContext = { +/** + * Cosmosdb-specific extension of the framework-level + * {@link BaseRouterContext}. Carries everything our procedures expect + * beyond what the transport layer provides: + * + * - `webviewName` — the panel/webview identifier. Used by common procedures + * in {@link buildCommonRouter} to build telemetry event ids + * (`cosmosDB.NoSQL.webview.event.${webviewName}.${eventName}`). + * + * - `actionContext` — the full `IActionContext` from + * `@microsoft/vscode-azext-utils`, populated by `telemetryMiddlewareImpl` + * in `trpc.ts`. Use this when you need azext-utils features beyond + * plain telemetry — for example, `actionContext.errorHandling + * .suppressDisplay`, `.telemetry.suppressIfSuccessful`, or to thread + * the context into another `callWithTelemetryAndErrorHandling`-aware + * helper. For just setting telemetry `properties`/`measurements`, you + * can also read the inherited base-level `ctx.telemetry` once a + * middleware populates it. + * + * `IActionContext.telemetry` structurally satisfies the base + * {@link import('./baseRouterContext').TelemetryContext} shape, but we + * intentionally do not alias the field — keeping `actionContext` as a + * separate, richer field makes the dependency on azext-utils explicit + * at the read site. + */ +export interface CosmosDBRouterContext extends BaseRouterContext { webviewName: string; - signal?: AbortSignal; - /** - * Telemetry action context injected by the telemetry middleware. - * Available in all procedures — use it to set custom telemetry properties - * instead of wrapping handlers in `callWithTelemetryAndErrorHandling`. - */ actionContext?: IActionContext; -}; +} export type QueryEditorMutableState = { connection?: NoSqlQueryConnection; @@ -65,7 +85,7 @@ export type QueryEditorMutableState = { pendingConfirmResolve?: (confirmed: boolean) => void; }; -export type QueryEditorRouterContext = BaseRouterContext & { +export type QueryEditorRouterContext = CosmosDBRouterContext & { sessions: Map; telemetryContext: TelemetryContext; panel: vscode.WebviewPanel; @@ -80,7 +100,7 @@ export type DocumentMutableState = { partitionKeyDefinition?: PartitionKeyDefinition; }; -export type DocumentRouterContext = BaseRouterContext & { +export type DocumentRouterContext = CosmosDBRouterContext & { connection: NoSqlQueryConnection; telemetryContext: TelemetryContext; panel: vscode.WebviewPanel; @@ -96,7 +116,7 @@ export type DocumentRouterContext = BaseRouterContext & { */ export type MigrationCommandDispatcher = (commandName: string, params: unknown[]) => Promise; -export type MigrationRouterContext = BaseRouterContext & { +export type MigrationRouterContext = CosmosDBRouterContext & { telemetryContext: TelemetryContext; panel: vscode.WebviewPanel; eventSink: TypedEventSink; @@ -110,8 +130,9 @@ export type MigrationRouterContext = BaseRouterContext & { * This is called once per tRPC instance so the procedures share the * instance's context type (QueryEditorRouterContext or DocumentRouterContext). * - * Common procedures only access `ctx.webviewName` which is on BaseRouterContext, - * so they work with any context that extends it. + * Common procedures only access `ctx.webviewName`, which lives on + * {@link CosmosDBRouterContext}, so they work with any context that + * extends it. * * Telemetry middleware is already baked into each procedure, so individual * `.use(trpcToTelemetry)` calls are not needed here. @@ -138,7 +159,7 @@ function buildCommonRouter(procedure: any, routerFn: any) { properties?: Record; measurements?: Record; }; - ctx: BaseRouterContext; + ctx: CosmosDBRouterContext; }) => { void callWithTelemetryAndErrorHandling( `cosmosDB.NoSQL.webview.event.${ctx.webviewName}.${input.eventName}`, @@ -172,7 +193,7 @@ function buildCommonRouter(procedure: any, routerFn: any) { componentStack?: string; properties?: Record; }; - ctx: BaseRouterContext; + ctx: CosmosDBRouterContext; }) => { void callWithTelemetryAndErrorHandling( `cosmosDB.NoSQL.webview.error.${ctx.webviewName}`, diff --git a/src/panels/trpc/baseRouterContext.ts b/src/panels/trpc/baseRouterContext.ts new file mode 100644 index 000000000..e081c2275 --- /dev/null +++ b/src/panels/trpc/baseRouterContext.ts @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Framework-level tRPC context types for the webview ↔ extension bridge. + * + * This file is intentionally generic and free of any cosmosdb-specific + * concerns (no `webviewName`, no `IActionContext`, no `vscode.WebviewPanel`). + * It declares the contract that `setupTrpc.ts` and the client `vscodeLink.ts` + * rely on. App-level fields belong in {@link ../appRouter.CosmosDBRouterContext} + * (or any future per-app extension). + * + * Mirrors the public surface of `@microsoft/vscode-ext-react-webview` so + * that — should we extract the framework layer into its own package — this + * file becomes the package's `BaseRouterContext` module without changes. + */ + +/** + * Structural shape for telemetry data attached to a procedure invocation. + * + * Any object that exposes `properties: Record` + * and `measurements: Record` satisfies this + * contract. The optional value type accommodates telemetry libraries + * that allow erased keys (e.g. `delete props['x']`) without forcing + * consumers to widen to `unknown`. + * + * Kept minimal so the framework layer does not depend on any specific + * telemetry library. Concrete telemetry middlewares may place a richer + * object on the app-level context instead (e.g. cosmosdb's + * `azextTelemetryRunner` exposes the full `IActionContext` via the + * {@link ../appRouter.CosmosDBRouterContext.actionContext} field + * rather than populating this field — `IActionContext.telemetry` + * carries trusted-value markers we don't want to leak into the + * framework's structural contract). + */ +export interface TelemetryContext { + properties: Record; + measurements: Record; +} + +/** + * Base router context shared by every tRPC procedure invocation. + * + * The framework populates {@link BaseRouterContext.signal} per-operation + * (see `setupTrpc.ts`). {@link BaseRouterContext.telemetry} is populated + * by user-supplied telemetry middleware when one is attached to the + * procedure (optional — base-only callers may leave it `undefined`). + * + * Application code extends this type with its own fields (database + * connections, webview identifiers, action contexts, etc.) — see + * {@link ../appRouter.CosmosDBRouterContext}. + */ +export interface BaseRouterContext { + /** + * Per-operation `AbortSignal` populated by `setupTrpc`. Procedures + * can poll `signal.aborted` between yields or pass the signal to + * cancellation-aware APIs (e.g. the MongoDB driver). + */ + signal?: AbortSignal; + + /** + * Telemetry context populated by the telemetry middleware (when used). + * Optional — procedures that need it should null-check. + * + * For richer telemetry shapes (e.g. `IActionContext` from azext-utils) + * extend this interface and add a typed field on the app-level context + * type rather than widening this base shape — keeps the framework + * layer dependency-free. + */ + telemetry?: TelemetryContext; +} + +/** + * Type helper that takes any context shape with an **optional** field `K` + * (typically `'telemetry'` or, in cosmosdb, `'actionContext'`) and + * returns the same shape with that field made **required**. + * + * Use it on procedure handlers that are mounted on a procedure-builder + * with the corresponding middleware already applied — at that point you + * *know* the field is present, and you want TypeScript to stop asking + * you to null-check it in every line. + * + * ```ts + * // BaseRouterContext.telemetry is optional in general, but every procedure + * // mounted on `publicProcedureWithTelemetry` is guaranteed to receive it. + * publicProcedureWithTelemetry.query(({ ctx }: { ctx: WithRequired }) => { + * ctx.telemetry.properties.foo = 'bar'; // no null-check needed + * }); + * ``` + * + * Cosmosdb uses this with `'actionContext'` on `CosmosDBRouterContext` + * (see `appRouter.ts`) — every procedure built on `queryEditorProcedure` + * etc. gets `ctx.actionContext` populated by the azext runner. + * + * Mirrors documentdb's `WithTelemetry` helper but is generic over + * the key name so cosmosdb can apply the same pattern to its richer + * `actionContext` field without inventing a separate helper. + */ +export type WithRequired>, K extends PropertyKey> = T & { + [P in K]-?: NonNullable; +}; + +/** + * Convenience alias for the most common cosmosdb case: assert that + * `actionContext` is non-optional on a procedure that runs through the + * `azextTelemetryRunner` middleware. + * + * Equivalent to `WithRequired`, but reads naturally + * at the call site: + * + * ```ts + * .query(({ ctx }: { ctx: WithActionContext }) => { + * ctx.actionContext.telemetry.suppressIfSuccessful = true; // no `?.` + * }); + * ``` + */ +export type WithActionContext = WithRequired; diff --git a/src/panels/trpc/middleware/azextTelemetryRunner.ts b/src/panels/trpc/middleware/azextTelemetryRunner.ts new file mode 100644 index 000000000..fb0afd662 --- /dev/null +++ b/src/panels/trpc/middleware/azextTelemetryRunner.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Cosmosdb-specific {@link TelemetryRunner} implementation backed by + * `@microsoft/vscode-azext-utils`'s `callWithTelemetryAndErrorHandling`. + * + * This is the **only** place in the trpc layer that imports azext-utils. + * The framework-level `telemetryMiddlewareBody` calls into this runner + * and stays dependency-free, so the rest of `src/panels/trpc/` could be + * lifted into a shared package without dragging azext-utils along + * (see `plans/webview-vs-documentdb-package.md`). + * + * The runner contributes a single field to the procedure ctx: + * + * - `actionContext` — the full `IActionContext` (for procedures that + * need azext-utils features like `errorHandling.suppressDisplay`, + * `telemetry.suppressIfSuccessful`, or to write structured + * `properties`/`measurements` via `actionContext.telemetry`). + * + * We intentionally do **not** populate `BaseRouterContext.telemetry`: + * `IActionContext.telemetry` carries `TelemetryTrustedValue` markers + * that are not part of the framework's structural `TelemetryContext` + * contract. Procedures that want plain `properties`/`measurements` + * read them from `ctx.actionContext.telemetry`. + */ + +import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; +import { type TelemetryRunner } from './telemetryMiddleware'; +import { type ProcedureInvocation } from './types'; + +/** + * Shape this runner injects into the procedure ctx. Application context + * types extend `BaseRouterContext` with this field so procedures can + * read `ctx.actionContext` without casts (see `CosmosDBRouterContext`). + */ +export interface AzextTelemetryEnrichment { + actionContext: IActionContext; +} + +/** + * The cosmosdb runner. Wraps each invocation in + * `callWithTelemetryAndErrorHandling` and forwards errors raised by the + * procedure to azext-utils telemetry without displaying them as toasts + * (each webview surfaces its own error UI). + * + * **Cancellation accounting.** Reads `invocation.signal?.aborted` after + * the call completes; when set, the call is reported with + * `result=Canceled` and `aborted=true` instead of `result=Failed`. This + * lets dashboards distinguish genuine errors from user-driven cancels + * (panel closed mid-query, user hit "Stop", etc.) so cancellation rate + * does not pollute the error budget. + */ +export const azextTelemetryRunner: TelemetryRunner = { + async run(eventId, invocation: ProcedureInvocation, invoke) { + const result = await callWithTelemetryAndErrorHandling(eventId, async (actionContext) => { + actionContext.errorHandling.suppressDisplay = true; + + const middlewareResult = await invoke({ actionContext }); + + const aborted = invocation.signal?.aborted ?? false; + if (aborted) { + actionContext.telemetry.properties.aborted = 'true'; + actionContext.telemetry.properties.result = 'Canceled'; + } + + if (!middlewareResult.ok && middlewareResult.error) { + const error = middlewareResult.error; + // Do not overwrite the canceled-result marker — a procedure + // that observed `ctx.signal.aborted` and threw should still + // count as a cancellation, not a failure. + if (!aborted) { + actionContext.telemetry.properties.result = 'Failed'; + } + actionContext.telemetry.properties.error = error.name; + actionContext.telemetry.properties.errorMessage = error.message; + actionContext.telemetry.properties.errorStack = error.stack ?? ''; + if (error.cause) { + actionContext.telemetry.properties.errorCause = JSON.stringify(error.cause, null, 0); + } + } + + return middlewareResult; + }); + + if (!result) { + throw new Error(`No result returned from tRPC telemetry wrapper for ${eventId}`); + } + + return result; + }, +}; diff --git a/src/panels/trpc/middleware/loggingMiddleware.ts b/src/panels/trpc/middleware/loggingMiddleware.ts new file mode 100644 index 000000000..4eb0e6805 --- /dev/null +++ b/src/panels/trpc/middleware/loggingMiddleware.ts @@ -0,0 +1,150 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Generic tRPC server-side logging middleware. + * + * Wraps every procedure call and reports start/end (with duration and + * outcome) to a pluggable {@link ProcedureLogger}. The middleware itself + * is dependency-free — concrete loggers (console, output channel, …) are + * provided by the application. + * + * # Why a middleware (and not a client-side `loggerLink`)? + * + * `loggerLink()` from `@trpc/client` only sees what the client sends and + * receives — it has no access to the server-side `ctx` and cannot honour + * per-call opt-outs the way a middleware can. See + * `plans/webview-vs-documentdb-package.md` section 2.3 for the + * architecture decision. + * + * # Why a body factory (not bound to a specific tRPC instance)? + * + * `t.middleware(fn)` is bound to the instance's context type, but the + * logger doesn't care about ctx. By returning a plain function we make + * the body reusable across all three (and any future) tRPC instances: + * + * ```ts + * const mw = queryEditorT.middleware(loggingMiddlewareBody(consoleProcedureLogger)); + * ``` + */ + +import { type MiddlewareResultLike, type ProcedureInvocation } from './types'; + +/** + * Sink invoked by the logging middleware for each procedure call. + * + * Implementations should be **non-throwing and fast** — the middleware + * already swallows thrown errors as a safety net, but slow loggers will + * extend perceived RPC latency. + * + * Both hooks are optional so consumers can subscribe only to what they + * need (e.g. log only completions and skip start events). + */ +export interface ProcedureLogger { + /** Called immediately before the procedure body runs. */ + onStart?(info: ProcedureInvocation): void; + + /** Called when the procedure completes (success or error). */ + onEnd?( + info: ProcedureInvocation & { + /** Wall-clock duration of the procedure body, in milliseconds. */ + durationMs: number; + /** `true` if the middleware result was `{ ok: true }`. */ + ok: boolean; + /** + * `true` if `info.signal?.aborted` is set when the call ends. + * Convenience flag so loggers can distinguish a clean error + * from a client-side cancellation without re-reading the + * signal themselves. + */ + aborted: boolean; + /** The propagated error when `ok === false`. */ + error?: Error; + }, + ): void; +} + +/** + * Default logger that writes a single line per completion to the dev + * console. Suitable as a fallback when no application-specific sink is + * available; production code should provide a richer logger (e.g. + * `vscode.LogOutputChannel`-backed). + */ +export const consoleProcedureLogger: ProcedureLogger = { + onEnd({ path, type, durationMs, ok, aborted, error }) { + const head = `[trpc] ${type} ${path} ${durationMs.toFixed(1)}ms`; + if (aborted) { + console.debug(`${head} canceled`); + } else if (ok) { + console.debug(`${head} ok`); + } else { + console.warn(`${head} error: ${error?.message ?? '(unknown)'}`); + } + }, +}; + +/** + * Build the body of a logging middleware. + * + * Pass the returned function to `t.middleware(...)`: + * + * ```ts + * const loggingMW = queryEditorT.middleware( + * loggingMiddlewareBody(consoleProcedureLogger), + * ); + * export const queryEditorProcedure = queryEditorT.procedure.use(loggingMW); + * ``` + * + * Accepts either a logger instance or a factory function — the latter + * is useful when the logger is created lazily (e.g. after extension + * activation) or per-invocation. + */ +export function loggingMiddlewareBody(loggerOrFactory: ProcedureLogger | (() => ProcedureLogger)) { + const resolveLogger = typeof loggerOrFactory === 'function' ? loggerOrFactory : () => loggerOrFactory; + + return async (opts: { + path: string; + type: ProcedureInvocation['type']; + // Structural read: any framework-populated `ctx.signal` is surfaced + // to logger sinks via `ProcedureInvocation.signal`. Optional so a + // procedure that bypasses the framework signal still type-checks. + ctx?: { signal?: AbortSignal }; + next: (...args: unknown[]) => Promise; + }): Promise => { + const invocation: ProcedureInvocation = { + path: opts.path, + type: opts.type, + signal: opts.ctx?.signal, + }; + + const logger = resolveLogger(); + safeInvoke(() => logger.onStart?.(invocation)); + + const start = Date.now(); + const result = await opts.next(); + const durationMs = Date.now() - start; + + const inspect = result as unknown as MiddlewareResultLike; + safeInvoke(() => + logger.onEnd?.({ + ...invocation, + durationMs, + ok: inspect.ok, + aborted: invocation.signal?.aborted ?? false, + error: inspect.ok ? undefined : inspect.error, + }), + ); + + return result; + }; +} + +function safeInvoke(fn: () => void): void { + try { + fn(); + } catch { + // Never let logging side-effects break a procedure. + } +} diff --git a/src/panels/trpc/middleware/outputChannelLogger.ts b/src/panels/trpc/middleware/outputChannelLogger.ts new file mode 100644 index 000000000..ec0ef7dd9 --- /dev/null +++ b/src/panels/trpc/middleware/outputChannelLogger.ts @@ -0,0 +1,68 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Cosmosdb-specific {@link ProcedureLogger} that writes one line per + * procedure completion to the extension's `vscode.LogOutputChannel` + * (`ext.outputChannel`). + * + * This is the only logger that has access to `ext.outputChannel`; the + * framework-level `loggingMiddleware.ts` only knows about the + * structural `ProcedureLogger` interface so it can be reused in other + * environments (tests, future packages, …). + * + * Format: `[trpc] mutation queryEditor.runQuery 42.0ms ok` + */ + +import { ext } from '../../../extensionVariables'; +import { type ProcedureLogger } from './loggingMiddleware'; + +/** + * Logger backed by `ext.outputChannel`. Successful calls go to `.debug` + * (hidden by default unless the user lifts the log level), failures go + * to `.warn` so they stand out without forcing the channel open. + * + * Resolved lazily because `ext.outputChannel` is wired during extension + * activation; webview tabs may be constructed in tests where it is + * unset, in which case we fall back to `console.*`. + */ +export const outputChannelProcedureLogger: ProcedureLogger = { + onEnd({ path, type, durationMs, ok, aborted, error }) { + const outcome = aborted ? 'canceled' : ok ? 'ok' : `error: ${error?.message ?? '(unknown)'}`; + const line = `[trpc] ${type} ${path} ${durationMs.toFixed(1)}ms ${outcome}`; + + const channel = tryGetOutputChannel(); + if (channel) { + // Canceled and successful calls go to debug so they stay out of + // the way; errors get warn so they surface in the channel header. + if (aborted || ok) { + channel.debug(line); + } else { + channel.warn(line); + } + return; + } + + if (aborted || ok) { + console.debug(line); + } else { + console.warn(line); + } + }, +}; + +/** + * `ext.outputChannel` is backed by a `required<…>()` slot that throws + * before extension activation. The middleware can be constructed during + * test setup or very early activation, so we tolerate that and fall + * back to `console.*`. + */ +function tryGetOutputChannel(): typeof ext.outputChannel | undefined { + try { + return ext.outputChannel; + } catch { + return undefined; + } +} diff --git a/src/panels/trpc/middleware/telemetryMiddleware.ts b/src/panels/trpc/middleware/telemetryMiddleware.ts new file mode 100644 index 000000000..ea9469ddd --- /dev/null +++ b/src/panels/trpc/middleware/telemetryMiddleware.ts @@ -0,0 +1,128 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Generic tRPC server-side telemetry middleware. + * + * The middleware itself does **not** talk to any telemetry backend. It + * delegates the actual recording to a pluggable {@link TelemetryRunner} + * supplied by the application: + * + * - The framework chooses the **event id** (defaults to + * `"${type}.${path}"`, overridable via `buildEventId`). + * - The runner decides **how to record** the event and **what to enrich + * the procedure ctx with** for the rest of the pipeline. + * + * This keeps the framework dependency-free; the concrete adapter for + * `@microsoft/vscode-azext-utils` lives in `azextTelemetryRunner.ts` + * and is the only place that imports azext-utils. + * + * # Why a middleware (and not a `loggerLink`)? + * + * Telemetry needs access to the server-side `ctx` (and the ability to + * mutate it, e.g. to surface an `actionContext` to procedures). Links + * only see transport-level data. See `plans/webview-vs-documentdb-package.md` + * section 2.3. + * + * # Why a body factory? + * + * `t.middleware(fn)` is bound to the instance's context type. Returning + * a plain function lets the same factory plug into any tRPC instance: + * + * ```ts + * const telemetryMW = queryEditorT.middleware( + * telemetryMiddlewareBody(azextTelemetryRunner, { + * buildEventId: ({ type, path }) => `cosmosDB.rpc.${type}.${path}`, + * }), + * ); + * ``` + */ + +import { type MiddlewareResultLike, type ProcedureInvocation } from './types'; + +/** + * Application-supplied recorder for a single procedure invocation. + * + * The runner is invoked once per call. Implementations should: + * + * 1. Open whatever telemetry scope they need (an `IActionContext`, an + * OpenTelemetry span, a plain `console.time`, …). + * 2. Call `invoke(enrichment)` with whatever fields they want to push + * into the procedure's `ctx`. The framework merges those into the + * existing ctx via `next({ ctx: enrichment })`. + * 3. Inspect the returned `MiddlewareResultLike` and report success or + * failure to the telemetry backend. + * 4. Return the result back to the caller untouched so the rest of the + * middleware chain receives it. + * + * `TEnrichment` is the precise shape the runner contributes to ctx — + * typically a record with one or two well-known keys (e.g. + * `{ actionContext, telemetry }`). Procedures that need those fields + * declare them on their concrete context type (see + * `appRouter.CosmosDBRouterContext`). + */ +export interface TelemetryRunner { + run( + eventId: string, + invocation: ProcedureInvocation, + invoke: (enrichment: TEnrichment) => Promise, + ): Promise; +} + +export interface TelemetryMiddlewareOptions { + /** + * Build the telemetry event id from the invocation. Defaults to + * `"${type}.${path}"`. Override to add a namespace prefix + * (`cosmosDB.rpc.…`) or to apply per-call sampling rules. + */ + buildEventId?: (invocation: ProcedureInvocation) => string; +} + +/** + * Build the body of a telemetry middleware bound to the given runner. + * + * Pass the returned function to `t.middleware(...)`. The runner's + * `TEnrichment` type must be assignable to the tRPC instance's context + * type — usually achieved by extending the per-app context interface + * (see `CosmosDBRouterContext`). + */ +export function telemetryMiddlewareBody( + runner: TelemetryRunner, + options: TelemetryMiddlewareOptions = {}, +) { + const buildEventId = options.buildEventId ?? defaultBuildEventId; + + return async (opts: { + path: string; + type: ProcedureInvocation['type']; + // Structural read so the runner can detect cancellation via + // `invocation.signal?.aborted`. Optional — procedures that + // intentionally run without a framework signal still type-check. + ctx?: { signal?: AbortSignal }; + next: (override?: { ctx: TEnrichment }) => Promise; + }): Promise => { + const invocation: ProcedureInvocation = { + path: opts.path, + type: opts.type, + signal: opts.ctx?.signal, + }; + const eventId = buildEventId(invocation); + + let captured: TResult | undefined; + await runner.run(eventId, invocation, async (enrichment) => { + const result = await opts.next({ ctx: enrichment }); + captured = result; + return result as unknown as MiddlewareResultLike; + }); + // The runner guarantees `invoke` was called; if it threw, control + // never reaches here. Cast back to the original branded type tRPC + // expects from a middleware function. + return captured as TResult; + }; +} + +function defaultBuildEventId({ type, path }: ProcedureInvocation): string { + return `${type}.${path}`; +} diff --git a/src/panels/trpc/middleware/types.ts b/src/panels/trpc/middleware/types.ts new file mode 100644 index 000000000..793c143c1 --- /dev/null +++ b/src/panels/trpc/middleware/types.ts @@ -0,0 +1,54 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Framework-level types shared by middleware factories under this folder. + * + * Intentionally framework-only: no cosmosdb-specific concerns, no + * `@microsoft/vscode-azext-utils` import. Mirrors the shape we would + * expose from a future `@microsoft/vscode-ext-react-webview`-like + * package — see `plans/webview-vs-documentdb-package.md`. + */ + +/** The three tRPC procedure flavors. */ +export type ProcedureType = 'query' | 'mutation' | 'subscription'; + +/** + * Lightweight description of a single procedure invocation, passed to + * logger / telemetry hooks. Independent of any tRPC internal type so + * tests and consumers can build it by hand. + */ +export interface ProcedureInvocation { + path: string; + type: ProcedureType; + + /** + * Per-operation `AbortSignal` lifted from `ctx.signal` (when the + * framework populated it — see `BaseRouterContext.signal`). Optional + * because (a) some procedures intentionally run without one, and + * (b) the structural read in middleware bodies is tolerant of a + * missing field. + * + * Read it from your runner / logger to distinguish a clean error + * from a client-side cancellation: + * + * ```ts + * if (invocation.signal?.aborted) { + * telemetry.properties.result = 'Canceled'; + * } + * ``` + */ + signal?: AbortSignal; +} + +/** + * Structural minimum of a tRPC `MiddlewareResult`. Sufficient to + * differentiate success from failure and to read the error in the + * failure case, without importing internal tRPC types. + */ +export interface MiddlewareResultLike { + ok: boolean; + error?: Error & { cause?: unknown }; +} diff --git a/src/panels/trpc/setupTrpc.ts b/src/panels/trpc/setupTrpc.ts index cacef9996..24789e4cd 100644 --- a/src/panels/trpc/setupTrpc.ts +++ b/src/panels/trpc/setupTrpc.ts @@ -6,7 +6,7 @@ import { getTRPCErrorFromUnknown, type AnyRouter } from '@trpc/server'; import * as l10n from '@vscode/l10n'; import type * as vscode from 'vscode'; -import { type BaseRouterContext } from './appRouter'; +import { type BaseRouterContext } from './baseRouterContext'; import { type VsCodeLinkRequestMessage } from './vscodeProtocol'; /** @@ -29,11 +29,22 @@ function wrapInTrpcErrorMessage(error: unknown, operationId: string) { /** * Safely posts a message to the webview panel. - * Returns false if the panel has already been disposed. + * + * `vscode.Webview.postMessage` may either throw synchronously or return a + * `Thenable` that rejects when the panel has been disposed. We guard both + * so that natural races (e.g. a subscription generator yielding one more + * value after the user closed the tab) do not surface as uncaught + * exceptions in the extension host. + * + * Returns `false` if the message could not be delivered; `true` otherwise. + * The boolean is informational — callers do not need to react. */ function safePostMessage(panel: vscode.WebviewPanel, message: unknown): boolean { try { - void panel.webview.postMessage(message); + // The Thenable returned by `postMessage` resolves with a delivery boolean + // and rejects if the webview is already gone. Attach a no-op catch so a + // late rejection does not surface as an unhandled promise rejection. + void Promise.resolve(panel.webview.postMessage(message)).catch(() => void 0); return true; } catch { // Panel was disposed between our check and the actual call @@ -41,6 +52,38 @@ function safePostMessage(panel: vscode.WebviewPanel, message: unknown): boolean } } +/** + * Normalizes a procedure's subscription return value (which may be an + * `AsyncIterable`, an `AsyncIterator`, or both — async generators are + * both) to a single live `AsyncIterator`. + * + * Calling `[Symbol.asyncIterator]()` once is required for iterables like + * {@link import('../../utils/TypedEventSink').TypedEventSink} which + * enforce single-consumer semantics; direct iterators are returned as-is. + */ +function toAsyncIterator(value: unknown): AsyncIterator { + if ( + value !== null && + typeof value === 'object' && + typeof (value as AsyncIterable)[Symbol.asyncIterator] === 'function' + ) { + return (value as AsyncIterable)[Symbol.asyncIterator](); + } + return value as AsyncIterator; +} + +/** + * Tracks a live subscription so we can both signal cooperative cancellation + * (via `abortController.abort()`) and release a consumer parked on the next + * `iterator.next()` (via `iterator.return()`). The abort signal alone cannot + * unblock a parked `next()`; the iterator-protocol `return()` is what + * propagates through the procedure's inner `for await` over an event sink. + */ +interface ActiveSubscription { + abortController: AbortController; + iterator: AsyncIterator; +} + /** * Sets up tRPC integration for a webview panel. * @@ -50,6 +93,8 @@ function safePostMessage(panel: vscode.WebviewPanel, message: unknown): boolean * * @param panel - The VS Code webview panel to attach the message listener to. * @param context - The router context passed to every procedure invocation. + * Cloned per-operation before `signal` is attached, so the shared object is + * never mutated and concurrent operations do not stomp on each other. * @param appRouter - The tRPC router for this webview type. * @param createCallerFactory - The `createCallerFactory` function from the * tRPC instance that created `appRouter`. @@ -59,8 +104,13 @@ export function setupTrpc (ctx: TContext) => Record, -): { disposable: vscode.Disposable; activeSubscriptions: Map } { - const activeSubscriptions = new Map(); +): { + disposable: vscode.Disposable; + activeSubscriptions: Map; + activeOperations: Map; +} { + const activeSubscriptions = new Map(); + const activeOperations = new Map(); const disposable = panel.webview.onDidReceiveMessage(async (message: VsCodeLinkRequestMessage) => { // Guard against non-tRPC messages reaching this listener (e.g. legacy @@ -91,55 +141,96 @@ export function setupTrpc { - for (const [id, abortController] of activeSubscriptions) { + // Abort all in-flight queries/mutations so server-side procedures can stop early. + for (const controller of activeOperations.values()) { + controller.abort(); + } + activeOperations.clear(); + + // Abort active subscriptions and call `return()` on each iterator so async + // generators terminate even when parked on `next()`. The abort signal alone + // cannot unblock a parked `next()`; `return()` propagates through the + // procedure's `for await` into any inner event sink and settles its pending + // promise. Rejections from `return()` are swallowed because we have no useful + // reaction during shutdown. + for (const { abortController, iterator } of activeSubscriptions.values()) { abortController.abort(); - activeSubscriptions.delete(id); + void Promise.resolve(iterator.return?.({ value: undefined, done: true })).catch(() => void 0); } + activeSubscriptions.clear(); }); - return { disposable, activeSubscriptions }; + return { disposable, activeSubscriptions, activeOperations }; } async function handleSubscriptionMessage( panel: vscode.WebviewPanel, message: VsCodeLinkRequestMessage, context: TContext, - activeSubscriptions: Map, + activeSubscriptions: Map, appRouter: TRouter, createCallerFactory: (router: TRouter) => (ctx: TContext) => Record, ) { + const abortController = new AbortController(); + try { + // Clone the context so the per-operation signal is isolated and the shared + // context object is never mutated. Without this, two concurrent subscriptions + // would share the same `signal` field and aborting one would affect the other. + const opContext: TContext = { ...context, signal: abortController.signal }; + const callerFactory = createCallerFactory(appRouter); - const caller = callerFactory(context); + const caller = callerFactory(opContext); const rawProcedure: unknown = caller[message.op.path]; if (typeof rawProcedure !== 'function') { throw new Error(l10n.t('Procedure not found: {name}', { name: message.op.path })); } - const abortController = new AbortController(); - activeSubscriptions.set(message.id, abortController); + type SubscriptionCaller = (input: unknown) => Promise; + const procedure = rawProcedure as SubscriptionCaller; - context.signal = abortController.signal; + // Resolve the procedure result, then normalize to a live AsyncIterator so we + // have a handle to call `return()` on `subscription.stop` and on panel + // disposal. Using `for await (...)` would obtain the iterator internally + // and give us no such handle, which means a consumer parked on a pending + // `next()` (e.g. an event sink with no recent emit) would stay parked. + const asyncIterable = await procedure(message.op.input); + const iterator = toAsyncIterator(asyncIterable); - type SubscriptionCaller = (input: unknown) => Promise>; - const procedure = rawProcedure as SubscriptionCaller; - const asyncIter = await procedure(message.op.input); + // Only track the subscription once we actually have an iterator. If the + // procedure lookup or the initial `await procedure(...)` throws, we fall + // through to the outer catch without inserting an entry — so an early + // failure cannot leave a stale entry behind for the lifetime of the panel. + activeSubscriptions.set(message.id, { abortController, iterator }); void (async () => { try { - for await (const value of asyncIter) { - safePostMessage(panel, { id: message.id, result: value }); + while (true) { + // Sequential next()/postMessage is required by the subscription protocol; + // parallelizing via Promise.all() would re-order or drop values. + // oxlint-disable-next-line no-await-in-loop + const result: IteratorResult = await iterator.next(); + if (result.done) { + break; + } + safePostMessage(panel, { id: message.id, result: result.value }); } + // On natural completion (procedure returned, or our `return()` propagated + // through the generator), inform the client. safePostMessage(panel, { id: message.id, complete: true }); } catch (error) { const trpcErrorMessage = wrapInTrpcErrorMessage(error, message.id); @@ -156,12 +247,33 @@ async function handleSubscriptionMessage, + activeSubscriptions: Map, ) { - const abortController = activeSubscriptions.get(message.id); + const record = activeSubscriptions.get(message.id); + if (record) { + record.abortController.abort(); + // Cooperative abort cannot unblock a parked `iterator.next()`. Calling `return()` + // here propagates through the procedure's async generator into any inner + // `for await` (including TypedEventSink consumers), which settles parked + // promises with `{ done: true }` and lets the streaming task exit cleanly. + // We swallow rejection because we have no useful reaction. + void Promise.resolve(record.iterator.return?.({ value: undefined, done: true })).catch(() => void 0); + activeSubscriptions.delete(message.id); + } +} + +/** + * Handles the 'abort' message type for queries and mutations. + * + * Looks up the active operation by ID and aborts its `AbortController`, + * which propagates through `ctx.signal.aborted` so procedure bodies that + * poll the signal (or pass it to the underlying SDK call) can cancel. + */ +function handleAbortMessage(message: VsCodeLinkRequestMessage, activeOperations: Map) { + const abortController = activeOperations.get(message.id); if (abortController) { abortController.abort(); - activeSubscriptions.delete(message.id); + activeOperations.delete(message.id); } } @@ -169,12 +281,20 @@ async function handleDefaultMessage, appRouter: TRouter, createCallerFactory: (router: TRouter) => (ctx: TContext) => Record, ) { + const abortController = new AbortController(); + activeOperations.set(message.id, abortController); + try { + // Clone the context so the per-operation signal is isolated and concurrent + // operations do not share (and stomp on) the same `signal` field. + const opContext: TContext = { ...context, signal: abortController.signal }; + const callerFactory = createCallerFactory(appRouter); - const caller = callerFactory(context); + const caller = callerFactory(opContext); const rawProcedure: unknown = caller[message.op.path]; if (typeof rawProcedure !== 'function') { @@ -185,10 +305,22 @@ async function handleDefaultMessage().create(); +/** Project-wide telemetry event id format: `cosmosDB.rpc.${type}.${path}`. */ +function buildCosmosDbEventId({ type, path }: ProcedureInvocation): string { + return `cosmosDB.rpc.${type}.${path}`; +} -const queryEditorTrpcToTelemetry = queryEditorT.middleware(async ({ path, type, next }) => { - return telemetryMiddlewareImpl(`cosmosDB.rpc.${type}.${path}`, (actionContext) => next({ ctx: { actionContext } })); +// The two middleware bodies are *ctx-agnostic* — they're plain async +// functions whose only contract with tRPC is structural (`path`, `type`, +// `next`). Each tRPC instance wraps them with its own `t.middleware(...)` +// so the bound types stay precise per webview. +// +// We deliberately inline the `.use(...)` chain at each instance instead of +// hiding it behind a generic helper: tRPC's `ProcedureBuilder` is a +// deep-generic type whose inference collapses to `any` the moment a +// helper widens its return type, which in turn would erase the typed +// router shape downstream (e.g. `trpcClient.foo.query` would lose +// `input`/`output` typing). Three near-identical lines per instance is +// the price of that precision. + +const sharedLoggingBody = loggingMiddlewareBody(outputChannelProcedureLogger); +const sharedTelemetryBody = telemetryMiddlewareBody(azextTelemetryRunner, { + buildEventId: buildCosmosDbEventId, }); -/** Base procedure with telemetry middleware already applied. */ -export const queryEditorProcedure = queryEditorT.procedure.use(queryEditorTrpcToTelemetry); +// ─── Query Editor tRPC Instance ───────────────────────────────────────────── + +const queryEditorT = initTRPC.context().create(); + +/** Base procedure with logging + telemetry middleware already applied. */ +export const queryEditorProcedure = queryEditorT.procedure + .use(queryEditorT.middleware(sharedLoggingBody)) + .use(queryEditorT.middleware(sharedTelemetryBody)); export const queryEditorRouter = queryEditorT.router; export const queryEditorMergeRouters = queryEditorT.mergeRouters; export const queryEditorCallerFactory = queryEditorT.createCallerFactory; // ─── Document tRPC Instance ───────────────────────────────────────────────── -// Context is DocumentRouterContext — all procedures get properly typed ctx. const documentT = initTRPC.context().create(); -const documentTrpcToTelemetry = documentT.middleware(async ({ path, type, next }) => { - return telemetryMiddlewareImpl(`cosmosDB.rpc.${type}.${path}`, (actionContext) => next({ ctx: { actionContext } })); -}); - -/** Base procedure with telemetry middleware already applied. */ -export const documentProcedure = documentT.procedure.use(documentTrpcToTelemetry); +/** Base procedure with logging + telemetry middleware already applied. */ +export const documentProcedure = documentT.procedure + .use(documentT.middleware(sharedLoggingBody)) + .use(documentT.middleware(sharedTelemetryBody)); export const documentRouter = documentT.router; export const documentCallerFactory = documentT.createCallerFactory; // ─── Migration Assistant tRPC Instance ────────────────────────────────────── -// Context is MigrationRouterContext — all procedures get properly typed ctx. const migrationT = initTRPC.context().create(); -const migrationTrpcToTelemetry = migrationT.middleware(async ({ path, type, next }) => { - return telemetryMiddlewareImpl(`cosmosDB.rpc.${type}.${path}`, (actionContext) => next({ ctx: { actionContext } })); -}); - -/** Base procedure with telemetry middleware already applied. */ -export const migrationProcedure = migrationT.procedure.use(migrationTrpcToTelemetry); +/** Base procedure with logging + telemetry middleware already applied. */ +export const migrationProcedure = migrationT.procedure + .use(migrationT.middleware(sharedLoggingBody)) + .use(migrationT.middleware(sharedTelemetryBody)); export const migrationRouter = migrationT.router; export const migrationMergeRouters = migrationT.mergeRouters; export const migrationCallerFactory = migrationT.createCallerFactory; - -// ─── Shared Telemetry Implementation ──────────────────────────────────────── - -/** - * Type guard for tRPC middleware error results. - * Avoids importing internal types from `@trpc/server/unstable-core-do-not-import`. - */ -function isMiddlewareError(result: { ok: boolean }): result is { ok: false; error: TRPCError } { - return !result.ok; -} - -/** - * Shared telemetry middleware logic. Wraps procedure execution in - * `callWithTelemetryAndErrorHandling` and logs errors without displaying them. - * - * Each tRPC instance creates its own middleware using this helper because - * `t.middleware()` is bound to the instance's context type. - * - * The function is generic over the exact result type returned by `next()`, - * so the branded `MiddlewareResult` flows through without needing to - * import internal tRPC types. - */ -async function telemetryMiddlewareImpl( - telemetryId: string, - next: (actionContext: IActionContext) => Promise, -): Promise { - const result = await callWithTelemetryAndErrorHandling(telemetryId, async (actionContext) => { - actionContext.errorHandling.suppressDisplay = true; - - const result = await next(actionContext); - - if (isMiddlewareError(result)) { - actionContext.telemetry.properties.result = 'Failed'; - actionContext.telemetry.properties.error = result.error.name; - actionContext.telemetry.properties.errorMessage = result.error.message; - actionContext.telemetry.properties.errorStack = result.error.stack ?? ''; - if (result.error.cause) { - actionContext.telemetry.properties.errorCause = JSON.stringify(result.error.cause, null, 0); - } - } - - return result; - }); - - if (!result) { - throw new Error(`No result returned from tRPC telemetry wrapper for ${telemetryId}`); - } - - return result; -} diff --git a/src/panels/trpc/vscodeProtocol.ts b/src/panels/trpc/vscodeProtocol.ts index 8ae394ee6..6ea94cec7 100644 --- a/src/panels/trpc/vscodeProtocol.ts +++ b/src/panels/trpc/vscodeProtocol.ts @@ -11,7 +11,7 @@ import { type Operation } from '@trpc/client'; type StopOperation = Omit, 'type'> & { - type: 'subscription.stop'; + type: 'subscription.stop' | 'abort'; }; /** @@ -21,6 +21,7 @@ type StopOperation = Omit, 'type'> & { export interface VsCodeLinkRequestMessage { id: string; // TODO, when tRPC v12 is released, 'subscription.stop' should be supported natively, until then, we're adding it manually. + // 'abort' is used to cancel in-flight queries and mutations (no native tRPC type either). op: Operation | StopOperation; } diff --git a/src/utils/TypedEventSink.test.ts b/src/utils/TypedEventSink.test.ts index 820443f0e..2bf12a48a 100644 --- a/src/utils/TypedEventSink.test.ts +++ b/src/utils/TypedEventSink.test.ts @@ -178,4 +178,85 @@ describe('TypedEventSink', () => { expect(results).toEqual([{ type: 'start', id: 'abc' }, { type: 'data', payload: 42 }, { type: 'end' }]); }); + + it('close() should be idempotent', () => { + const sink = new TypedEventSink(); + sink.close(); + expect(sink.isClosed).toBe(true); + + // Calling close() again must not throw and must keep state consistent. + sink.close(); + expect(sink.isClosed).toBe(true); + }); + + describe('iterator.return()', () => { + it('releases a consumer parked on next() with no buffered events', async () => { + const sink = new TypedEventSink(); + const iterator = sink[Symbol.asyncIterator](); + + // Park the consumer on next() — no events buffered, sink not closed. + const pendingNext = iterator.next(); + + // Drive return() externally (like setupTrpc does on subscription.stop). + const returnResult = await iterator.return!({ value: undefined as unknown as NumEvent, done: true }); + + expect(returnResult.done).toBe(true); + + // The previously parked next() should now resolve with { done: true }. + const settled = await pendingNext; + expect(settled.done).toBe(true); + expect(sink.isClosed).toBe(true); + }); + + it('completes a for-await loop that calls break early', async () => { + const sink = new TypedEventSink(); + + sink.emit({ type: 'num', value: 10 }); + sink.emit({ type: 'num', value: 20 }); + + const received: NumEvent[] = []; + for await (const event of sink) { + received.push(event); + // `break` calls iterator.return() under the iterator protocol; + // this single-iteration loop is intentional. + break; + } + + expect(received).toEqual([{ type: 'num', value: 10 }]); + expect(sink.isClosed).toBe(true); + + // Subsequent emit() calls are dropped, exactly like after close(). + sink.emit({ type: 'num', value: 99 }); + expect(sink.isClosed).toBe(true); + }); + + it('drops buffered events on return() so they cannot leak to a later consumer', async () => { + const sink = new TypedEventSink(); + + sink.emit({ type: 'num', value: 10 }); + sink.emit({ type: 'num', value: 20 }); + + const iterator = sink[Symbol.asyncIterator](); + await iterator.return!({ value: undefined as unknown as NumEvent, done: true }); + + // A second consumer is allowed after return() — single-consumer guard is released. + const second: NumEvent[] = []; + for await (const event of sink) { + second.push(event); + } + expect(second).toEqual([]); + }); + + it('is idempotent (return() after return())', async () => { + const sink = new TypedEventSink(); + const iterator = sink[Symbol.asyncIterator](); + + const r1 = await iterator.return!({ value: undefined as unknown as NumEvent, done: true }); + const r2 = await iterator.return!({ value: undefined as unknown as NumEvent, done: true }); + + expect(r1.done).toBe(true); + expect(r2.done).toBe(true); + expect(sink.isClosed).toBe(true); + }); + }); }); diff --git a/src/utils/TypedEventSink.ts b/src/utils/TypedEventSink.ts index 3eb072a38..bbb31924c 100644 --- a/src/utils/TypedEventSink.ts +++ b/src/utils/TypedEventSink.ts @@ -70,8 +70,13 @@ export class TypedEventSink implements AsyncIterab /** * Close the sink. The async iterator will complete after all buffered * events have been consumed. No further events can be emitted. + * + * Idempotent: calling `close()` more than once is a no-op. */ close(): void { + if (this.done) { + return; + } this.done = true; if (this.resolve) { @@ -111,6 +116,47 @@ export class TypedEventSink implements AsyncIterab this.resolve = resolve; }); }, + + /** + * Implements the optional `return()` half of the async-iterator + * protocol so callers can release a parked consumer without + * having to wait for the next `emit` or `close`. + * + * Invoked automatically by `for await (...) { break; }`, + * `for await (...) { throw ...; }`, and explicit + * `iterator.return()` calls. The tRPC integration in + * `setupTrpc.ts` also calls it on `subscription.stop` and on + * panel disposal to close out the unsubscribe-while-panel-alive + * window that abort signals alone cannot reach (an abort + * signal cannot unblock a `next()` that is parked waiting for + * the next `emit()`). + * + * After `return()` the sink reports `isClosed === true`, + * subsequent `emit()` calls are dropped, and a new consumer can + * iterate again (it will see `{ done: true }` immediately). + */ + return: (): Promise> => { + // Mark the sink closed so any race between `return()` and a + // late `emit()` from the producer is dropped on the floor. + this.done = true; + this.queue.length = 0; + + // If we were parked on a pending `next()`, settle it with + // `done: true` so the caller's `for await` loop terminates + // cleanly instead of staying pending forever. + if (this.resolve) { + const res = this.resolve; + this.resolve = null; + res({ value: undefined as unknown as T, done: true }); + } + + // Release the single-consumer guard. A second `for await` + // over the same sink is now allowed; it will see `done: true` + // on the first `next()` because `this.done` is `true`. + this.iterating = false; + + return Promise.resolve({ value: undefined as unknown as T, done: true }); + }, }; } } diff --git a/src/webviews/WebviewContext.tsx b/src/webviews/WebviewContext.tsx index 112d57aef..319759d49 100644 --- a/src/webviews/WebviewContext.tsx +++ b/src/webviews/WebviewContext.tsx @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import type * as React from 'react'; -import { createContext } from 'react'; +import { createContext, useMemo } from 'react'; import { type WebviewApi } from 'vscode-webview'; export type WebviewState = object; @@ -13,8 +13,39 @@ export type WebviewContextValue = { vscodeApi: WebviewApi; }; +/** + * React context that exposes the per-webview `vscodeApi` handle + * (returned by `acquireVsCodeApi()` in the webview bootstrap) to any + * descendant component. Consumers use `useContext(WebviewContext)` — + * typically via the {@link import('./api/trpc/useTrpcClient').useTrpcClient} + * hook, which reads it under the hood. + * + * The default value is `{} as WebviewContextValue` — components must + * be rendered inside a {@link WithWebviewContext} (or another provider + * of this context) for the API to be usable. + */ export const WebviewContext = createContext({} as WebviewContextValue); +/** + * Provider component that wraps its children in a + * {@link WebviewContext.Provider} pre-filled with the given `vscodeApi`. + * + * Use it at the top of every webview entry point to avoid repeating + * the provider JSX in each panel: + * + * ```tsx + * const vscodeApi = acquireVsCodeApi(); + * + * createRoot(document.getElementById('root')!).render( + * + * + * , + * ); + * ``` + * + * Mirrors the helper of the same name in the documentdb sister package + * so future extraction is a one-line import rename. + */ export const WithWebviewContext = ({ vscodeApi, children, @@ -22,5 +53,11 @@ export const WithWebviewContext = ({ vscodeApi: WebviewApi; children: React.ReactNode; }) => { - return {children}; + // Memoize the context value so consumers do not re-render on every + // parent render. `vscodeApi` is stable across the lifetime of the + // webview (it's the result of `acquireVsCodeApi()`, which the host + // guarantees to be idempotent), so a single-deps `useMemo` keeps the + // value identity-stable forever. + const value = useMemo(() => ({ vscodeApi }), [vscodeApi]); + return {children}; }; diff --git a/src/webviews/api/trpc/errorLink.test.ts b/src/webviews/api/trpc/errorLink.test.ts new file mode 100644 index 000000000..8cd78f481 --- /dev/null +++ b/src/webviews/api/trpc/errorLink.test.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type AnyRouter } from '@trpc/server'; +import { observable } from '@trpc/server/observable'; +import { vi, type Mock } from 'vitest'; +import { errorLink, type ErrorHandler } from './errorLink'; + +/** + * Build a downstream link that emits one of: `next` value, `error`, or + * `complete`, so tests can drive each branch of the link wrapper. + */ +type DownstreamOutcome = + | { kind: 'next'; value: { result: { data: unknown } } } + | { kind: 'error'; error: unknown } + | { kind: 'complete' }; + +function makeDownstreamNext(outcome: DownstreamOutcome) { + return () => + observable<{ result: { data: unknown } }, unknown>((observer) => { + if (outcome.kind === 'next') { + observer.next(outcome.value); + observer.complete(); + } else if (outcome.kind === 'error') { + observer.error(outcome.error); + } else { + observer.complete(); + } + return () => void 0; + }); +} + +function createTestHarness( + type: 'query' | 'mutation' | 'subscription', + outcome: DownstreamOutcome, + onErrorHandler: (err: Error) => void, +) { + const link = errorLink(onErrorHandler); + const linkRuntime = link({} as never); + + const op = { + id: 0, + type, + path: 'demo.someProcedure', + input: undefined, + context: { trpc: { requestId: 'r-1' } }, + signal: null, + }; + + const next = makeDownstreamNext(outcome); + const obs = linkRuntime({ op, next } as never); + + const onNext: Mock = vi.fn(); + const onError: Mock = vi.fn(); + const onComplete: Mock = vi.fn(); + obs.subscribe({ next: onNext, error: onError, complete: onComplete }); + + return { onNext, onError, onComplete }; +} + +describe('errorLink', () => { + it('forwards query errors to the consumer onError handler', () => { + const handler = vi.fn() as Mock & ErrorHandler; + const { onError } = createTestHarness('query', { kind: 'error', error: new Error('boom') }, handler); + + expect(handler).toHaveBeenCalledTimes(1); + const forwarded = handler.mock.calls[0][0]; + expect(forwarded).toBeInstanceOf(Error); + expect(forwarded.message).toBe('boom'); + + // The error is re-emitted downstream so call-site .catch handlers still fire. + expect(onError).toHaveBeenCalledTimes(1); + }); + + it('forwards mutation errors to the consumer onError handler', () => { + const handler = vi.fn() as Mock & ErrorHandler; + const { onError } = createTestHarness('mutation', { kind: 'error', error: new Error('nope') }, handler); + + expect(handler).toHaveBeenCalledTimes(1); + expect(handler.mock.calls[0][0].message).toBe('nope'); + expect(onError).toHaveBeenCalledTimes(1); + }); + + it('normalises non-Error rejections into Error instances', () => { + const handler = vi.fn() as Mock & ErrorHandler; + createTestHarness('query', { kind: 'error', error: 'string failure' }, handler); + + expect(handler).toHaveBeenCalledTimes(1); + const forwarded = handler.mock.calls[0][0]; + expect(forwarded).toBeInstanceOf(Error); + expect(forwarded.message).toBe('string failure'); + }); + + it('does not forward subscription errors to the consumer handler', () => { + const handler = vi.fn() as Mock & ErrorHandler; + const { onError } = createTestHarness('subscription', { kind: 'error', error: new Error('sub') }, handler); + + // Subscriptions have their own per-call onError hook; this link must + // not double-report them through the consumer's global handler. + expect(handler).not.toHaveBeenCalled(); + + // The error still propagates down the link chain so the subscription's + // own onError callback can react. + expect(onError).toHaveBeenCalledTimes(1); + }); + + it('passes through successful values without invoking the handler', () => { + const handler = vi.fn() as Mock & ErrorHandler; + const { onNext, onError, onComplete } = createTestHarness( + 'query', + { kind: 'next', value: { result: { data: 'ok' } } }, + handler, + ); + + expect(handler).not.toHaveBeenCalled(); + expect(onNext).toHaveBeenCalledWith({ result: { data: 'ok' } }); + expect(onComplete).toHaveBeenCalledTimes(1); + expect(onError).not.toHaveBeenCalled(); + }); + + it('passes through complete signals without invoking the handler', () => { + const handler = vi.fn() as Mock & ErrorHandler; + const { onComplete, onError } = createTestHarness('query', { kind: 'complete' }, handler); + + expect(handler).not.toHaveBeenCalled(); + expect(onComplete).toHaveBeenCalledTimes(1); + expect(onError).not.toHaveBeenCalled(); + }); +}); diff --git a/src/webviews/api/trpc/useTrpcClient.ts b/src/webviews/api/trpc/useTrpcClient.ts index ed1165654..e4534375c 100644 --- a/src/webviews/api/trpc/useTrpcClient.ts +++ b/src/webviews/api/trpc/useTrpcClient.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createTRPCClient, loggerLink } from '@trpc/client'; +import { createTRPCClient, loggerLink, type TRPCClient as TRPCClientV11 } from '@trpc/client'; import { type AnyRouter } from '@trpc/server'; import { useCallback, useContext, useMemo } from 'react'; import { WebviewContext } from '../../WebviewContext'; @@ -11,33 +11,61 @@ import { errorLink, type ErrorHandler } from './errorLink'; import { vscodeLink, type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from './vscodeLink'; /** - * Custom React hook that provides a tRPC client for communication between the webview and VSCode extension. + * Convenience alias for the tRPC client instance returned by + * {@link useTrpcClient}. Useful when you need to thread the client + * down through props or store it in a ref: * - * @typeParam TRouter - The per-webview app router type (e.g. QueryEditorAppRouter, DocumentAppRouter). - * @returns An object containing the tRPC client (`trpcClient`) + * ```ts + * const clientRef = useRef | null>(null); + * ``` * - * @example - * // In your component: - * import { useTrpcClient } from 'useTrpcClient'; + * Aliases tRPC v11's `TRPCClient` (formerly `CreateTRPCClient`, + * deprecated in v11 and slated for removal in v12). + */ +export type TrpcClient = TRPCClientV11; + +/** + * Options accepted by {@link useTrpcClient}. + * + * Options are passed as an object (rather than positional parameters) + * so new fields can be added without breaking existing call sites. All + * fields are optional — a bare `useTrpcClient()` call returns + * a client with only the default link stack (`loggerLink` + `vscodeLink`). + */ +export interface UseTrpcClientOptions { + /** + * Invoked when a query or mutation surfaces an error through the + * link pipeline. Subscriptions deliver their errors through the + * caller's `subscribe({ onError })` callback and are intentionally + * not forwarded here (see `errorLink.ts`). + * + * Note: changing this handler between renders rebuilds the + * underlying tRPC client. Wrap in `useCallback` at the call site to + * keep the client stable. + */ + onError?: ErrorHandler; +} + +/** + * Custom React hook that provides a tRPC client for communication + * between the webview and the VSCode extension host. * - * export const MyComponent = () => { - * const { trpcClient } = useTrpcClient(); + * @typeParam TRouter - The per-webview app router type (e.g. + * `QueryEditorAppRouter`, `DocumentAppRouter`). + * @param options - See {@link UseTrpcClientOptions}. + * @returns An object containing the tRPC client as `trpcClient`. * - * // Use the tRPC client to make queries and mutations - * useEffect(() => { - * trpcClient.myProcedure.query().then((result) => { - * console.log('Procedure result:', result); - * }); - * }, [trpcClient]); + * @example + * // No error handler — fire-and-forget calls only: + * const { trpcClient } = useTrpcClient(); * - * return ( - * <> - * { / * Your component's JSX * /} - * - * ); - * }; + * @example + * // With an error handler that surfaces toasts: + * const onError = useCallback((err) => toaster.error(err.message), [toaster]); + * const { trpcClient } = useTrpcClient({ onError }); */ -export function useTrpcClient(onError?: ErrorHandler) { +export function useTrpcClient(options: UseTrpcClientOptions = {}) { + const { onError } = options; const { vscodeApi } = useContext(WebviewContext); /** @@ -82,7 +110,7 @@ export function useTrpcClient(onError?: ErrorHandler) }, []); // Use useMemo to avoid recreating the client on every render - const trpcClient = useMemo( + const trpcClient = useMemo>( () => createTRPCClient({ links: [ diff --git a/src/webviews/api/trpc/vscodeLink.test.ts b/src/webviews/api/trpc/vscodeLink.test.ts new file mode 100644 index 000000000..6d00f204d --- /dev/null +++ b/src/webviews/api/trpc/vscodeLink.test.ts @@ -0,0 +1,430 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TRPCClientError } from '@trpc/client'; +import { type AnyRouter } from '@trpc/server'; +import { vi, type Mock } from 'vitest'; +import { vscodeLink, type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from './vscodeLink'; + +/** + * Creates a mock Operation object for testing. + * The `context.trpc.requestId` field is set to a deterministic value + * so tests can predict the operationId used by the link. + */ +function createMockOp( + type: 'query' | 'mutation' | 'subscription', + path: string, + requestId: string, + signal?: AbortSignal | null, +) { + return { + id: 0, + type, + path, + input: undefined, + context: { trpc: { requestId } }, + signal: signal ?? null, + }; +} + +/** + * Sets up the vscodeLink with mock send/onReceive functions and subscribes + * to the observable returned for a given operation. + * + * Returns helpers to simulate server responses and inspect calls. + */ +function createTestHarness(op: ReturnType) { + const sentMessages: VsCodeLinkRequestMessage[] = []; + const send: Mock = vi.fn((msg: VsCodeLinkRequestMessage) => { + sentMessages.push(msg); + }); + + // Capture the callback registered via onReceive so we can simulate server responses + let receiveCallback: ((message: VsCodeLinkResponseMessage) => void) | null = null; + const unsubscribeFn: Mock = vi.fn(); + const onReceive: Mock = vi.fn((cb: (message: VsCodeLinkResponseMessage) => void) => { + receiveCallback = cb; + return unsubscribeFn; + }); + + const link = vscodeLink({ send, onReceive }); + // vscodeLink returns: (runtime) => ({ op, next }) => Observable + // runtime is unused (_runtime), so we pass a dummy + // next is unused (terminating link), so we pass a dummy + const linkRuntime = link({} as never); + const observable = linkRuntime({ op, next: (() => {}) as never } as never); + + // Observer callbacks + const onNext: Mock = vi.fn(); + const onError: Mock = vi.fn(); + const onComplete: Mock = vi.fn(); + + // Subscribe to the observable + const subscription = observable.subscribe({ + next: onNext, + error: onError, + complete: onComplete, + }); + + /** Simulate a response from the server to the client */ + function simulateResponse(message: VsCodeLinkResponseMessage) { + if (!receiveCallback) { + throw new Error('onReceive callback not registered — link setup failed'); + } + receiveCallback(message); + } + + return { + send, + onReceive, + unsubscribeFn, + sentMessages, + subscription, + onNext, + onError, + onComplete, + simulateResponse, + }; +} + +describe('vscodeLink', () => { + describe('query operations', () => { + it('should send the operation and receive data', () => { + const op = createMockOp('query', 'common.reportEvent', 'q-1'); + const { sentMessages, onNext, onComplete, simulateResponse } = createTestHarness(op); + + // The link should have sent the operation (signal is stripped by sendSafe before postMessage) + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].id).toBe('q-1'); + const { signal: _sig, ...expectedOp } = op; + void _sig; + expect(sentMessages[0].op).toEqual(expectedOp); + + // Simulate the server responding + simulateResponse({ id: 'q-1', result: { text: 'hello' } }); + + // The observer should have received the data wrapped in { result: { data } } + expect(onNext).toHaveBeenCalledTimes(1); + expect(onNext).toHaveBeenCalledWith({ + result: { data: { text: 'hello' } }, + }); + + // Queries auto-complete after receiving a result + expect(onComplete).toHaveBeenCalledTimes(1); + }); + + it('should ignore messages with a different operationId', () => { + const op = createMockOp('query', 'some.path', 'q-2'); + const { onNext, simulateResponse } = createTestHarness(op); + + // Send a response with a different id + simulateResponse({ id: 'wrong-id', result: 'nope' }); + + expect(onNext).not.toHaveBeenCalled(); + }); + }); + + describe('mutation operations', () => { + it('should send and complete after receiving a result', () => { + const op = createMockOp('mutation', 'common.reportEvent', 'm-1'); + const { sentMessages, onNext, onComplete, simulateResponse } = createTestHarness(op); + + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('mutation'); + + simulateResponse({ id: 'm-1', result: 'ok' }); + + expect(onNext).toHaveBeenCalledTimes(1); + expect(onNext).toHaveBeenCalledWith({ result: { data: 'ok' } }); + expect(onComplete).toHaveBeenCalledTimes(1); + }); + }); + + describe('error handling', () => { + it('should propagate errors via TRPCClientError', () => { + const op = createMockOp('query', 'some.path', 'e-1'); + const { onNext, onError, onComplete, simulateResponse } = createTestHarness(op); + + simulateResponse({ + id: 'e-1', + error: { + name: 'TRPCError', + message: 'Something went wrong', + code: -32600, + }, + }); + + expect(onError).toHaveBeenCalledTimes(1); + const error = onError.mock.calls[0][0]; + expect(error).toBeInstanceOf(TRPCClientError); + expect(error.message).toBe('Something went wrong'); + + // No data or completion should have been emitted + expect(onNext).not.toHaveBeenCalled(); + expect(onComplete).not.toHaveBeenCalled(); + }); + + it('should propagate errors for subscriptions', () => { + const op = createMockOp('subscription', 'some.sub', 'e-2'); + const { onError, simulateResponse } = createTestHarness(op); + + simulateResponse({ + id: 'e-2', + error: { + name: 'Error', + message: 'Subscription failed', + }, + }); + + expect(onError).toHaveBeenCalledTimes(1); + const error = onError.mock.calls[0][0]; + expect(error).toBeInstanceOf(TRPCClientError); + }); + }); + + describe('subscription operations', () => { + it('should stream multiple data yields without auto-completing', () => { + const op = createMockOp('subscription', 'some.sub', 's-1'); + const { onNext, onComplete, simulateResponse } = createTestHarness(op); + + // First yield + simulateResponse({ id: 's-1', result: { count: 0 } }); + expect(onNext).toHaveBeenCalledTimes(1); + expect(onNext).toHaveBeenCalledWith({ result: { data: { count: 0 } } }); + // Subscription should NOT complete after data + expect(onComplete).not.toHaveBeenCalled(); + + // Second yield + simulateResponse({ id: 's-1', result: { count: 1 } }); + expect(onNext).toHaveBeenCalledTimes(2); + expect(onNext).toHaveBeenLastCalledWith({ result: { data: { count: 1 } } }); + expect(onComplete).not.toHaveBeenCalled(); + + // Third yield + simulateResponse({ id: 's-1', result: { count: 2 } }); + expect(onNext).toHaveBeenCalledTimes(3); + expect(onComplete).not.toHaveBeenCalled(); + }); + + it('should complete when a complete message is received', () => { + const op = createMockOp('subscription', 'some.sub', 's-2'); + const { onNext, onComplete, simulateResponse } = createTestHarness(op); + + // Yield some data first + simulateResponse({ id: 's-2', result: 'data1' }); + expect(onNext).toHaveBeenCalledTimes(1); + + // Server signals completion + simulateResponse({ id: 's-2', complete: true }); + expect(onComplete).toHaveBeenCalledTimes(1); + }); + + it('should send subscription.stop when unsubscribed', () => { + const op = createMockOp('subscription', 'some.sub', 's-3'); + const { sentMessages, subscription } = createTestHarness(op); + + // The initial send + expect(sentMessages).toHaveLength(1); + + // Unsubscribe + subscription.unsubscribe(); + + // Should have sent a stop message + expect(sentMessages).toHaveLength(2); + expect(sentMessages[1].id).toBe('s-3'); + expect(sentMessages[1].op.type).toBe('subscription.stop'); + expect(sentMessages[1].op.path).toBe('some.sub'); + }); + }); + + describe('cleanup behavior', () => { + it('should call the onReceive unsubscribe function on cleanup', () => { + const op = createMockOp('query', 'some.path', 'c-1'); + const { unsubscribeFn, subscription, simulateResponse } = createTestHarness(op); + + // Complete the query so the observable finishes + simulateResponse({ id: 'c-1', result: 'done' }); + + // Explicitly unsubscribe + subscription.unsubscribe(); + + expect(unsubscribeFn).toHaveBeenCalled(); + }); + + it('should NOT send subscription.stop for query operations on cleanup', () => { + const op = createMockOp('query', 'some.path', 'c-2'); + const { sentMessages, subscription, simulateResponse } = createTestHarness(op); + + simulateResponse({ id: 'c-2', result: 'done' }); + subscription.unsubscribe(); + + // Only the initial send, no stop message + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('query'); + }); + + it('should NOT send subscription.stop for mutation operations on cleanup', () => { + const op = createMockOp('mutation', 'some.path', 'c-3'); + const { sentMessages, subscription, simulateResponse } = createTestHarness(op); + + simulateResponse({ id: 'c-3', result: 'ok' }); + subscription.unsubscribe(); + + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('mutation'); + }); + }); + + describe('concurrent operations', () => { + it('should correctly route messages to independent operations', () => { + // Set up two concurrent operations with different IDs + const op1 = createMockOp('query', 'path.one', 'concurrent-1'); + const op2 = createMockOp('query', 'path.two', 'concurrent-2'); + + const sentMessages: VsCodeLinkRequestMessage[] = []; + const send: Mock = vi.fn((msg: VsCodeLinkRequestMessage) => sentMessages.push(msg)); + + const receiveCallbacks: Array<(message: VsCodeLinkResponseMessage) => void> = []; + const onReceive: Mock = vi.fn((cb: (message: VsCodeLinkResponseMessage) => void) => { + receiveCallbacks.push(cb); + return vi.fn(); + }); + + const link = vscodeLink({ send, onReceive }); + const linkRuntime = link({} as never); + + const onNext1: Mock = vi.fn(); + const onNext2: Mock = vi.fn(); + + linkRuntime({ op: op1, next: (() => {}) as never } as never).subscribe({ next: onNext1 }); + linkRuntime({ op: op2, next: (() => {}) as never } as never).subscribe({ next: onNext2 }); + + // Both operations should have been sent + expect(sentMessages).toHaveLength(2); + + // Simulate response for op2 only — broadcast to all handlers + for (const cb of receiveCallbacks) { + cb({ id: 'concurrent-2', result: 'for-op2' }); + } + + // Only op2's observer should have received data + expect(onNext1).not.toHaveBeenCalled(); + expect(onNext2).toHaveBeenCalledTimes(1); + expect(onNext2).toHaveBeenCalledWith({ result: { data: 'for-op2' } }); + + // Now respond to op1 + for (const cb of receiveCallbacks) { + cb({ id: 'concurrent-1', result: 'for-op1' }); + } + + expect(onNext1).toHaveBeenCalledTimes(1); + expect(onNext1).toHaveBeenCalledWith({ result: { data: 'for-op1' } }); + // op2 should still only have 1 call + expect(onNext2).toHaveBeenCalledTimes(1); + }); + }); + + describe('abort signal operations', () => { + it('should send an abort message when the signal is aborted after send', () => { + const ac = new AbortController(); + const op = createMockOp('query', 'some.path', 'abort-1', ac.signal); + const { sentMessages, onError } = createTestHarness(op); + + // The initial operation should have been sent + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('query'); + + // Abort the signal + ac.abort(); + + // An abort message should have been sent + expect(sentMessages).toHaveLength(2); + expect(sentMessages[1].id).toBe('abort-1'); + expect(sentMessages[1].op.type).toBe('abort'); + expect(sentMessages[1].op.path).toBe('some.path'); + + // The observer should have received an error + expect(onError).toHaveBeenCalledTimes(1); + const error = onError.mock.calls[0][0]; + expect(error).toBeInstanceOf(TRPCClientError); + expect(error.message).toBe('Aborted'); + }); + + it('should error immediately when the signal is already aborted', () => { + const ac = new AbortController(); + ac.abort(); // Abort before creating the operation + + const op = createMockOp('query', 'some.path', 'abort-2', ac.signal); + const { sentMessages, onError } = createTestHarness(op); + + // An abort message should have been sent (but NOT the original operation). + // The abort message is the only one sent since signal was pre-aborted. + expect(sentMessages.some((m) => m.op.type === 'abort')).toBe(true); + + // The observer should have received an error + expect(onError).toHaveBeenCalledTimes(1); + const error = onError.mock.calls[0][0]; + expect(error).toBeInstanceOf(TRPCClientError); + expect(error.message).toBe('Aborted'); + }); + + it('should send abort for mutations too', () => { + const ac = new AbortController(); + const op = createMockOp('mutation', 'some.mutation', 'abort-3', ac.signal); + const { sentMessages, onError } = createTestHarness(op); + + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('mutation'); + + ac.abort(); + + expect(sentMessages).toHaveLength(2); + expect(sentMessages[1].op.type).toBe('abort'); + + expect(onError).toHaveBeenCalledTimes(1); + }); + + it('should not send abort message after cleanup/unsubscribe', () => { + const ac = new AbortController(); + const op = createMockOp('query', 'some.path', 'abort-4', ac.signal); + const { sentMessages, subscription, simulateResponse } = createTestHarness(op); + + // Complete the query + simulateResponse({ id: 'abort-4', result: 'done' }); + subscription.unsubscribe(); + + // Now abort — no abort message should be sent since the listener was cleaned up + ac.abort(); + + // Only the initial operation send should exist + expect(sentMessages).toHaveLength(1); + expect(sentMessages[0].op.type).toBe('query'); + }); + + it('should still use subscription.stop for subscriptions, not abort', () => { + const op = createMockOp('subscription', 'some.sub', 'abort-5'); + const { sentMessages, subscription } = createTestHarness(op); + + expect(sentMessages).toHaveLength(1); + + subscription.unsubscribe(); + + // Should send subscription.stop, not abort + expect(sentMessages).toHaveLength(2); + expect(sentMessages[1].op.type).toBe('subscription.stop'); + }); + + it('should not send abort when no signal is provided', () => { + const op = createMockOp('query', 'some.path', 'abort-6'); + const { sentMessages, subscription, simulateResponse } = createTestHarness(op); + + simulateResponse({ id: 'abort-6', result: 'done' }); + subscription.unsubscribe(); + + // Only the initial operation, no abort message + expect(sentMessages).toHaveLength(1); + }); + }); +}); diff --git a/src/webviews/api/trpc/vscodeLink.ts b/src/webviews/api/trpc/vscodeLink.ts index e650dca7a..514e955ea 100644 --- a/src/webviews/api/trpc/vscodeLink.ts +++ b/src/webviews/api/trpc/vscodeLink.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TRPCClientError, type TRPCLink } from '@trpc/client'; +import { TRPCClientError, type Operation, type TRPCLink } from '@trpc/client'; import { type AnyRouter } from '@trpc/server'; import { observable } from '@trpc/server/observable'; // Their example uses a reference from /server/ and so do we: https://trpc.io/docs/client/links#example import { type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from '../../../panels/trpc/vscodeProtocol'; @@ -94,16 +94,64 @@ function vscodeLink(options: VSCodeLinkOptions): TRPC // Register the message handler to receive messages from the server const unsubscribe = onReceive(handleMessage); + /** + * Abort-signal handling. + * + * tRPC populates `op.signal` when the caller provides `{ signal: AbortSignal }` in + * request options (e.g. `trpcClient.myQuery.query(input, { signal: ac.signal })`). + * + * Note: `op.signal` is a live AbortSignal on the client side — it is NOT serialized + * over postMessage. Instead, when the signal fires, we send an explicit 'abort' message + * to the extension host so it can cancel the server-side operation. + * + * For subscriptions we still use the existing `subscription.stop` cleanup path; the + * abort flow targets queries and mutations, which previously had no cancellation hook. + */ + + /** + * `op.signal` is a live `AbortSignal` and is NOT cloneable via the structured-clone + * algorithm used by `postMessage`. Forwarding the op verbatim would throw + * `DataCloneError`. `sendSafe` strips it so the underlying `send()` only ever + * sees serialisable data. The signal itself is handled entirely on the client side + * via the `onAbort` listener below. + */ + const sendSafe = (message: VsCodeLinkRequestMessage): void => { + const { signal: _sig, ...safeOp } = message.op as Operation & { signal?: unknown }; + void _sig; + send({ ...message, op: safeOp as VsCodeLinkRequestMessage['op'] }); + }; + + const onAbort = (): void => { + sendSafe({ id: operationId, op: { ...op, type: 'abort' } }); + observer.error(TRPCClientError.from(new Error('Aborted'))); + }; + + const opSignal = (op as { signal?: AbortSignal | null }).signal ?? null; + if (opSignal) { + if (opSignal.aborted) { + // Signal was already aborted before the operation started — bail out + // without sending the original op, only the abort message. + onAbort(); + return () => { + unsubscribe(); + }; + } + opSignal.addEventListener('abort', onAbort, { once: true }); + } + // Send the operation to the server with a unique ID - send({ id: operationId, op }); + sendSafe({ id: operationId, op }); // Return a cleanup function that is called when the observable is unsubscribed // This is relevant when working with subscriptions. return () => { // If it's a subscription, send a stop message to the server if (op.type === 'subscription') { - send({ id: operationId, op: { ...op, type: 'subscription.stop' } }); + sendSafe({ id: operationId, op: { ...op, type: 'subscription.stop' } }); } + // Remove the abort listener so a late `ac.abort()` after natural completion + // does not send a stray 'abort' message for an operation that's already done. + opSignal?.removeEventListener('abort', onAbort); // Cleanup the message handler unsubscribe(); }; diff --git a/src/webviews/cosmosdb/Document/state/DocumentContext.tsx b/src/webviews/cosmosdb/Document/state/DocumentContext.tsx index 7030718a4..ad91249e9 100644 --- a/src/webviews/cosmosdb/Document/state/DocumentContext.tsx +++ b/src/webviews/cosmosdb/Document/state/DocumentContext.tsx @@ -37,7 +37,7 @@ export const WithDocumentContext = ({ children }: { children: ReactNode }) => { [], ); - const { trpcClient } = useTrpcClient(onError); + const { trpcClient } = useTrpcClient({ onError }); const provider = useMemo( () => new DocumentContextProvider(dispatch, dispatchToast, trpcClient), diff --git a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx index c277546c3..183cd72a4 100644 --- a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx +++ b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx @@ -52,7 +52,7 @@ export const WithQueryEditorContext = ({ children }: { children: ReactNode }) => [], ); - const { trpcClient } = useTrpcClient(onError); + const { trpcClient } = useTrpcClient({ onError }); const provider = useMemo( () => new QueryEditorContextProvider(dispatch, dispatchToast, trpcClient), From 0f557f3df77b4f771a3d1dc863bf16e6a87817d7 Mon Sep 17 00:00:00 2001 From: Dmitrii Shilov <6812525+bk201-@users.noreply.github.com> Date: Wed, 3 Jun 2026 11:56:10 +0200 Subject: [PATCH 2/3] refactor(packages): extract @cosmosdb/webview-rpc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the generic tRPC transport for VS Code webviews out of src/ into a standalone workspace package. The package is intentionally cosmosdb-agnostic — concrete routers, telemetry adapters, and logger adapters stay in the consumer (src/panels/trpc/middleware/...). Subpaths: * '@cosmosdb/webview-rpc' — TypedEventSink, wire-protocol types (shared) * '@cosmosdb/webview-rpc/server' — setupTrpc, BaseRouterContext, middleware factories (loggingMiddlewareBody, telemetryMiddlewareBody), middleware types (ProcedureInvocation, ProcedureType, MiddlewareResultLike), ProcedureLogger / TelemetryRunner adapter interfaces, WithRequired / WithTelemetry helpers * '@cosmosdb/webview-rpc/client' — vscodeLink, errorLink (browser-only, no vscode API) * '@cosmosdb/webview-rpc/react' — WebviewContext + WithWebviewContext provider, useTrpcClient(options?) hook (memoised tRPC client wired up with loggerLink + optional errorLink + vscodeLink) Build wiring: * tsconfig.base.json — path aliases for all four subpaths * vite.config.ext.mjs — server/client/shared aliases (no /react — that's browser-only) * vite.config.views.mjs — client/react/shared aliases (no /server — vscode/Node-only, noExtensionImports plugin would reject) * tsconfig.test.json — exclude packages/**/*.test.ts so Mocha tsc doesn't pick up vitest tests Validation gate green: tsc (main + test + vitest), vitest (1121 passed / 1 skipped), npm run vite-prod (ext + views), oxlint (0 errors / 436 baseline warnings), eslint --quiet (clean). --- docs/trpc-webview-guide.md | 2 +- l10n/bundle.l10n.json | 1 - package-lock.json | 39 ++- package.json | 2 - packages/README.md | 22 +- packages/webview-rpc/README.md | 267 ++++++++++++++++ packages/webview-rpc/package.json | 52 ++++ .../webview-rpc/src/client/errorLink.test.ts | 288 ++++++++++++++++++ packages/webview-rpc/src/client/errorLink.ts | 94 ++++++ packages/webview-rpc/src/client/events.ts | 178 +++++++++++ packages/webview-rpc/src/client/index.ts | 16 + .../src/client}/vscodeLink.test.ts | 0 .../webview-rpc/src/client}/vscodeLink.ts | 4 +- packages/webview-rpc/src/index.ts | 17 ++ .../webview-rpc/src/react}/WebviewContext.tsx | 9 +- packages/webview-rpc/src/react/index.ts | 12 + .../webview-rpc/src/react/useTrpcClient.ts | 168 ++++++++++ .../src/server}/baseRouterContext.ts | 64 +--- packages/webview-rpc/src/server/index.ts | 27 ++ .../src/server/middleware/index.ts | 8 + .../server}/middleware/loggingMiddleware.ts | 8 +- .../server}/middleware/telemetryMiddleware.ts | 29 +- .../src/server}/middleware/types.ts | 6 +- .../webview-rpc/src/server}/setupTrpc.ts | 4 +- .../src/shared}/TypedEventSink.test.ts | 0 .../webview-rpc/src/shared}/TypedEventSink.ts | 9 - .../webview-rpc/src/shared}/vscodeProtocol.ts | 0 packages/webview-rpc/tsconfig.json | 11 + src/panels/DocumentTab.ts | 2 +- src/panels/MigrationAssistantTab.ts | 4 +- src/panels/QueryEditorTab.ts | 4 +- .../migration/helpers/migrationHelpers.ts | 2 +- src/panels/migration/steps/phase1Discovery.ts | 2 +- .../migration/steps/phase2Assessment.ts | 2 +- .../migration/steps/phase3SchemaConversion.ts | 2 +- .../migration/steps/phase4Provisioning.ts | 2 +- src/panels/trpc/appRouter.ts | 4 +- .../trpc/middleware/azextTelemetryRunner.ts | 3 +- .../trpc/middleware/outputChannelLogger.ts | 2 +- .../trpc/routers/migrationEventsRouter.ts | 2 +- .../trpc/routers/queryEditorEventsRouter.ts | 2 +- src/panels/trpc/trpc.ts | 10 +- src/webviews/api/trpc/errorLink.test.ts | 131 -------- src/webviews/api/trpc/errorLink.ts | 43 --- src/webviews/api/trpc/useTrpcClient.ts | 127 -------- .../Document/state/DocumentContext.tsx | 25 +- .../state/DocumentContextProvider.tsx | 4 +- .../cosmosdb/Migration/MigrationAssistant.tsx | 2 +- .../Migration/state/MigrationChannel.ts | 4 +- .../QueryPanel/GenerateQueryInput.tsx | 20 +- .../QueryEditor/state/QueryEditorContext.tsx | 25 +- .../state/QueryEditorContextProvider.tsx | 4 +- src/webviews/index.tsx | 2 +- .../utils/context/BaseContextProvider.tsx | 5 +- tsconfig.base.json | 6 +- tsconfig.test.json | 10 +- vite.config.ext.mjs | 3 + vite.config.views.mjs | 5 + 58 files changed, 1332 insertions(+), 464 deletions(-) create mode 100644 packages/webview-rpc/README.md create mode 100644 packages/webview-rpc/package.json create mode 100644 packages/webview-rpc/src/client/errorLink.test.ts create mode 100644 packages/webview-rpc/src/client/errorLink.ts create mode 100644 packages/webview-rpc/src/client/events.ts create mode 100644 packages/webview-rpc/src/client/index.ts rename {src/webviews/api/trpc => packages/webview-rpc/src/client}/vscodeLink.test.ts (100%) rename {src/webviews/api/trpc => packages/webview-rpc/src/client}/vscodeLink.ts (98%) create mode 100644 packages/webview-rpc/src/index.ts rename {src/webviews => packages/webview-rpc/src/react}/WebviewContext.tsx (89%) create mode 100644 packages/webview-rpc/src/react/index.ts create mode 100644 packages/webview-rpc/src/react/useTrpcClient.ts rename {src/panels/trpc => packages/webview-rpc/src/server}/baseRouterContext.ts (51%) create mode 100644 packages/webview-rpc/src/server/index.ts create mode 100644 packages/webview-rpc/src/server/middleware/index.ts rename {src/panels/trpc => packages/webview-rpc/src/server}/middleware/loggingMiddleware.ts (94%) rename {src/panels/trpc => packages/webview-rpc/src/server}/middleware/telemetryMiddleware.ts (83%) rename {src/panels/trpc => packages/webview-rpc/src/server}/middleware/types.ts (86%) rename {src/panels/trpc => packages/webview-rpc/src/server}/setupTrpc.ts (99%) rename {src/utils => packages/webview-rpc/src/shared}/TypedEventSink.test.ts (100%) rename {src/utils => packages/webview-rpc/src/shared}/TypedEventSink.ts (94%) rename {src/panels/trpc => packages/webview-rpc/src/shared}/vscodeProtocol.ts (100%) create mode 100644 packages/webview-rpc/tsconfig.json delete mode 100644 src/webviews/api/trpc/errorLink.test.ts delete mode 100644 src/webviews/api/trpc/errorLink.ts delete mode 100644 src/webviews/api/trpc/useTrpcClient.ts diff --git a/docs/trpc-webview-guide.md b/docs/trpc-webview-guide.md index 911ee23f7..60f0b63ee 100644 --- a/docs/trpc-webview-guide.md +++ b/docs/trpc-webview-guide.md @@ -148,7 +148,7 @@ export const appRouter = router({ In your panel class: ```typescript -import { TypedEventSink } from '../utils/TypedEventSink'; +import { TypedEventSink } from '@cosmosdb/webview-rpc'; import { setupTrpc } from '../webviews/api/extension-server/setupTrpc'; class MyPanel extends BaseTab { diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 3f7ffdda7..cf34bf476 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -679,7 +679,6 @@ "Press Alt+Down to open column menu": "Press Alt+Down to open column menu", "Previous query:": "Previous query:", "Priority Level": "Priority Level", - "Procedure not found: {name}": "Procedure not found: {name}", "Project field help": "Project field help", "Project Name": "Project Name", "Project:": "Project:", diff --git a/package-lock.json b/package-lock.json index 986812632..83bffcd29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,8 +26,6 @@ "@microsoft/vscode-azureresources-api": "~3.1.0", "@monaco-editor/react": "~4.7.0", "@prantlf/jsonlint": "~17.0.0", - "@trpc/client": "~11.17.0", - "@trpc/server": "~11.17.0", "@vscode/l10n": "~0.0.18", "@vscode/prompt-tsx": "^0.4.0-alpha.7", "allotment": "~1.20.4", @@ -782,6 +780,10 @@ "resolved": "packages/schema-analyzer", "link": true }, + "node_modules/@cosmosdb/webview-rpc": { + "resolved": "packages/webview-rpc", + "link": true + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -12987,6 +12989,39 @@ "optional": true } } + }, + "packages/webview-rpc": { + "name": "@cosmosdb/webview-rpc", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@trpc/client": "~11.17.0", + "@trpc/server": "~11.17.0" + }, + "devDependencies": { + "@types/node": "~25.9.1", + "@types/react": "~19.2.15", + "@types/vscode": "~1.109.0", + "@types/vscode-webview": "~1.57.5", + "@vscode/l10n": "~0.0.18", + "react": "~19.2.1", + "vitest": "~4.1.7" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "@vscode/l10n": ">=0.0.18", + "react": ">=18.0.0" + }, + "peerDependenciesMeta": { + "@vscode/l10n": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 4df5b7ce1..f1fbd76df 100644 --- a/package.json +++ b/package.json @@ -155,8 +155,6 @@ "@microsoft/vscode-azureresources-api": "~3.1.0", "@monaco-editor/react": "~4.7.0", "@prantlf/jsonlint": "~17.0.0", - "@trpc/client": "~11.17.0", - "@trpc/server": "~11.17.0", "@vscode/l10n": "~0.0.18", "@vscode/prompt-tsx": "^0.4.0-alpha.7", "allotment": "~1.20.4", diff --git a/packages/README.md b/packages/README.md index fb39313ff..c6f8aae5b 100644 --- a/packages/README.md +++ b/packages/README.md @@ -2,18 +2,26 @@ This directory contains standalone packages that are part of the monorepo. +## Active Packages + +| Package | Description | Status | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `@cosmosdb/nosql-language-service` | NoSQL language service — parser, AST, autocomplete, hover, formatting, and editor providers | ✅ Active | +| `@cosmosdb/schema-analyzer` | Schema inference from sampled documents | ✅ Active | +| `@cosmosdb/webview-rpc` | Generic tRPC transport for VS Code webviews: `setupTrpc`, `vscodeLink`, `errorLink`, `TypedEventSink`, pluggable logging/telemetry middleware bodies, and React bindings (`WebviewContext` + `useTrpcClient`). Subpaths: `./server`, `./client`, `./react`. | ✅ Active | + ## Planned Packages -| Package | Description | Status | -| ---------------------------------- | ------------------------------------------------------------------------------------------- | --------- | -| `@cosmosdb/nosql-language-service` | NoSQL language service — parser, AST, autocomplete, hover, formatting, and editor providers | ✅ Active | -| `@cosmosdb/schema-analyzer` | Schema inference from sampled documents | ✅ Active | -| `@cosmosdb/shared` | Shared tRPC contracts, Zod schemas, and types | Planned | -| `@cosmosdb/webviews` | React/Fluent UI webview client | Planned | +| Package | Description | Status | +| -------------------- | --------------------------------------------- | ------- | +| `@cosmosdb/shared` | Shared tRPC contracts, Zod schemas, and types | Planned | +| `@cosmosdb/webviews` | React/Fluent UI webview client | Planned | ## Adding a New Package 1. Create a new directory under `packages/` 2. Add a `package.json` with the package name scoped to `@cosmosdb/` 3. Add a `tsconfig.json` that extends `../../tsconfig.base.json` -4. The package will be automatically discovered by pnpm workspace +4. Add path aliases to `tsconfig.base.json` (`paths`) so `tsc` resolves the package to its `src/` +5. Add matching `resolve.alias` entries to `vite.config.ext.mjs` and/or `vite.config.views.mjs` (subpath aliases must come before the bare-package alias) +6. Run `npm install` from the repo root so npm workspaces creates the `node_modules/@cosmosdb/` junction diff --git a/packages/webview-rpc/README.md b/packages/webview-rpc/README.md new file mode 100644 index 000000000..6b3b232f6 --- /dev/null +++ b/packages/webview-rpc/README.md @@ -0,0 +1,267 @@ +# `@cosmosdb/webview-rpc` + +Generic [tRPC](https://trpc.io) transport for VS Code webviews. The package is intentionally **application-agnostic** — it ships only the framework pieces (transport, middleware factories, adapter interfaces) and knows nothing about any specific extension's routers, contexts, or telemetry backend. Concrete logger / telemetry runners, tRPC instances, and routers all live in the consumer. + +## What's in here + +| Subpath | Side | Purpose | +| ------------------------------ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `@cosmosdb/webview-rpc` | shared | `TypedEventSink` — single-consumer async event sink (re-exported from `./shared`). | +| `@cosmosdb/webview-rpc/server` | extension-host (Node + `vscode`) | `setupTrpc`, `BaseRouterContext`, `WithRequired`, middleware factories (`loggingMiddlewareBody`, `telemetryMiddlewareBody`), middleware types (`ProcedureInvocation`, `ProcedureType`, `MiddlewareResultLike`), `ProcedureLogger` / `TelemetryRunner` adapter interfaces, plus re-exports of `initTRPC` / `AnyRouter` from `@trpc/server`. | +| `@cosmosdb/webview-rpc/client` | webview (browser, no `vscode` API) | `vscodeLink`, `errorLink`, `createEventChannel` + `RpcEventChannel` / `RpcEventEmitter` types, wire-protocol types (`VsCodeLinkRequestMessage`, `VsCodeLinkResponseMessage`, `StopOperation`, `OperationContext`). | +| `@cosmosdb/webview-rpc/react` | webview (browser, React) | `WebviewContext` + `WithWebviewContext` provider and the `useTrpcClient()` hook. Returns `{ trpcClient, events }` — a per-webview singleton pair cached by `vscodeApi`, so every call inside the same webview hands back the **same** client and the **same** event channel. Re-exports `AnyRouter` for consumer-side type aliases. | + +## Wiring + +A complete wire-up has three pieces: a **router on the server**, a **client in the webview**, and a shared **router type** the client imports for end-to-end type safety. tRPC itself is re-exported through this package, so the consumer never needs a direct `@trpc/*` import. + +### 1. Server (extension host) + +```ts +// src/panels/myAppRouter.ts ────────────────────────────────────────────────── +import { + type BaseRouterContext, + initTRPC, + loggingMiddlewareBody, + setupTrpc, + telemetryMiddlewareBody, +} from '@cosmosdb/webview-rpc/server'; +import * as vscode from 'vscode'; +import { z } from 'zod'; +import { myLogger, myTelemetryRunner } from './observability'; // your adapters + +// 1. Extend the framework's BaseRouterContext with whatever your procedures need. +// `signal` (AbortSignal) is populated by setupTrpc per-call; `telemetry` +// optionally by the telemetry middleware. +export interface MyRouterContext extends BaseRouterContext { + panel: vscode.WebviewPanel; + db: MyDatabaseConnection; +} + +// 2. Build a tRPC instance bound to that context. One instance per webview +// type keeps procedure type-inference precise — don't share across webviews. +const t = initTRPC.context().create(); + +// 3. (Optional) Apply the shared middleware bodies via `t.middleware(...)`. +const procedure = t.procedure + .use(t.middleware(loggingMiddlewareBody(myLogger))) + .use( + t.middleware( + telemetryMiddlewareBody(myTelemetryRunner, { + buildEventId: ({ type, path }) => `myApp.rpc.${type}.${path}`, + }), + ), + ); + +// 4. Define routes. The full router type is what the client imports for +// end-to-end type safety — *only the type*, never the value. +export const myAppRouter = t.router({ + greet: procedure + .input(z.object({ name: z.string() })) + .query(({ input }) => `hello, ${input.name}!`), + + saveDoc: procedure + .input(z.object({ text: z.string() })) + .mutation(async ({ ctx, input }) => { + // ctx.signal is an AbortSignal — pass it to cancellable APIs. + await ctx.db.write(input.text, { signal: ctx.signal }); + }), +}); + +export type MyAppRouter = typeof myAppRouter; + +// 5. Attach the router to a webview panel. Returns a disposable that tears +// down the message listener and aborts in-flight work on panel disposal. +export function attachMyRouter(panel: vscode.WebviewPanel, db: MyDatabaseConnection) { + const ctx: MyRouterContext = { panel, db }; + const { disposable } = setupTrpc(panel, ctx, myAppRouter, t.createCallerFactory); + return disposable; +} +``` + +### 2. Client — vanilla webview (no React) + +If you're not using React, talk to `vscodeLink` directly. The link only needs a `send` callback (postMessage) and an `onReceive` subscriber that hands incoming responses to a handler. + +```ts +// src/webview/main.ts ───────────────────────────────────────────────────────── +import { + createEventChannel, + errorLink, + vscodeLink, + type VsCodeLinkResponseMessage, +} from '@cosmosdb/webview-rpc/client'; +import { createTRPCClient, loggerLink } from '@trpc/client'; +import type { MyAppRouter } from '../panels/myAppRouter'; + +declare function acquireVsCodeApi(): { postMessage(msg: unknown): void }; +const vscodeApi = acquireVsCodeApi(); + +// One event channel per client. Subscribe / unsubscribe at will. +const events = createEventChannel(); +events.onError((err, info) => console.error(`[tRPC] ${info.path}`, err)); +events.onSuccess((info) => console.debug(`[tRPC] ${info.path} ok`)); +events.onAborted((info) => console.debug(`[tRPC] ${info.path} canceled`)); + +const client = createTRPCClient({ + links: [ + loggerLink(), // console diagnostics, optional + errorLink(events), + vscodeLink({ + send: (msg) => vscodeApi.postMessage(msg), + onReceive: (handler) => { + const listener = (event: MessageEvent) => { + const data = event.data as VsCodeLinkResponseMessage | undefined; + if (data?.id) handler(data); + }; + window.addEventListener('message', listener); + return () => window.removeEventListener('message', listener); + }, + }), + ], +}); + +const greeting = await client.greet.query({ name: 'world' }); +``` + +### 3. Client — React webview + +The `/react` subpath bundles the `acquireVsCodeApi` plumbing and the boilerplate above into two pieces: `WithWebviewContext` (provider) and `useTrpcClient` (hook). + +`useTrpcClient` returns a **per-webview singleton** `{ trpcClient, events }` cached by `vscodeApi` — call the hook from as many components as you like; every caller in the same webview gets the same client and the same event channel. That means cross-cutting subscribers (toasts, ARIA announcements, telemetry) added anywhere in the tree see every event. + +```tsx +// src/webview/index.tsx ─────────────────────────────────────────────────────── +import { WithWebviewContext } from '@cosmosdb/webview-rpc/react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App'; + +declare function acquireVsCodeApi(): { postMessage(msg: unknown): void }; +const vscodeApi = acquireVsCodeApi(); + +createRoot(document.getElementById('root')!).render( + + + , +); +``` + +```tsx +// src/webview/App.tsx ───────────────────────────────────────────────────────── +import { useTrpcClient } from '@cosmosdb/webview-rpc/react'; +import { useEffect, useState } from 'react'; +import type { MyAppRouter } from '../panels/myAppRouter'; + +export function App() { + // Same `{ trpcClient, events }` for every call inside this webview. + // `events` is identity-stable across renders → safe as a useEffect dep. + const { trpcClient, events } = useTrpcClient(); + + // Cross-cutting handlers: subscribe anywhere, get every event. + // Each `on*` returns an unsubscribe function — perfect for cleanup. + useEffect(() => { + const offError = events.onError((err, info) => + console.error(`[tRPC] ${info.path}: ${err.message}`), + ); + const offAborted = events.onAborted((info) => + console.debug(`[tRPC] ${info.path} canceled`), + ); + return () => { + offError(); + offAborted(); + }; + }, [events]); + + const [greeting, setGreeting] = useState(''); + useEffect(() => { + void trpcClient.greet.query({ name: 'world' }).then(setGreeting); + }, [trpcClient]); + + return

{greeting}

; +} +``` + +> **Need to mutate responses (retry / fallback / payload rewrite)?** The event channel is intentionally **observer-only** — handlers can't change the value or convert errors into successes. Write a dedicated `TRPCLink` for that; it's the native tRPC extension point and we deliberately don't duplicate it. + +### 4. Server → client streaming with `TypedEventSink` + +For long-running work (background tasks, progress, log streams) the server pushes events through a `TypedEventSink` and exposes them as a tRPC subscription. The sink bridges imperative `emit()` calls into the async-iterable shape tRPC subscriptions consume. + +```ts +// Server side +import { TypedEventSink } from '@cosmosdb/webview-rpc'; + +type AppEvent = + | { type: 'progress'; percent: number } + | { type: 'done'; result: string }; + +const events = new TypedEventSink(); + +// Inside your router (re-using `t` and `procedure` from above): +export const myAppRouter = t.router({ + // ...other routes... + onEvent: procedure.subscription(async function* ({ ctx }) { + for await (const event of events) { + if (ctx.signal?.aborted) return; // honour cancellation + yield event; + } + }), +}); + +// Anywhere in your extension: +events.emit({ type: 'progress', percent: 42 }); +events.emit('done', { result: 'ok' }); // two-arg form for autocompletion + +// Don't forget to close the sink when the owning tab/session is disposed, +// otherwise the subscription generator never completes: +panel.onDidDispose(() => events.close()); +``` + +```tsx +// React webview side +trpcClient.onEvent.subscribe(undefined, { + onData: (event) => /* event is typed as AppEvent */ console.log(event), + onError: (err) => console.error(err), +}); +``` + +## Adapter pattern + +The middleware bodies are **logger-agnostic** and **telemetry-runner-agnostic**. The consumer supplies concrete implementations of the two interfaces below and passes them to the factory functions: + +```ts +import { type ProcedureLogger, type TelemetryRunner, loggingMiddlewareBody, telemetryMiddlewareBody } from '@cosmosdb/webview-rpc/server'; + +// Example: write a one-line summary to a vscode.LogOutputChannel. +const myLogger: ProcedureLogger = { + onStart: ({ type, path }) => channel.debug(`[tRPC] ${type} ${path}`), + onEnd: ({ type, path, durationMs, ok, aborted }) => + channel.debug(`[tRPC] ${type} ${path} ${aborted ? 'canceled' : ok ? 'ok' : 'error'} (${durationMs}ms)`), +}; + +// Example: open a scope per call, enrich ctx with it, then close it +// (success/failure decided from the MiddlewareResultLike). +const myRunner: TelemetryRunner<{ scope: MyScope }> = { + async run(eventId, invocation, invoke) { + const scope = openScope(eventId); + try { + const result = await invoke({ scope }); + scope.end(result.ok ? 'ok' : 'error', result.error); + return result; + } catch (err) { + scope.end('error', err); + throw err; + } + }, +}; + +// Then wire them into your own tRPC instance: +const t = initTRPC.context().create(); +export const proc = t.procedure + .use(t.middleware(loggingMiddlewareBody(myLogger))) + .use(t.middleware(telemetryMiddlewareBody(myRunner, { buildEventId: ({ type, path }) => `myApp.${type}.${path}` }))); +``` + +## Subpath separation + +`/server` and `/client` are **strictly separated** so the webview bundler cannot accidentally pull `vscode` API imports into the browser bundle. Wire-protocol types live in `/` (shared) and are re-imported by both sides. The `/react` subpath builds on `/client` and is the only one that imports React. diff --git a/packages/webview-rpc/package.json b/packages/webview-rpc/package.json new file mode 100644 index 000000000..99c68b843 --- /dev/null +++ b/packages/webview-rpc/package.json @@ -0,0 +1,52 @@ +{ + "name": "@cosmosdb/webview-rpc", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "Generic tRPC transport for VS Code webviews: postMessage wire protocol, abort-aware extension-host dispatcher (setupTrpc), client-side tRPC links (vscodeLink, errorLink), pluggable logging/telemetry middleware bodies, a single-consumer async event sink (TypedEventSink), and React bindings (WebviewContext + useTrpcClient). Application code (routers, contexts, telemetry adapters) lives in the consumer.", + "main": "src/index.ts", + "types": "src/index.ts", + "exports": { + ".": "./src/index.ts", + "./server": "./src/server/index.ts", + "./client": "./src/client/index.ts", + "./react": "./src/react/index.ts" + }, + "files": [ + "src" + ], + "scripts": { + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest" + }, + "dependencies": { + "@trpc/client": "~11.17.0", + "@trpc/server": "~11.17.0" + }, + "peerDependencies": { + "@vscode/l10n": ">=0.0.18", + "react": ">=18.0.0" + }, + "peerDependenciesMeta": { + "@vscode/l10n": { + "optional": true + }, + "react": { + "optional": true + } + }, + "devDependencies": { + "@types/node": "~25.9.1", + "@types/react": "~19.2.15", + "@types/vscode": "~1.109.0", + "@types/vscode-webview": "~1.57.5", + "@vscode/l10n": "~0.0.18", + "react": "~19.2.1", + "vitest": "~4.1.7" + }, + "engines": { + "node": ">=22" + }, + "license": "MIT" +} diff --git a/packages/webview-rpc/src/client/errorLink.test.ts b/packages/webview-rpc/src/client/errorLink.test.ts new file mode 100644 index 000000000..370d64a37 --- /dev/null +++ b/packages/webview-rpc/src/client/errorLink.test.ts @@ -0,0 +1,288 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type AnyRouter } from '@trpc/server'; +import { observable } from '@trpc/server/observable'; +import { vi, type Mock } from 'vitest'; +import { errorLink } from './errorLink'; +import { createEventChannel, type RpcEventEmitter } from './events'; + +/** + * Build a downstream link that emits one of: `next` value, `error`, or + * `complete`, so tests can drive each branch of the link wrapper. + */ +type DownstreamOutcome = + | { kind: 'next'; value: { result: { data: unknown } } } + | { kind: 'error'; error: unknown } + | { kind: 'complete' }; + +function makeDownstreamNext(outcome: DownstreamOutcome) { + return () => + observable<{ result: { data: unknown } }, unknown>((observer) => { + if (outcome.kind === 'next') { + observer.next(outcome.value); + observer.complete(); + } else if (outcome.kind === 'error') { + observer.error(outcome.error); + } else { + observer.complete(); + } + return () => void 0; + }); +} + +interface Harness { + onNext: Mock; + onError: Mock; + onComplete: Mock; + events: RpcEventEmitter; + success: Mock; + error: Mock; + aborted: Mock; +} + +function createTestHarness(type: 'query' | 'mutation' | 'subscription', outcome: DownstreamOutcome): Harness { + const events = createEventChannel(); + const success = vi.fn(); + const error = vi.fn(); + const aborted = vi.fn(); + events.onSuccess(success); + events.onError(error); + events.onAborted(aborted); + + const link = errorLink(events); + const linkRuntime = link({} as never); + + const op = { + id: 0, + type, + path: 'demo.someProcedure', + input: undefined, + context: { trpc: { requestId: 'r-1' } }, + signal: null, + }; + + const next = makeDownstreamNext(outcome); + const obs = linkRuntime({ op, next } as never); + + const onNext: Mock = vi.fn(); + const onError: Mock = vi.fn(); + const onComplete: Mock = vi.fn(); + obs.subscribe({ next: onNext, error: onError, complete: onComplete }); + + return { onNext, onError, onComplete, events, success, error, aborted }; +} + +describe('errorLink', () => { + describe('errors', () => { + it('forwards query errors to channel onError subscribers', () => { + const h = createTestHarness('query', { kind: 'error', error: new Error('boom') }); + + expect(h.error).toHaveBeenCalledTimes(1); + const [forwarded, info] = h.error.mock.calls[0] as [Error, { type: string; path: string }]; + expect(forwarded).toBeInstanceOf(Error); + expect(forwarded.message).toBe('boom'); + expect(info).toEqual({ type: 'query', path: 'demo.someProcedure' }); + + // The error is re-emitted downstream so call-site .catch handlers still fire. + expect(h.onError).toHaveBeenCalledTimes(1); + // Aborted/success channels are not touched for a plain error. + expect(h.aborted).not.toHaveBeenCalled(); + expect(h.success).not.toHaveBeenCalled(); + }); + + it('forwards mutation errors to channel onError subscribers', () => { + const h = createTestHarness('mutation', { kind: 'error', error: new Error('nope') }); + + expect(h.error).toHaveBeenCalledTimes(1); + expect(h.error.mock.calls[0][1]).toEqual({ type: 'mutation', path: 'demo.someProcedure' }); + expect(h.onError).toHaveBeenCalledTimes(1); + }); + + it('normalises non-Error rejections into Error instances', () => { + const h = createTestHarness('query', { kind: 'error', error: 'string failure' }); + + expect(h.error).toHaveBeenCalledTimes(1); + const forwarded = h.error.mock.calls[0][0] as Error; + expect(forwarded).toBeInstanceOf(Error); + expect(forwarded.message).toBe('string failure'); + }); + + it('does not publish subscription errors to the channel', () => { + const h = createTestHarness('subscription', { kind: 'error', error: new Error('sub') }); + + // Subscriptions have their own per-call onError hook; this link must + // not double-report them through the central channel. + expect(h.error).not.toHaveBeenCalled(); + expect(h.aborted).not.toHaveBeenCalled(); + // The error still propagates down the link chain so the subscription's + // own onError callback can react. + expect(h.onError).toHaveBeenCalledTimes(1); + }); + }); + + describe('aborts', () => { + it('routes top-level AbortError to onAborted, never to onError', () => { + const abortErr = Object.assign(new Error('Aborted'), { name: 'AbortError' }); + const h = createTestHarness('query', { kind: 'error', error: abortErr }); + + expect(h.aborted).toHaveBeenCalledTimes(1); + expect(h.aborted.mock.calls[0][0]).toEqual({ type: 'query', path: 'demo.someProcedure' }); + expect(h.error).not.toHaveBeenCalled(); + // Always re-emitted downstream. + expect(h.onError).toHaveBeenCalledTimes(1); + }); + + it('detects AbortError nested in cause (TRPCClientError wrapping)', () => { + const cause = Object.assign(new Error('Aborted'), { name: 'AbortError' }); + const wrapped = Object.assign(new Error('TRPCClientError'), { cause }); + const h = createTestHarness('mutation', { kind: 'error', error: wrapped }); + + expect(h.aborted).toHaveBeenCalledTimes(1); + expect(h.error).not.toHaveBeenCalled(); + }); + + it('does not publish subscription aborts to the channel', () => { + const abortErr = Object.assign(new Error('Aborted'), { name: 'AbortError' }); + const h = createTestHarness('subscription', { kind: 'error', error: abortErr }); + + expect(h.aborted).not.toHaveBeenCalled(); + expect(h.error).not.toHaveBeenCalled(); + expect(h.onError).toHaveBeenCalledTimes(1); + }); + + it('silently drops aborts when there are no onAborted subscribers', () => { + const events = createEventChannel(); + const error = vi.fn(); + events.onError(error); + + const link = errorLink(events); + const linkRuntime = link({} as never); + const abortErr = Object.assign(new Error('Aborted'), { name: 'AbortError' }); + const obs = linkRuntime({ + op: { id: 0, type: 'query', path: 'p', input: undefined, context: {}, signal: null }, + next: makeDownstreamNext({ kind: 'error', error: abortErr }), + } as never); + + const onError = vi.fn(); + obs.subscribe({ next: vi.fn(), error: onError, complete: vi.fn() }); + + // Abort dropped at channel; onError never fired. + expect(error).not.toHaveBeenCalled(); + // Call-site still sees the rejection. + expect(onError).toHaveBeenCalledTimes(1); + }); + }); + + describe('successes', () => { + it('publishes query success with extracted data to channel onSuccess', () => { + const h = createTestHarness('query', { kind: 'next', value: { result: { data: 'ok' } } }); + + expect(h.success).toHaveBeenCalledTimes(1); + const [info, data] = h.success.mock.calls[0] as [{ type: string; path: string }, unknown]; + expect(info).toEqual({ type: 'query', path: 'demo.someProcedure' }); + expect(data).toBe('ok'); + + expect(h.onNext).toHaveBeenCalledWith({ result: { data: 'ok' } }); + expect(h.onComplete).toHaveBeenCalledTimes(1); + expect(h.onError).not.toHaveBeenCalled(); + expect(h.error).not.toHaveBeenCalled(); + }); + + it('does not publish subscription emissions to the channel', () => { + // Subscriptions emit values too, but we deliberately skip success + // publication for them — they have their own onData. + const h = createTestHarness('subscription', { kind: 'next', value: { result: { data: 1 } } }); + + expect(h.success).not.toHaveBeenCalled(); + expect(h.onNext).toHaveBeenCalledTimes(1); + }); + + it('passes through complete signals without publishing anything', () => { + const h = createTestHarness('query', { kind: 'complete' }); + + expect(h.success).not.toHaveBeenCalled(); + expect(h.error).not.toHaveBeenCalled(); + expect(h.aborted).not.toHaveBeenCalled(); + expect(h.onComplete).toHaveBeenCalledTimes(1); + expect(h.onError).not.toHaveBeenCalled(); + }); + }); + + describe('pub-sub semantics', () => { + it('delivers each event to multiple subscribers', () => { + const events = createEventChannel(); + const a = vi.fn(); + const b = vi.fn(); + const c = vi.fn(); + events.onError(a); + events.onError(b); + events.onError(c); + + const link = errorLink(events); + const linkRuntime = link({} as never); + const obs = linkRuntime({ + op: { id: 0, type: 'query', path: 'p', input: undefined, context: {}, signal: null }, + next: makeDownstreamNext({ kind: 'error', error: new Error('x') }), + } as never); + obs.subscribe({ next: vi.fn(), error: vi.fn(), complete: vi.fn() }); + + expect(a).toHaveBeenCalledTimes(1); + expect(b).toHaveBeenCalledTimes(1); + expect(c).toHaveBeenCalledTimes(1); + }); + + it('returns idempotent unsubscribe from on* methods', () => { + const events = createEventChannel(); + const handler = vi.fn(); + const off = events.onError(handler); + off(); + off(); // second call is a no-op + events.emitError(new Error('x'), { type: 'query', path: 'p' }); + expect(handler).not.toHaveBeenCalled(); + }); + + it('isolates exceptions thrown by one handler from siblings', () => { + const events = createEventChannel(); + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => void 0); + const bad = vi.fn(() => { + throw new Error('bad subscriber'); + }); + const good = vi.fn(); + events.onError(bad); + events.onError(good); + + events.emitError(new Error('x'), { type: 'query', path: 'p' }); + + expect(bad).toHaveBeenCalledTimes(1); + expect(good).toHaveBeenCalledTimes(1); + expect(consoleSpy).toHaveBeenCalled(); + consoleSpy.mockRestore(); + }); + + it('allows a subscriber to unsubscribe during dispatch without affecting siblings', () => { + const events = createEventChannel(); + const order: string[] = []; + // Use a ref object so the closure can see the unsubscribe function + // that's only known *after* `events.onError(a)` returns. + const offRef: { current: (() => void) | undefined } = { current: undefined }; + const a = vi.fn(() => { + order.push('a'); + offRef.current?.(); + }); + const b = vi.fn(() => order.push('b')); + offRef.current = events.onError(a); + events.onError(b); + + events.emitError(new Error('x'), { type: 'query', path: 'p' }); + + expect(order).toEqual(['a', 'b']); + // After unsubscription, a no longer fires. + events.emitError(new Error('y'), { type: 'query', path: 'p' }); + expect(a).toHaveBeenCalledTimes(1); + expect(b).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/packages/webview-rpc/src/client/errorLink.ts b/packages/webview-rpc/src/client/errorLink.ts new file mode 100644 index 000000000..ddbc39a5b --- /dev/null +++ b/packages/webview-rpc/src/client/errorLink.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type TRPCClientError, type TRPCLink } from '@trpc/client'; +import { type AnyRouter } from '@trpc/server'; +import { observable } from '@trpc/server/observable'; +import { type RpcEventEmitter } from './events'; + +/** + * tRPC link that observes the outcome of each query / mutation and + * republishes it through an {@link RpcEventEmitter} channel, so any + * number of subscribers can react to successes, errors, and caller + * aborts from one central place. + * + * Behaviour: + * + * - **Subscriptions** are passed through untouched. They have their + * own per-call `.subscribe({ onData, onError, onComplete })` API and + * routing them through the channel would surface every streamed + * error twice. + * - **Successes** publish `{ result.data }` to the channel. The + * downstream `next` is always called so the call-site promise + * resolves normally — the link is observer-only. + * - **Errors** that match the client-side `AbortError` shape are + * routed to `emitAborted` and **never** to `emitError`. Other errors + * are routed to `emitError`. In both cases the error is re-emitted + * downstream so the call-site `.catch(...)` still fires — the link + * never swallows. + * + * @example + * ```ts + * const events = createEventChannel(); + * const client = createTRPCClient({ + * links: [loggerLink(), errorLink(events), vscodeLink({ send, onReceive })], + * }); + * events.onError((err, info) => toaster.error(`${info.path}: ${err.message}`)); + * ``` + */ +export function errorLink(events: RpcEventEmitter): TRPCLink { + return () => { + return ({ next, op }) => { + return observable((observer) => { + return next(op).subscribe({ + next(value) { + // Subscriptions emit many values and complete differently; + // treat only one-shot queries/mutations as "succeeded". + if (op.type !== 'subscription') { + // tRPC v11 envelope shape: { result: { data: T } } for + // a settled query/mutation. Defensive read so a + // shape-mismatched link upstream still degrades to + // `undefined` data instead of crashing the pipeline. + const data = (value as { result?: { data?: unknown } })?.result?.data; + events.emitSuccess({ type: op.type, path: op.path }, data); + } + observer.next(value); + }, + error(err: unknown) { + if (op.type !== 'subscription') { + if (isAbortError(err)) { + // Client-initiated cancellation — never reach + // onError; surface to onAborted (if anyone is + // subscribed) and otherwise drop silently. + events.emitAborted({ type: op.type, path: op.path }); + } else { + const error = err instanceof Error ? err : new Error(String(err)); + events.emitError(error, { type: op.type, path: op.path }); + } + } + // Always re-emit so call-site `.catch(...)` handlers still fire. + observer.error(err as TRPCClientError); + }, + complete() { + observer.complete(); + }, + }); + }); + }; + }; +} + +/** + * Heuristic for client-initiated `AbortSignal` cancellation. Matches + * the standard `DOMException('…', 'AbortError')` shape on both the + * error itself and its `cause` chain (tRPC wraps the original in a + * `TRPCClientError`). + */ +function isAbortError(err: unknown): boolean { + if (!err || typeof err !== 'object') return false; + if ((err as { name?: string }).name === 'AbortError') return true; + const cause = (err as { cause?: { name?: string } }).cause; + return cause?.name === 'AbortError'; +} diff --git a/packages/webview-rpc/src/client/events.ts b/packages/webview-rpc/src/client/events.ts new file mode 100644 index 000000000..9fb356b21 --- /dev/null +++ b/packages/webview-rpc/src/client/events.ts @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Cross-cutting observability channel for a single tRPC client instance. + * + * The channel is the *only* sanctioned extension point for observing + * outcomes of queries and mutations from outside the call site: + * centralised toasts, ARIA announcements, telemetry, status-bar + * indicators, cancellation logs, and so on. Each subscriber sees every + * event for as long as it stays subscribed. + * + * The channel is intentionally **observer-only** — handlers cannot + * mutate the response value or convert an error into a success. If you + * need true interceptor behaviour (retry / fallback / payload rewrite), + * write a dedicated `TRPCLink` and add it to the client's `links` + * array; that is the native tRPC extension point and we deliberately do + * not duplicate it. + * + * Subscriptions are **not** routed through this channel. They have + * their own per-call `.subscribe({ onData, onError, onComplete })` + * hooks; double-reporting them centrally would surface every streamed + * error twice. Only `query` and `mutation` operations are observed. + */ + +/** + * Metadata about the procedure call that triggered a lifecycle event. + * The `type` field is narrowed to `query | mutation` because + * subscriptions are filtered out before the event is published. + */ +export interface CallInfo { + type: 'query' | 'mutation'; + path: string; +} + +/** + * Handler invoked when a query or mutation resolves successfully. + * + * `data` is the resolved value the call site would receive from + * `await client.foo.query()`. It is typed as `unknown` because a single + * central handler typically routes by `info.path` rather than knowing + * the per-procedure result type at the subscription site. + */ +export type SuccessHandler = (info: CallInfo, data: unknown) => void; + +/** + * Handler invoked when a query or mutation rejects with a non-abort + * error. Caller-initiated cancellations are routed to + * {@link AbortedHandler} instead — see {@link RpcEventChannel.onAborted}. + */ +export type ErrorHandler = (error: Error, info: CallInfo) => void; + +/** + * Handler invoked when a query or mutation was canceled via the + * `AbortSignal` the caller passed to it. Exists so consumers can react + * to user-initiated cancellations (e.g. a "Run Query" → "Cancel" flow) + * without dressing up an abort as an error in a central toast. + * + * If nobody subscribes to `onAborted`, aborts are silently dropped at + * the channel — the call site that triggered the cancellation already + * knows the outcome via its own `.catch(...)`. + */ +export type AbortedHandler = (info: CallInfo) => void; + +/** + * Function returned by every `on*` subscriber. Call it to detach the + * handler. Idempotent — calling it twice is safe and is a no-op the + * second time. + */ +export type Unsubscribe = () => void; + +/** + * Public surface of the per-client event channel. Returned alongside + * the tRPC client from `useTrpcClient` (and from the equivalent + * vanilla-client factory). + * + * @example + * ```ts + * const { trpcClient, events } = useTrpcClient(); + * + * useEffect(() => { + * const offError = events.onError((err, info) => toaster.error(`${info.path}: ${err.message}`)); + * const offOk = events.onSuccess((info) => statusBar.flash(`✔ ${info.path}`)); + * const offAbort = events.onAborted((info) => log.debug(`canceled: ${info.path}`)); + * return () => { offError(); offOk(); offAbort(); }; + * }, [events]); + * ``` + */ +export interface RpcEventChannel { + /** Subscribe to successful query/mutation completions. */ + onSuccess(handler: SuccessHandler): Unsubscribe; + /** Subscribe to non-abort query/mutation errors. */ + onError(handler: ErrorHandler): Unsubscribe; + /** Subscribe to caller-initiated query/mutation aborts. */ + onAborted(handler: AbortedHandler): Unsubscribe; +} + +/** + * Internal-but-exposed surface used by `errorLink` to publish events + * into the channel. Kept separate from {@link RpcEventChannel} so the + * subscription API stays read-only from the consumer's perspective. + * + * Each `emit*` method iterates a snapshot of the handler set so that a + * handler unsubscribing itself (or subscribing a new one) during + * dispatch does not perturb the current iteration. Exceptions thrown + * from a handler are reported via `console.error` and never propagate — + * one buggy subscriber must not break the rest of the pipeline. + */ +export interface RpcEventEmitter extends RpcEventChannel { + emitSuccess(info: CallInfo, data: unknown): void; + emitError(error: Error, info: CallInfo): void; + emitAborted(info: CallInfo): void; +} + +/** + * Build a fresh pub-sub channel for a single tRPC client. + * + * The channel is intentionally tiny — three `Set`s of handlers and a + * uniform `dispatch` helper that swallows handler exceptions so that + * one broken subscriber can't take down the rest of the pipeline. + * + * Subscribe functions return an idempotent `Unsubscribe`. Snapshots + * (`[...set]`) are taken before dispatch so a handler can safely + * subscribe / unsubscribe during the call without disturbing the + * in-flight iteration. + */ +export function createEventChannel(): RpcEventEmitter { + const successHandlers = new Set(); + const errorHandlers = new Set(); + const abortedHandlers = new Set(); + + function dispatch void>(handlers: Set, invoke: (handler: T) => void): void { + // Snapshot first so subscribe/unsubscribe inside a handler is safe — + // `Array.from` (not `[...handlers]`) keeps `no-useless-spread` happy. + const snapshot = Array.from(handlers); + for (const handler of snapshot) { + try { + invoke(handler); + } catch (err) { + // A broken subscriber must not break siblings or the link chain. + // oxlint-disable-next-line no-console + console.error('[webview-rpc] event handler threw', err); + } + } + } + + return { + onSuccess(handler) { + successHandlers.add(handler); + return () => { + successHandlers.delete(handler); + }; + }, + onError(handler) { + errorHandlers.add(handler); + return () => { + errorHandlers.delete(handler); + }; + }, + onAborted(handler) { + abortedHandlers.add(handler); + return () => { + abortedHandlers.delete(handler); + }; + }, + emitSuccess(info, data) { + dispatch(successHandlers, (h) => h(info, data)); + }, + emitError(error, info) { + dispatch(errorHandlers, (h) => h(error, info)); + }, + emitAborted(info) { + dispatch(abortedHandlers, (h) => h(info)); + }, + }; +} diff --git a/packages/webview-rpc/src/client/index.ts b/packages/webview-rpc/src/client/index.ts new file mode 100644 index 000000000..5993d977e --- /dev/null +++ b/packages/webview-rpc/src/client/index.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Webview entry point. Re-exports the client-side surface (browser-safe; + * no `vscode` API). + * + * The shared wire-protocol types are re-exported from the package root + * (`@cosmosdb/webview-rpc`). + */ + +export * from './vscodeLink'; +export * from './errorLink'; +export * from './events'; diff --git a/src/webviews/api/trpc/vscodeLink.test.ts b/packages/webview-rpc/src/client/vscodeLink.test.ts similarity index 100% rename from src/webviews/api/trpc/vscodeLink.test.ts rename to packages/webview-rpc/src/client/vscodeLink.test.ts diff --git a/src/webviews/api/trpc/vscodeLink.ts b/packages/webview-rpc/src/client/vscodeLink.ts similarity index 98% rename from src/webviews/api/trpc/vscodeLink.ts rename to packages/webview-rpc/src/client/vscodeLink.ts index 514e955ea..302c2117d 100644 --- a/src/webviews/api/trpc/vscodeLink.ts +++ b/packages/webview-rpc/src/client/vscodeLink.ts @@ -6,9 +6,9 @@ import { TRPCClientError, type Operation, type TRPCLink } from '@trpc/client'; import { type AnyRouter } from '@trpc/server'; import { observable } from '@trpc/server/observable'; // Their example uses a reference from /server/ and so do we: https://trpc.io/docs/client/links#example -import { type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from '../../../panels/trpc/vscodeProtocol'; +import { type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from '../shared/vscodeProtocol'; -export type { VsCodeLinkRequestMessage, VsCodeLinkResponseMessage } from '../../../panels/trpc/vscodeProtocol'; +export type { VsCodeLinkRequestMessage, VsCodeLinkResponseMessage } from '../shared/vscodeProtocol'; interface VSCodeLinkOptions { // Function to send a message to the server / extension diff --git a/packages/webview-rpc/src/index.ts b/packages/webview-rpc/src/index.ts new file mode 100644 index 000000000..9aec21399 --- /dev/null +++ b/packages/webview-rpc/src/index.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Root entry point — re-exports the shared (side-independent) surface of + * `@cosmosdb/webview-rpc`. For side-specific imports, use the subpath + * entries: + * + * - `@cosmosdb/webview-rpc/server` for extension-host code (`vscode` API + Node). + * - `@cosmosdb/webview-rpc/client` for webview code (browser, no `vscode` API). + * - `@cosmosdb/webview-rpc/react` for React bindings on top of `/client`. + */ + +export * from './shared/TypedEventSink'; +export * from './shared/vscodeProtocol'; diff --git a/src/webviews/WebviewContext.tsx b/packages/webview-rpc/src/react/WebviewContext.tsx similarity index 89% rename from src/webviews/WebviewContext.tsx rename to packages/webview-rpc/src/react/WebviewContext.tsx index 319759d49..5cf8cfa5a 100644 --- a/src/webviews/WebviewContext.tsx +++ b/packages/webview-rpc/src/react/WebviewContext.tsx @@ -17,8 +17,8 @@ export type WebviewContextValue = { * React context that exposes the per-webview `vscodeApi` handle * (returned by `acquireVsCodeApi()` in the webview bootstrap) to any * descendant component. Consumers use `useContext(WebviewContext)` — - * typically via the {@link import('./api/trpc/useTrpcClient').useTrpcClient} - * hook, which reads it under the hood. + * typically via the {@link useTrpcClient} hook, which reads it under + * the hood. * * The default value is `{} as WebviewContextValue` — components must * be rendered inside a {@link WithWebviewContext} (or another provider @@ -38,13 +38,10 @@ export const WebviewContext = createContext({} as WebviewCo * * createRoot(document.getElementById('root')!).render( * - * + * * , * ); * ``` - * - * Mirrors the helper of the same name in the documentdb sister package - * so future extraction is a one-line import rename. */ export const WithWebviewContext = ({ vscodeApi, diff --git a/packages/webview-rpc/src/react/index.ts b/packages/webview-rpc/src/react/index.ts new file mode 100644 index 000000000..0768fe228 --- /dev/null +++ b/packages/webview-rpc/src/react/index.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from './WebviewContext'; +export * from './useTrpcClient'; + +// Re-export the base router-shape type so consumers writing generic +// helpers around `TrpcClient` don't need to import directly +// from `@trpc/server` (purely a type — erased at runtime). +export type { AnyRouter } from '@trpc/server'; diff --git a/packages/webview-rpc/src/react/useTrpcClient.ts b/packages/webview-rpc/src/react/useTrpcClient.ts new file mode 100644 index 000000000..a6b37057b --- /dev/null +++ b/packages/webview-rpc/src/react/useTrpcClient.ts @@ -0,0 +1,168 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createTRPCClient, loggerLink, type TRPCClient as TRPCClientV11 } from '@trpc/client'; +import { type AnyRouter } from '@trpc/server'; +import { useContext } from 'react'; +import { type WebviewApi } from 'vscode-webview'; +import { + createEventChannel, + errorLink, + type RpcEventChannel, + type RpcEventEmitter, + vscodeLink, + type VsCodeLinkRequestMessage, + type VsCodeLinkResponseMessage, +} from '../client'; +import { WebviewContext, type WebviewState } from './WebviewContext'; + +/** + * Convenience alias for the tRPC client instance returned by + * {@link useTrpcClient}. Useful when you need to thread the client + * down through props or store it in a ref: + * + * ```ts + * const clientRef = useRef | null>(null); + * ``` + * + * Aliases tRPC v11's `TRPCClient` (formerly `CreateTRPCClient`, + * deprecated in v11 and slated for removal in v12). + */ +export type TrpcClient = TRPCClientV11; + +/** + * Shape returned by {@link useTrpcClient}. The pair is identity-stable + * across renders and across multiple calls to the hook inside the same + * webview — see the hook docstring for the cache strategy. + */ +export interface UseTrpcClientResult { + /** The shared tRPC client for the current webview. */ + trpcClient: TrpcClient; + /** + * Cross-cutting observability channel for the client. Subscribe via + * `events.onError(...)` / `onSuccess(...)` / `onAborted(...)` — + * each call returns an unsubscribe function suitable for use as a + * `useEffect` cleanup. + */ + events: RpcEventChannel; +} + +/** + * Internal cache entry — keeps the runtime tRPC client (typed as + * `unknown` because it varies per webview) and its event channel + * paired together so they're always handed out as a unit. + */ +interface CacheEntry { + trpcClient: unknown; + events: RpcEventEmitter; +} + +/** + * Per-webview cache of `{ trpcClient, events }` pairs, keyed by the + * `vscodeApi` handle (which is, by VS Code's design, a per-webview + * singleton returned exactly once by `acquireVsCodeApi()`). + * + * A `WeakMap` gives us "one client per webview" naturally: + * + * - Two components calling `useTrpcClient` in the *same* webview share + * the same `vscodeApi` and therefore the same cache entry — so they + * get the same client and the same event channel. Subscribers from + * anywhere in the tree see every event. + * - When the webview is disposed and the `vscodeApi` is garbage- + * collected, the cache entry is reclaimed automatically — no manual + * cleanup, no module-level leak between hot-reloads or tests. + * + * The `TRouter` generic is compile-time only — at runtime the client + * is a tRPC proxy whose shape is identical for any router. We assume + * (and the codebase enforces) one router per webview, so casting the + * cached client to `TrpcClient` at the call site is sound. + */ +const clientCache = new WeakMap, CacheEntry>(); + +/** + * Custom React hook that provides the shared tRPC client and event + * channel for the current webview. + * + * Call it as many times as you like — every call inside the same + * webview returns the **same** `{ trpcClient, events }` pair, so: + * + * - There is exactly one tRPC client per webview (no duplicate link + * stacks, no duplicate `postMessage` listeners). + * - `events` is identity-stable across renders, which means + * `useEffect(() => events.onError(...), [events])` subscribes exactly + * once and unsubscribes on unmount. + * - Cross-cutting handlers (toasts, ARIA announcements, telemetry) are + * subscribed via `events.onError(...)` / `onSuccess(...)` / + * `onAborted(...)` from anywhere in the component tree; every + * subscriber sees every event. + * + * @typeParam TRouter - The per-webview app router type. + * + * @example + * ```tsx + * const { trpcClient, events } = useTrpcClient(); + * + * useEffect(() => { + * const offError = events.onError((err, info) => + * toaster.error(`${info.path}: ${err.message}`), + * ); + * return offError; + * }, [events, toaster]); + * ``` + */ +export function useTrpcClient(): UseTrpcClientResult { + const { vscodeApi } = useContext(WebviewContext); + + let entry = clientCache.get(vscodeApi); + if (!entry) { + const events = createEventChannel(); + + /** + * Forward outbound RPC requests to the extension host. Closing + * over `vscodeApi` is safe because the cache entry's lifetime + * is bounded by the same handle — when `vscodeApi` is reclaimed + * the entry goes with it. + */ + const send = (message: VsCodeLinkRequestMessage) => { + vscodeApi.postMessage(message); + }; + + /** + * Register a single `window.message` listener and forward + * tRPC-shaped envelopes to the supplied callback. tRPC calls + * this once per in-flight request and uses the returned + * disposer to clean up — see tRPC's `vscodeLink` contract. + */ + const onReceive = (callback: (message: VsCodeLinkResponseMessage) => void) => { + const handler = (event: MessageEvent) => { + // a basic type guard here + if ((event.data as VsCodeLinkResponseMessage).id) { + const message = event.data as VsCodeLinkResponseMessage; + callback(message); + } + }; + + window.addEventListener('message', handler); + return () => { + window.removeEventListener('message', handler); + }; + }; + + const trpcClient = createTRPCClient({ + links: [loggerLink(), errorLink(events), vscodeLink({ send, onReceive })], + }); + + entry = { trpcClient, events }; + clientCache.set(vscodeApi, entry); + } + + // Safe cast: see the WeakMap docstring above — at runtime the + // client is a router-agnostic proxy, and one webview has one router + // by construction. + return { + trpcClient: entry.trpcClient as TrpcClient, + events: entry.events, + }; +} diff --git a/src/panels/trpc/baseRouterContext.ts b/packages/webview-rpc/src/server/baseRouterContext.ts similarity index 51% rename from src/panels/trpc/baseRouterContext.ts rename to packages/webview-rpc/src/server/baseRouterContext.ts index e081c2275..aab9b6bd6 100644 --- a/src/panels/trpc/baseRouterContext.ts +++ b/packages/webview-rpc/src/server/baseRouterContext.ts @@ -6,15 +6,11 @@ /** * Framework-level tRPC context types for the webview ↔ extension bridge. * - * This file is intentionally generic and free of any cosmosdb-specific - * concerns (no `webviewName`, no `IActionContext`, no `vscode.WebviewPanel`). - * It declares the contract that `setupTrpc.ts` and the client `vscodeLink.ts` - * rely on. App-level fields belong in {@link ../appRouter.CosmosDBRouterContext} - * (or any future per-app extension). - * - * Mirrors the public surface of `@microsoft/vscode-ext-react-webview` so - * that — should we extract the framework layer into its own package — this - * file becomes the package's `BaseRouterContext` module without changes. + * This file is intentionally generic and free of any application-specific + * concerns. It declares the contract that `setupTrpc.ts` and the client + * `vscodeLink.ts` rely on. Application code extends {@link BaseRouterContext} + * with its own fields (database connections, webview identifiers, action + * contexts, etc.). */ /** @@ -28,12 +24,7 @@ * * Kept minimal so the framework layer does not depend on any specific * telemetry library. Concrete telemetry middlewares may place a richer - * object on the app-level context instead (e.g. cosmosdb's - * `azextTelemetryRunner` exposes the full `IActionContext` via the - * {@link ../appRouter.CosmosDBRouterContext.actionContext} field - * rather than populating this field — `IActionContext.telemetry` - * carries trusted-value markers we don't want to leak into the - * framework's structural contract). + * object on the app-level context instead and leave this field unused. */ export interface TelemetryContext { properties: Record; @@ -48,15 +39,13 @@ export interface TelemetryContext { * by user-supplied telemetry middleware when one is attached to the * procedure (optional — base-only callers may leave it `undefined`). * - * Application code extends this type with its own fields (database - * connections, webview identifiers, action contexts, etc.) — see - * {@link ../appRouter.CosmosDBRouterContext}. + * Application code extends this type with its own fields. */ export interface BaseRouterContext { /** * Per-operation `AbortSignal` populated by `setupTrpc`. Procedures * can poll `signal.aborted` between yields or pass the signal to - * cancellation-aware APIs (e.g. the MongoDB driver). + * cancellation-aware APIs (e.g. database drivers, fetch). */ signal?: AbortSignal; @@ -64,18 +53,17 @@ export interface BaseRouterContext { * Telemetry context populated by the telemetry middleware (when used). * Optional — procedures that need it should null-check. * - * For richer telemetry shapes (e.g. `IActionContext` from azext-utils) - * extend this interface and add a typed field on the app-level context - * type rather than widening this base shape — keeps the framework - * layer dependency-free. + * For richer telemetry shapes extend this interface and add a typed + * field on the app-level context type rather than widening this base + * shape — keeps the framework layer dependency-free. */ telemetry?: TelemetryContext; } /** * Type helper that takes any context shape with an **optional** field `K` - * (typically `'telemetry'` or, in cosmosdb, `'actionContext'`) and - * returns the same shape with that field made **required**. + * (typically `'telemetry'`, but anything you populate via middleware + * works) and returns the same shape with that field made **required**. * * Use it on procedure handlers that are mounted on a procedure-builder * with the corresponding middleware already applied — at that point you @@ -90,30 +78,10 @@ export interface BaseRouterContext { * }); * ``` * - * Cosmosdb uses this with `'actionContext'` on `CosmosDBRouterContext` - * (see `appRouter.ts`) — every procedure built on `queryEditorProcedure` - * etc. gets `ctx.actionContext` populated by the azext runner. - * - * Mirrors documentdb's `WithTelemetry` helper but is generic over - * the key name so cosmosdb can apply the same pattern to its richer - * `actionContext` field without inventing a separate helper. + * Generic over the key name so applications can apply the same pattern + * to their own enriched fields (e.g. an `actionContext` populated by a + * custom telemetry runner) without inventing a separate helper. */ export type WithRequired>, K extends PropertyKey> = T & { [P in K]-?: NonNullable; }; - -/** - * Convenience alias for the most common cosmosdb case: assert that - * `actionContext` is non-optional on a procedure that runs through the - * `azextTelemetryRunner` middleware. - * - * Equivalent to `WithRequired`, but reads naturally - * at the call site: - * - * ```ts - * .query(({ ctx }: { ctx: WithActionContext }) => { - * ctx.actionContext.telemetry.suppressIfSuccessful = true; // no `?.` - * }); - * ``` - */ -export type WithActionContext = WithRequired; diff --git a/packages/webview-rpc/src/server/index.ts b/packages/webview-rpc/src/server/index.ts new file mode 100644 index 000000000..487b3ee1d --- /dev/null +++ b/packages/webview-rpc/src/server/index.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Extension-host entry point. Re-exports the server-side surface for use + * in code that runs in the Node.js extension host (depends on `vscode`). + * + * The shared wire-protocol types are re-exported from the package root + * (`@cosmosdb/webview-rpc`). + */ + +export * from './baseRouterContext'; +export * from './setupTrpc'; +export * from './middleware'; + +// Re-export shared protocol types so server code can import everything +// from a single subpath if it prefers. +export type { VsCodeLinkRequestMessage, VsCodeLinkResponseMessage } from '../shared/vscodeProtocol'; + +// Re-export the tRPC builder + base router type. Consumers wire their +// own `initTRPC.context().create()` instances (one per webview, so +// each gets a precisely-typed router/procedure) — exposing them here +// keeps `@trpc/server` an implementation detail of this package: the +// host extension can stay tRPC-agnostic at the import level. +export { initTRPC, type AnyRouter } from '@trpc/server'; diff --git a/packages/webview-rpc/src/server/middleware/index.ts b/packages/webview-rpc/src/server/middleware/index.ts new file mode 100644 index 000000000..8057214e1 --- /dev/null +++ b/packages/webview-rpc/src/server/middleware/index.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from './types'; +export * from './loggingMiddleware'; +export * from './telemetryMiddleware'; diff --git a/src/panels/trpc/middleware/loggingMiddleware.ts b/packages/webview-rpc/src/server/middleware/loggingMiddleware.ts similarity index 94% rename from src/panels/trpc/middleware/loggingMiddleware.ts rename to packages/webview-rpc/src/server/middleware/loggingMiddleware.ts index 4eb0e6805..81507d488 100644 --- a/src/panels/trpc/middleware/loggingMiddleware.ts +++ b/packages/webview-rpc/src/server/middleware/loggingMiddleware.ts @@ -15,18 +15,16 @@ * * `loggerLink()` from `@trpc/client` only sees what the client sends and * receives — it has no access to the server-side `ctx` and cannot honour - * per-call opt-outs the way a middleware can. See - * `plans/webview-vs-documentdb-package.md` section 2.3 for the - * architecture decision. + * per-call opt-outs the way a middleware can. * * # Why a body factory (not bound to a specific tRPC instance)? * * `t.middleware(fn)` is bound to the instance's context type, but the * logger doesn't care about ctx. By returning a plain function we make - * the body reusable across all three (and any future) tRPC instances: + * the body reusable across every tRPC instance the consumer creates: * * ```ts - * const mw = queryEditorT.middleware(loggingMiddlewareBody(consoleProcedureLogger)); + * const mw = appT.middleware(loggingMiddlewareBody(consoleProcedureLogger)); * ``` */ diff --git a/src/panels/trpc/middleware/telemetryMiddleware.ts b/packages/webview-rpc/src/server/middleware/telemetryMiddleware.ts similarity index 83% rename from src/panels/trpc/middleware/telemetryMiddleware.ts rename to packages/webview-rpc/src/server/middleware/telemetryMiddleware.ts index ea9469ddd..1a7d9d465 100644 --- a/src/panels/trpc/middleware/telemetryMiddleware.ts +++ b/packages/webview-rpc/src/server/middleware/telemetryMiddleware.ts @@ -15,16 +15,15 @@ * - The runner decides **how to record** the event and **what to enrich * the procedure ctx with** for the rest of the pipeline. * - * This keeps the framework dependency-free; the concrete adapter for - * `@microsoft/vscode-azext-utils` lives in `azextTelemetryRunner.ts` - * and is the only place that imports azext-utils. + * This keeps the framework dependency-free — every concrete telemetry + * backend (Application Insights, OpenTelemetry, plain `console`, …) is + * a {@link TelemetryRunner} adapter living in the consumer. * * # Why a middleware (and not a `loggerLink`)? * * Telemetry needs access to the server-side `ctx` (and the ability to - * mutate it, e.g. to surface an `actionContext` to procedures). Links - * only see transport-level data. See `plans/webview-vs-documentdb-package.md` - * section 2.3. + * mutate it, e.g. to surface a backend-specific scope object to + * procedures). Links only see transport-level data. * * # Why a body factory? * @@ -32,9 +31,9 @@ * a plain function lets the same factory plug into any tRPC instance: * * ```ts - * const telemetryMW = queryEditorT.middleware( - * telemetryMiddlewareBody(azextTelemetryRunner, { - * buildEventId: ({ type, path }) => `cosmosDB.rpc.${type}.${path}`, + * const telemetryMW = appT.middleware( + * telemetryMiddlewareBody(myRunner, { + * buildEventId: ({ type, path }) => `myApp.rpc.${type}.${path}`, * }), * ); * ``` @@ -47,7 +46,7 @@ import { type MiddlewareResultLike, type ProcedureInvocation } from './types'; * * The runner is invoked once per call. Implementations should: * - * 1. Open whatever telemetry scope they need (an `IActionContext`, an + * 1. Open whatever telemetry scope they need (an action context, an * OpenTelemetry span, a plain `console.time`, …). * 2. Call `invoke(enrichment)` with whatever fields they want to push * into the procedure's `ctx`. The framework merges those into the @@ -59,9 +58,8 @@ import { type MiddlewareResultLike, type ProcedureInvocation } from './types'; * * `TEnrichment` is the precise shape the runner contributes to ctx — * typically a record with one or two well-known keys (e.g. - * `{ actionContext, telemetry }`). Procedures that need those fields - * declare them on their concrete context type (see - * `appRouter.CosmosDBRouterContext`). + * `{ scope, telemetry }`). Procedures that need those fields declare + * them on their concrete context type. */ export interface TelemetryRunner { run( @@ -75,7 +73,7 @@ export interface TelemetryMiddlewareOptions { /** * Build the telemetry event id from the invocation. Defaults to * `"${type}.${path}"`. Override to add a namespace prefix - * (`cosmosDB.rpc.…`) or to apply per-call sampling rules. + * (`myApp.rpc.…`) or to apply per-call sampling rules. */ buildEventId?: (invocation: ProcedureInvocation) => string; } @@ -85,8 +83,7 @@ export interface TelemetryMiddlewareOptions { * * Pass the returned function to `t.middleware(...)`. The runner's * `TEnrichment` type must be assignable to the tRPC instance's context - * type — usually achieved by extending the per-app context interface - * (see `CosmosDBRouterContext`). + * type — usually achieved by extending the per-app context interface. */ export function telemetryMiddlewareBody( runner: TelemetryRunner, diff --git a/src/panels/trpc/middleware/types.ts b/packages/webview-rpc/src/server/middleware/types.ts similarity index 86% rename from src/panels/trpc/middleware/types.ts rename to packages/webview-rpc/src/server/middleware/types.ts index 793c143c1..00e7d9d3c 100644 --- a/src/panels/trpc/middleware/types.ts +++ b/packages/webview-rpc/src/server/middleware/types.ts @@ -6,10 +6,8 @@ /** * Framework-level types shared by middleware factories under this folder. * - * Intentionally framework-only: no cosmosdb-specific concerns, no - * `@microsoft/vscode-azext-utils` import. Mirrors the shape we would - * expose from a future `@microsoft/vscode-ext-react-webview`-like - * package — see `plans/webview-vs-documentdb-package.md`. + * Intentionally framework-only: no application-specific concerns and no + * dependency on any concrete telemetry / logging library. */ /** The three tRPC procedure flavors. */ diff --git a/src/panels/trpc/setupTrpc.ts b/packages/webview-rpc/src/server/setupTrpc.ts similarity index 99% rename from src/panels/trpc/setupTrpc.ts rename to packages/webview-rpc/src/server/setupTrpc.ts index 24789e4cd..052b20f79 100644 --- a/src/panels/trpc/setupTrpc.ts +++ b/packages/webview-rpc/src/server/setupTrpc.ts @@ -6,8 +6,8 @@ import { getTRPCErrorFromUnknown, type AnyRouter } from '@trpc/server'; import * as l10n from '@vscode/l10n'; import type * as vscode from 'vscode'; +import { type VsCodeLinkRequestMessage } from '../shared/vscodeProtocol'; import { type BaseRouterContext } from './baseRouterContext'; -import { type VsCodeLinkRequestMessage } from './vscodeProtocol'; /** * Converts an unknown error into a tRPC-compatible error response. @@ -58,7 +58,7 @@ function safePostMessage(panel: vscode.WebviewPanel, message: unknown): boolean * both) to a single live `AsyncIterator`. * * Calling `[Symbol.asyncIterator]()` once is required for iterables like - * {@link import('../../utils/TypedEventSink').TypedEventSink} which + * {@link import('../shared/TypedEventSink').TypedEventSink} which * enforce single-consumer semantics; direct iterators are returned as-is. */ function toAsyncIterator(value: unknown): AsyncIterator { diff --git a/src/utils/TypedEventSink.test.ts b/packages/webview-rpc/src/shared/TypedEventSink.test.ts similarity index 100% rename from src/utils/TypedEventSink.test.ts rename to packages/webview-rpc/src/shared/TypedEventSink.test.ts diff --git a/src/utils/TypedEventSink.ts b/packages/webview-rpc/src/shared/TypedEventSink.ts similarity index 94% rename from src/utils/TypedEventSink.ts rename to packages/webview-rpc/src/shared/TypedEventSink.ts index bbb31924c..9e43090b5 100644 --- a/src/utils/TypedEventSink.ts +++ b/packages/webview-rpc/src/shared/TypedEventSink.ts @@ -15,15 +15,6 @@ export type DiscriminatedEvent = { type: string }; */ export type EventOfType = Extract; -/** - * Write-only interface for emitting events into a TypedEventSink. - * Used by session factories that need to emit a subset of events - * into sinks with different full event unions (e.g., DocumentEvent or QueryEditorEvent). - */ -export interface UntypedEventEmitter { - emit(event: { type: string; [key: string]: unknown }): void; -} - /** * A typed async-iterable event emitter that bridges imperative `emit()` calls * into the async generator consumed by tRPC subscriptions. diff --git a/src/panels/trpc/vscodeProtocol.ts b/packages/webview-rpc/src/shared/vscodeProtocol.ts similarity index 100% rename from src/panels/trpc/vscodeProtocol.ts rename to packages/webview-rpc/src/shared/vscodeProtocol.ts diff --git a/packages/webview-rpc/tsconfig.json b/packages/webview-rpc/tsconfig.json new file mode 100644 index 000000000..cc0779269 --- /dev/null +++ b/packages/webview-rpc/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "out", + "rootDir": "src", + "noEmit": true, + "types": ["node", "vitest/globals"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "out", "**/*.test.ts"] +} diff --git a/src/panels/DocumentTab.ts b/src/panels/DocumentTab.ts index a120d4421..c9ff4c4c8 100644 --- a/src/panels/DocumentTab.ts +++ b/src/panels/DocumentTab.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { setupTrpc } from '@cosmosdb/webview-rpc/server'; import * as l10n from '@vscode/l10n'; import * as vscode from 'vscode'; import { getCosmosDBKeyCredential } from '../cosmosdb/CosmosDBCredential'; @@ -10,7 +11,6 @@ import { type NoSqlQueryConnection } from '../cosmosdb/NoSqlQueryConnection'; import { type CosmosDBRecordIdentifier } from '../cosmosdb/types/queryResult'; import { BaseTab } from './BaseTab'; import { documentAppRouter, documentCallerFactory, type DocumentRouterContext } from './trpc/appRouter'; -import { setupTrpc } from './trpc/setupTrpc'; type DocumentTabMode = 'add' | 'edit' | 'view'; diff --git a/src/panels/MigrationAssistantTab.ts b/src/panels/MigrationAssistantTab.ts index cb1bc52e7..ba18f9e8d 100644 --- a/src/panels/MigrationAssistantTab.ts +++ b/src/panels/MigrationAssistantTab.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { TypedEventSink } from '@cosmosdb/webview-rpc'; +import { setupTrpc } from '@cosmosdb/webview-rpc/server'; import { VSCodeAzureSubscriptionProvider } from '@microsoft/vscode-azext-azureauth'; import { LocationListStep, @@ -35,7 +37,6 @@ import { createCosmosDBManagementClient } from '../utils/azureClients'; import { sanitizeCosmosDBAccountName } from '../utils/cosmosDBAccountName'; import { MIGRATION_SELECTED_MODEL_KEY } from '../utils/modelUtils'; import { pickAppResource, pickWorkspaceResource } from '../utils/pickItem/pickAppResource'; -import { TypedEventSink } from '../utils/TypedEventSink'; import { BaseTab } from './BaseTab'; import { getSelectedModel, IS_PHASE4_REQUIRED, isDebugPromptsEnabled } from './migration/helpers/aiHelpers'; import { emitMigrationEvent, resetCancellationToken } from './migration/helpers/migrationHelpers'; @@ -64,7 +65,6 @@ import { getAccessPatternsTemplateContent } from './migration/templates/accessPa import { getVolumetricsTemplateContent } from './migration/templates/volumetricsTemplate'; import { migrationAppRouter, migrationCallerFactory, type MigrationRouterContext } from './trpc/appRouter'; import { type MigrationEvent } from './trpc/routers/migrationEventsRouter'; -import { setupTrpc } from './trpc/setupTrpc'; export class MigrationAssistantTab extends BaseTab { public static readonly title = 'Cosmos DB Migration Assistant'; diff --git a/src/panels/QueryEditorTab.ts b/src/panels/QueryEditorTab.ts index 3b870b683..ebd9a31aa 100644 --- a/src/panels/QueryEditorTab.ts +++ b/src/panels/QueryEditorTab.ts @@ -4,6 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { type JSONSchema } from '@cosmosdb/schema-analyzer'; +import { TypedEventSink } from '@cosmosdb/webview-rpc'; +import { setupTrpc } from '@cosmosdb/webview-rpc/server'; import * as vscode from 'vscode'; import { getThemedIconPath } from '../constants'; import { getCosmosDBKeyCredential } from '../cosmosdb/CosmosDBCredential'; @@ -12,7 +14,6 @@ import { type QuerySession } from '../cosmosdb/session/QuerySession'; import { type SerializedQueryResult } from '../cosmosdb/types/queryResult'; import { SchemaFileStorage } from '../services/SchemaFileStorage'; import { getIsSurveyDisabledGlobally } from '../utils/survey'; -import { TypedEventSink } from '../utils/TypedEventSink'; import { BaseTab } from './BaseTab'; import { queryEditorAppRouter, @@ -21,7 +22,6 @@ import { type QueryEditorRouterContext, } from './trpc/appRouter'; import { type QueryEditorEvent } from './trpc/routers/queryEditorEventsRouter'; -import { setupTrpc } from './trpc/setupTrpc'; export class QueryEditorTab extends BaseTab { public static readonly title = 'Query Editor'; diff --git a/src/panels/migration/helpers/migrationHelpers.ts b/src/panels/migration/helpers/migrationHelpers.ts index a32eb8da5..010d224b3 100644 --- a/src/panels/migration/helpers/migrationHelpers.ts +++ b/src/panels/migration/helpers/migrationHelpers.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import * as vscode from 'vscode'; import { ext } from '../../../extensionVariables'; import { MigrationProjectService } from '../../../services/MigrationProjectService'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type MigrationEvent, type MigrationEventName, diff --git a/src/panels/migration/steps/phase1Discovery.ts b/src/panels/migration/steps/phase1Discovery.ts index 5fbdc4c37..06a807b75 100644 --- a/src/panels/migration/steps/phase1Discovery.ts +++ b/src/panels/migration/steps/phase1Discovery.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; import * as l10n from '@vscode/l10n'; import { renderPrompt } from '@vscode/prompt-tsx'; @@ -11,7 +12,6 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { ext } from '../../../extensionVariables'; import { MigrationProjectService, type ProjectJson } from '../../../services/MigrationProjectService'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type MigrationEvent } from '../../trpc/routers/migrationEventsRouter'; import { createMkDebug, diff --git a/src/panels/migration/steps/phase2Assessment.ts b/src/panels/migration/steps/phase2Assessment.ts index 2fac2c7ba..aa7debefc 100644 --- a/src/panels/migration/steps/phase2Assessment.ts +++ b/src/panels/migration/steps/phase2Assessment.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; import * as l10n from '@vscode/l10n'; import * as path from 'path'; @@ -11,7 +12,6 @@ import { ext } from '../../../extensionVariables'; import { MigrationProjectService, type ProjectJson } from '../../../services/MigrationProjectService'; import { extractStructuralDDL } from '../../../utils/ddlExtractor'; import { decodeFileBytes } from '../../../utils/decodeFileBytes'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type MigrationEvent } from '../../trpc/routers/migrationEventsRouter'; import { getCosmosDbBestPractices } from '../bestPractices'; import { diff --git a/src/panels/migration/steps/phase3SchemaConversion.ts b/src/panels/migration/steps/phase3SchemaConversion.ts index e2cb60d3b..0df037a47 100644 --- a/src/panels/migration/steps/phase3SchemaConversion.ts +++ b/src/panels/migration/steps/phase3SchemaConversion.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { callWithTelemetryAndErrorHandling } from '@microsoft/vscode-azext-utils'; import * as l10n from '@vscode/l10n'; import * as path from 'path'; import * as vscode from 'vscode'; import { ext } from '../../../extensionVariables'; import { MigrationProjectService, type ProjectJson } from '../../../services/MigrationProjectService'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type MigrationEvent } from '../../trpc/routers/migrationEventsRouter'; import { getCosmosDbBestPractices, getIndexPathSyntaxRule } from '../bestPractices'; import { diff --git a/src/panels/migration/steps/phase4Provisioning.ts b/src/panels/migration/steps/phase4Provisioning.ts index ac2b4b1f2..326fc754d 100644 --- a/src/panels/migration/steps/phase4Provisioning.ts +++ b/src/panels/migration/steps/phase4Provisioning.ts @@ -14,6 +14,7 @@ import { type CosmosClient, type IndexingPolicy as CosmosIndexingPolicy, } from '@azure/cosmos'; +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { VSCodeAzureSubscriptionProvider } from '@microsoft/vscode-azext-azureauth'; import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils'; import { callWithTelemetryAndErrorHandling, parseError, type IActionContext } from '@microsoft/vscode-azext-utils'; @@ -38,7 +39,6 @@ import { MigrationProjectService, type ProjectJson } from '../../../services/Mig import { createCosmosDBManagementClient } from '../../../utils/azureClients'; import { validateCosmosDBAccountName } from '../../../utils/cosmosDBAccountName'; import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type MigrationEvent } from '../../trpc/routers/migrationEventsRouter'; import { getCosmosDbBestPractices } from '../bestPractices'; import { type CosmosModel, type IndexingPolicy } from '../cosmosModel'; diff --git a/src/panels/trpc/appRouter.ts b/src/panels/trpc/appRouter.ts index d7846b232..688249deb 100644 --- a/src/panels/trpc/appRouter.ts +++ b/src/panels/trpc/appRouter.ts @@ -12,6 +12,8 @@ */ import { type PartitionKeyDefinition } from '@azure/cosmos'; +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; +import { type BaseRouterContext } from '@cosmosdb/webview-rpc/server'; import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; import { z } from 'zod'; @@ -21,8 +23,6 @@ import { type CosmosDBRecordIdentifier } from '../../cosmosdb/types/queryResult' import { type TelemetryContext } from '../../Telemetry'; import { openSurvey, promptAfterActionEventually } from '../../utils/survey'; import { ExperienceKind, UsageImpact } from '../../utils/surveyTypes'; -import { type TypedEventSink } from '../../utils/TypedEventSink'; -import { type BaseRouterContext } from './baseRouterContext'; import { documentRouterDef } from './routers/documentRouter'; import { migrationEventsRouterDef, type MigrationEvent } from './routers/migrationEventsRouter'; import { migrationRouterDef } from './routers/migrationRouter'; diff --git a/src/panels/trpc/middleware/azextTelemetryRunner.ts b/src/panels/trpc/middleware/azextTelemetryRunner.ts index fb0afd662..318b98de7 100644 --- a/src/panels/trpc/middleware/azextTelemetryRunner.ts +++ b/src/panels/trpc/middleware/azextTelemetryRunner.ts @@ -27,9 +27,8 @@ * read them from `ctx.actionContext.telemetry`. */ +import { type ProcedureInvocation, type TelemetryRunner } from '@cosmosdb/webview-rpc/server'; import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; -import { type TelemetryRunner } from './telemetryMiddleware'; -import { type ProcedureInvocation } from './types'; /** * Shape this runner injects into the procedure ctx. Application context diff --git a/src/panels/trpc/middleware/outputChannelLogger.ts b/src/panels/trpc/middleware/outputChannelLogger.ts index ec0ef7dd9..dce6eb70e 100644 --- a/src/panels/trpc/middleware/outputChannelLogger.ts +++ b/src/panels/trpc/middleware/outputChannelLogger.ts @@ -16,8 +16,8 @@ * Format: `[trpc] mutation queryEditor.runQuery 42.0ms ok` */ +import { type ProcedureLogger } from '@cosmosdb/webview-rpc/server'; import { ext } from '../../../extensionVariables'; -import { type ProcedureLogger } from './loggingMiddleware'; /** * Logger backed by `ext.outputChannel`. Successful calls go to `.debug` diff --git a/src/panels/trpc/routers/migrationEventsRouter.ts b/src/panels/trpc/routers/migrationEventsRouter.ts index ae9e9f350..be5b6bfc4 100644 --- a/src/panels/trpc/routers/migrationEventsRouter.ts +++ b/src/panels/trpc/routers/migrationEventsRouter.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { type ProjectJson } from '../../../services/MigrationProjectService'; import { type ModelInfo } from '../../../utils/modelUtils'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { type ProvisioningResult } from '../../migration/steps/phase4Provisioning'; import { migrationProcedure, migrationRouter } from '../trpc'; diff --git a/src/panels/trpc/routers/queryEditorEventsRouter.ts b/src/panels/trpc/routers/queryEditorEventsRouter.ts index 3f6d75dfe..1ee2a214e 100644 --- a/src/panels/trpc/routers/queryEditorEventsRouter.ts +++ b/src/panels/trpc/routers/queryEditorEventsRouter.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type TypedEventSink } from '@cosmosdb/webview-rpc'; import { z } from 'zod'; -import { type TypedEventSink } from '../../../utils/TypedEventSink'; import { queryEditorProcedure, queryEditorRouter } from '../trpc'; // ─── Query Editor Event Discriminated Union ───────────────────────────────── diff --git a/src/panels/trpc/trpc.ts b/src/panels/trpc/trpc.ts index 0929c9b17..ea45597b1 100644 --- a/src/panels/trpc/trpc.ts +++ b/src/panels/trpc/trpc.ts @@ -40,13 +40,15 @@ * @see https://trpc.io/docs/v11/procedures */ -import { initTRPC } from '@trpc/server'; +import { + initTRPC, + loggingMiddlewareBody, + type ProcedureInvocation, + telemetryMiddlewareBody, +} from '@cosmosdb/webview-rpc/server'; import { type DocumentRouterContext, type MigrationRouterContext, type QueryEditorRouterContext } from './appRouter'; import { azextTelemetryRunner } from './middleware/azextTelemetryRunner'; -import { loggingMiddlewareBody } from './middleware/loggingMiddleware'; import { outputChannelProcedureLogger } from './middleware/outputChannelLogger'; -import { telemetryMiddlewareBody } from './middleware/telemetryMiddleware'; -import { type ProcedureInvocation } from './middleware/types'; // ─── Shared observability wiring ──────────────────────────────────────────── diff --git a/src/webviews/api/trpc/errorLink.test.ts b/src/webviews/api/trpc/errorLink.test.ts deleted file mode 100644 index 8cd78f481..000000000 --- a/src/webviews/api/trpc/errorLink.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type AnyRouter } from '@trpc/server'; -import { observable } from '@trpc/server/observable'; -import { vi, type Mock } from 'vitest'; -import { errorLink, type ErrorHandler } from './errorLink'; - -/** - * Build a downstream link that emits one of: `next` value, `error`, or - * `complete`, so tests can drive each branch of the link wrapper. - */ -type DownstreamOutcome = - | { kind: 'next'; value: { result: { data: unknown } } } - | { kind: 'error'; error: unknown } - | { kind: 'complete' }; - -function makeDownstreamNext(outcome: DownstreamOutcome) { - return () => - observable<{ result: { data: unknown } }, unknown>((observer) => { - if (outcome.kind === 'next') { - observer.next(outcome.value); - observer.complete(); - } else if (outcome.kind === 'error') { - observer.error(outcome.error); - } else { - observer.complete(); - } - return () => void 0; - }); -} - -function createTestHarness( - type: 'query' | 'mutation' | 'subscription', - outcome: DownstreamOutcome, - onErrorHandler: (err: Error) => void, -) { - const link = errorLink(onErrorHandler); - const linkRuntime = link({} as never); - - const op = { - id: 0, - type, - path: 'demo.someProcedure', - input: undefined, - context: { trpc: { requestId: 'r-1' } }, - signal: null, - }; - - const next = makeDownstreamNext(outcome); - const obs = linkRuntime({ op, next } as never); - - const onNext: Mock = vi.fn(); - const onError: Mock = vi.fn(); - const onComplete: Mock = vi.fn(); - obs.subscribe({ next: onNext, error: onError, complete: onComplete }); - - return { onNext, onError, onComplete }; -} - -describe('errorLink', () => { - it('forwards query errors to the consumer onError handler', () => { - const handler = vi.fn() as Mock & ErrorHandler; - const { onError } = createTestHarness('query', { kind: 'error', error: new Error('boom') }, handler); - - expect(handler).toHaveBeenCalledTimes(1); - const forwarded = handler.mock.calls[0][0]; - expect(forwarded).toBeInstanceOf(Error); - expect(forwarded.message).toBe('boom'); - - // The error is re-emitted downstream so call-site .catch handlers still fire. - expect(onError).toHaveBeenCalledTimes(1); - }); - - it('forwards mutation errors to the consumer onError handler', () => { - const handler = vi.fn() as Mock & ErrorHandler; - const { onError } = createTestHarness('mutation', { kind: 'error', error: new Error('nope') }, handler); - - expect(handler).toHaveBeenCalledTimes(1); - expect(handler.mock.calls[0][0].message).toBe('nope'); - expect(onError).toHaveBeenCalledTimes(1); - }); - - it('normalises non-Error rejections into Error instances', () => { - const handler = vi.fn() as Mock & ErrorHandler; - createTestHarness('query', { kind: 'error', error: 'string failure' }, handler); - - expect(handler).toHaveBeenCalledTimes(1); - const forwarded = handler.mock.calls[0][0]; - expect(forwarded).toBeInstanceOf(Error); - expect(forwarded.message).toBe('string failure'); - }); - - it('does not forward subscription errors to the consumer handler', () => { - const handler = vi.fn() as Mock & ErrorHandler; - const { onError } = createTestHarness('subscription', { kind: 'error', error: new Error('sub') }, handler); - - // Subscriptions have their own per-call onError hook; this link must - // not double-report them through the consumer's global handler. - expect(handler).not.toHaveBeenCalled(); - - // The error still propagates down the link chain so the subscription's - // own onError callback can react. - expect(onError).toHaveBeenCalledTimes(1); - }); - - it('passes through successful values without invoking the handler', () => { - const handler = vi.fn() as Mock & ErrorHandler; - const { onNext, onError, onComplete } = createTestHarness( - 'query', - { kind: 'next', value: { result: { data: 'ok' } } }, - handler, - ); - - expect(handler).not.toHaveBeenCalled(); - expect(onNext).toHaveBeenCalledWith({ result: { data: 'ok' } }); - expect(onComplete).toHaveBeenCalledTimes(1); - expect(onError).not.toHaveBeenCalled(); - }); - - it('passes through complete signals without invoking the handler', () => { - const handler = vi.fn() as Mock & ErrorHandler; - const { onComplete, onError } = createTestHarness('query', { kind: 'complete' }, handler); - - expect(handler).not.toHaveBeenCalled(); - expect(onComplete).toHaveBeenCalledTimes(1); - expect(onError).not.toHaveBeenCalled(); - }); -}); diff --git a/src/webviews/api/trpc/errorLink.ts b/src/webviews/api/trpc/errorLink.ts deleted file mode 100644 index 690743e02..000000000 --- a/src/webviews/api/trpc/errorLink.ts +++ /dev/null @@ -1,43 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type TRPCClientError, type TRPCLink } from '@trpc/client'; -import { type AnyRouter } from '@trpc/server'; -import { observable } from '@trpc/server/observable'; - -export type ErrorHandler = (error: Error) => void; - -/** - * A tRPC link that catches errors from downstream links and forwards them - * to a handler callback. This mirrors the old channel-based `sendCommand` - * behavior where errors were automatically caught and shown to the user. - * - * Subscriptions are passed through without error interception — they have - * their own `onError` callbacks. - */ -export function errorLink(onError: ErrorHandler): TRPCLink { - return () => { - return ({ next, op }) => { - return observable((observer) => { - return next(op).subscribe({ - next(value) { - observer.next(value); - }, - error(err: unknown) { - // Subscriptions handle their own errors; only intercept queries/mutations - if (op.type !== 'subscription') { - const error = err instanceof Error ? err : new Error(String(err)); - onError(error); - } - observer.error(err as TRPCClientError); - }, - complete() { - observer.complete(); - }, - }); - }); - }; - }; -} diff --git a/src/webviews/api/trpc/useTrpcClient.ts b/src/webviews/api/trpc/useTrpcClient.ts deleted file mode 100644 index e4534375c..000000000 --- a/src/webviews/api/trpc/useTrpcClient.ts +++ /dev/null @@ -1,127 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createTRPCClient, loggerLink, type TRPCClient as TRPCClientV11 } from '@trpc/client'; -import { type AnyRouter } from '@trpc/server'; -import { useCallback, useContext, useMemo } from 'react'; -import { WebviewContext } from '../../WebviewContext'; -import { errorLink, type ErrorHandler } from './errorLink'; -import { vscodeLink, type VsCodeLinkRequestMessage, type VsCodeLinkResponseMessage } from './vscodeLink'; - -/** - * Convenience alias for the tRPC client instance returned by - * {@link useTrpcClient}. Useful when you need to thread the client - * down through props or store it in a ref: - * - * ```ts - * const clientRef = useRef | null>(null); - * ``` - * - * Aliases tRPC v11's `TRPCClient` (formerly `CreateTRPCClient`, - * deprecated in v11 and slated for removal in v12). - */ -export type TrpcClient = TRPCClientV11; - -/** - * Options accepted by {@link useTrpcClient}. - * - * Options are passed as an object (rather than positional parameters) - * so new fields can be added without breaking existing call sites. All - * fields are optional — a bare `useTrpcClient()` call returns - * a client with only the default link stack (`loggerLink` + `vscodeLink`). - */ -export interface UseTrpcClientOptions { - /** - * Invoked when a query or mutation surfaces an error through the - * link pipeline. Subscriptions deliver their errors through the - * caller's `subscribe({ onError })` callback and are intentionally - * not forwarded here (see `errorLink.ts`). - * - * Note: changing this handler between renders rebuilds the - * underlying tRPC client. Wrap in `useCallback` at the call site to - * keep the client stable. - */ - onError?: ErrorHandler; -} - -/** - * Custom React hook that provides a tRPC client for communication - * between the webview and the VSCode extension host. - * - * @typeParam TRouter - The per-webview app router type (e.g. - * `QueryEditorAppRouter`, `DocumentAppRouter`). - * @param options - See {@link UseTrpcClientOptions}. - * @returns An object containing the tRPC client as `trpcClient`. - * - * @example - * // No error handler — fire-and-forget calls only: - * const { trpcClient } = useTrpcClient(); - * - * @example - * // With an error handler that surfaces toasts: - * const onError = useCallback((err) => toaster.error(err.message), [toaster]); - * const { trpcClient } = useTrpcClient({ onError }); - */ -export function useTrpcClient(options: UseTrpcClientOptions = {}) { - const { onError } = options; - const { vscodeApi } = useContext(WebviewContext); - - /** - * Function to send messages to the VSCode extension. - * - * @param message - The message to send, following the VsCodeLinkRequestMessage format. - */ - const send = useCallback( - (message: VsCodeLinkRequestMessage) => { - vscodeApi.postMessage(message); - }, - [vscodeApi], - ); - - /** - * Function to handle incoming messages from the VSCode extension. - * This function is provided to the tRPC client and is used internally to manage tRPC responses. - * - * @param callback - The callback to invoke when a tRPC response message is received. - * @returns A function to unsubscribe the event listener. - * - * Note to code maintainers: - * The tRPC client expects this `onReceive` function to handle the subscription and unsubscription - * of the event listener for tRPC responses. It registers the handler when a tRPC request is made, - * and unregisters it after the response is received. - * Be cautious when modifying this function, as it could affect the tRPC client's ability to - * receive responses correctly. - */ - const onReceive = useCallback((callback: (message: VsCodeLinkResponseMessage) => void) => { - const handler = (event: MessageEvent) => { - // a basic type guard here - if ((event.data as VsCodeLinkResponseMessage).id) { - const message = event.data as VsCodeLinkResponseMessage; - callback(message); - } - }; - - window.addEventListener('message', handler); - return () => { - window.removeEventListener('message', handler); - }; - }, []); - - // Use useMemo to avoid recreating the client on every render - const trpcClient = useMemo>( - () => - createTRPCClient({ - links: [ - loggerLink(), - ...(onError ? [errorLink(onError)] : []), - vscodeLink({ send, onReceive }), - ], - }), - [onError, send, onReceive], - ); - - // Return the tRPC client - return { trpcClient }; -} diff --git a/src/webviews/cosmosdb/Document/state/DocumentContext.tsx b/src/webviews/cosmosdb/Document/state/DocumentContext.tsx index ad91249e9..c3bfca7d1 100644 --- a/src/webviews/cosmosdb/Document/state/DocumentContext.tsx +++ b/src/webviews/cosmosdb/Document/state/DocumentContext.tsx @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { useTrpcClient } from '@cosmosdb/webview-rpc/react'; import { Toaster, useId, useToastController } from '@fluentui/react-components'; import { createContext, type ReactNode, useContext, useEffect, useMemo, useReducer, useRef } from 'react'; import { type DocumentAppRouter } from '../../../../panels/trpc/appRouter'; -import { useTrpcClient } from '../../../api/trpc/useTrpcClient'; import { type BaseContextProvider } from '../../../utils/context/BaseContextProvider'; import { ErrorBoundary } from '../../../utils/ErrorBoundary'; import { DocumentContextProvider } from './DocumentContextProvider'; @@ -28,23 +28,20 @@ export const WithDocumentContext = ({ children }: { children: ReactNode }) => { const { dispatchToast } = useToastController(toasterId); const [state, dispatch] = useReducer(DocumentPanelDispatch, { ...defaultState }); - // Use a ref so the errorLink can forward errors to the provider once it's created. + // Use a ref so the central error subscriber can forward errors to the + // provider once it's created (the provider is built below from + // `trpcClient`, so it does not exist yet on the first render). const providerRef = useRef(null); - const onError = useMemo( - () => (error: Error) => { - void providerRef.current?.showErrorMessage(error.message); - }, - [], - ); - const { trpcClient } = useTrpcClient({ onError }); + const { trpcClient, events } = useTrpcClient(); const provider = useMemo( () => new DocumentContextProvider(dispatch, dispatchToast, trpcClient), [dispatchToast, trpcClient], ); - // Keep the ref pointing at the current provider so errorLink can forward errors. + // Keep the ref pointing at the current provider so the onError + // subscriber below can forward errors to it. useEffect(() => { providerRef.current = provider; return () => { @@ -52,6 +49,14 @@ export const WithDocumentContext = ({ children }: { children: ReactNode }) => { }; }, [provider]); + // Subscribe to the shared event channel exactly once — `events` is + // identity-stable across renders by `useTrpcClient`'s WeakMap cache. + useEffect(() => { + return events.onError((error) => { + void providerRef.current?.showErrorMessage(error.message); + }); + }, [events]); + useEffect(() => { return () => provider.dispose(); }, [provider]); diff --git a/src/webviews/cosmosdb/Document/state/DocumentContextProvider.tsx b/src/webviews/cosmosdb/Document/state/DocumentContextProvider.tsx index d84020236..d536fd33d 100644 --- a/src/webviews/cosmosdb/Document/state/DocumentContextProvider.tsx +++ b/src/webviews/cosmosdb/Document/state/DocumentContextProvider.tsx @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { type JSONObject, type JSONValue, type PartitionKeyDefinition } from '@azure/cosmos'; -import { type TRPCClient } from '@trpc/client'; +import { type TrpcClient } from '@cosmosdb/webview-rpc/react'; import * as l10n from '@vscode/l10n'; import { type DocumentAppRouter } from '../../../api/types'; import { BaseContextProvider, type DispatchToastFn } from '../../../utils/context/BaseContextProvider'; @@ -16,7 +16,7 @@ export class DocumentContextProvider extends BaseContextProvider void, dispatchToast: DispatchToastFn, - trpcClient: TRPCClient, + trpcClient: TrpcClient, ) { super(dispatchToast, trpcClient); } diff --git a/src/webviews/cosmosdb/Migration/MigrationAssistant.tsx b/src/webviews/cosmosdb/Migration/MigrationAssistant.tsx index 92da9047b..7ee30cdff 100644 --- a/src/webviews/cosmosdb/Migration/MigrationAssistant.tsx +++ b/src/webviews/cosmosdb/Migration/MigrationAssistant.tsx @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { useTrpcClient } from '@cosmosdb/webview-rpc/react'; import { Accordion, AccordionHeader, @@ -59,7 +60,6 @@ import { useCallback, useEffect, useMemo, useState, type ReactElement, type Reac import { type MigrationAppRouter } from '../../../panels/trpc/appRouter'; import { sanitizeCosmosDBAccountName, validateCosmosDBAccountName } from '../../../utils/cosmosDBAccountName'; import { formatTokenCount, partitionModelsByCapability } from '../../../utils/modelUtils'; -import { useTrpcClient } from '../../api/trpc/useTrpcClient'; import { CosmosDBIcon } from '../../icons/CosmosDBIcon'; import { BaseContextProvider, type DispatchToastFn } from '../../utils/context/BaseContextProvider'; import { ErrorBoundary } from '../../utils/ErrorBoundary'; diff --git a/src/webviews/cosmosdb/Migration/state/MigrationChannel.ts b/src/webviews/cosmosdb/Migration/state/MigrationChannel.ts index 65eeadd98..992c5b2a5 100644 --- a/src/webviews/cosmosdb/Migration/state/MigrationChannel.ts +++ b/src/webviews/cosmosdb/Migration/state/MigrationChannel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type TRPCClient } from '@trpc/client'; +import { type TrpcClient } from '@cosmosdb/webview-rpc/react'; import { type MigrationAppRouter } from '../../../../panels/trpc/appRouter'; /** @@ -37,7 +37,7 @@ export class MigrationChannel implements Channel { private readonly handlers = new Map>(); private subscription: { unsubscribe(): void } | undefined; - constructor(private readonly trpcClient: TRPCClient) { + constructor(private readonly trpcClient: TrpcClient) { // oxlint-disable-next-line typescript/no-unsafe-call, typescript/no-unsafe-member-access -- generic tRPC client typings this.subscription = ( trpcClient as unknown as { diff --git a/src/webviews/cosmosdb/QueryEditor/QueryPanel/GenerateQueryInput.tsx b/src/webviews/cosmosdb/QueryEditor/QueryPanel/GenerateQueryInput.tsx index 92e6aba95..a6cf4bf8a 100644 --- a/src/webviews/cosmosdb/QueryEditor/QueryPanel/GenerateQueryInput.tsx +++ b/src/webviews/cosmosdb/QueryEditor/QueryPanel/GenerateQueryInput.tsx @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { useTrpcClient } from '@cosmosdb/webview-rpc/react'; import { Button, Combobox, @@ -28,7 +29,6 @@ import { import * as l10n from '@vscode/l10n'; import { useCallback, useEffect, useRef, useState } from 'react'; import { type QueryEditorAppRouter } from '../../../../panels/trpc/appRouter'; -import { useTrpcClient } from '../../../api/trpc/useTrpcClient'; import { useQueryEditorState, useQueryEditorStateDispatch } from '../state/QueryEditorContext'; import { usePromptHistory } from './usePromptHistory'; @@ -130,7 +130,11 @@ const useStyles = makeStyles({ outline: '1px solid var(--vscode-focusBorder)', outlineOffset: '0px', boxShadow: 'none', - borderColor: 'transparent', + // Griffel rejects the `borderColor` shorthand; expand to longhands. + borderTopColor: 'transparent', + borderRightColor: 'transparent', + borderBottomColor: 'transparent', + borderLeftColor: 'transparent', borderRadius: '3px', }, { customizeSelector: (s) => `${s}${s}` }, @@ -214,7 +218,11 @@ const useStyles = makeStyles({ outline: '1px solid var(--vscode-focusBorder)', outlineOffset: '1px', boxShadow: 'none !important' as never, - borderColor: 'transparent', + // Griffel rejects the `borderColor` shorthand; expand to longhands. + borderTopColor: 'transparent', + borderRightColor: 'transparent', + borderBottomColor: 'transparent', + borderLeftColor: 'transparent', borderRadius: '6px', }, { customizeSelector: (s) => `${s}${s}${s}` }, @@ -244,7 +252,11 @@ const useStyles = makeStyles({ outline: '1px solid var(--vscode-focusBorder)', outlineOffset: '0px', boxShadow: 'none', - borderColor: 'transparent', + // Griffel rejects the `borderColor` shorthand; expand to longhands. + borderTopColor: 'transparent', + borderRightColor: 'transparent', + borderBottomColor: 'transparent', + borderLeftColor: 'transparent', borderRadius: '3px', }, { customizeSelector: (s) => `${s}${s}` }, diff --git a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx index 183cd72a4..5bc839c5a 100644 --- a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx +++ b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContext.tsx @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { useTrpcClient } from '@cosmosdb/webview-rpc/react'; import { Toaster, useId, useToastController } from '@fluentui/react-components'; import { type ReactNode, createContext, useContext, useEffect, useMemo, useReducer, useRef } from 'react'; import { type QueryEditorAppRouter } from '../../../../panels/trpc/appRouter'; -import { useTrpcClient } from '../../../api/trpc/useTrpcClient'; import { type BaseContextProvider } from '../../../utils/context/BaseContextProvider'; import { ErrorBoundary } from '../../../utils/ErrorBoundary'; import { QueryEditorContextProvider } from './QueryEditorContextProvider'; @@ -43,23 +43,20 @@ export const WithQueryEditorContext = ({ children }: { children: ReactNode }) => const { dispatchToast } = useToastController(toasterId); const [state, dispatch] = useReducer(QueryEditorDispatch, { ...defaultState }); - // Use a ref so the errorLink can forward errors to the provider once it's created. + // Use a ref so the central error subscriber can forward errors to the + // provider once it's created (the provider is built below from + // `trpcClient`, so it does not exist yet on the first render). const providerRef = useRef(null); - const onError = useMemo( - () => (error: Error) => { - void providerRef.current?.showErrorMessage(error.message); - }, - [], - ); - const { trpcClient } = useTrpcClient({ onError }); + const { trpcClient, events } = useTrpcClient(); const provider = useMemo( () => new QueryEditorContextProvider(dispatch, dispatchToast, trpcClient), [dispatchToast, trpcClient], ); - // Keep the ref pointing at the current provider so errorLink can forward errors. + // Keep the ref pointing at the current provider so the onError + // subscriber below can forward errors to it. useEffect(() => { providerRef.current = provider; return () => { @@ -67,6 +64,14 @@ export const WithQueryEditorContext = ({ children }: { children: ReactNode }) => }; }, [provider]); + // Subscribe to the shared event channel exactly once — `events` is + // identity-stable across renders by `useTrpcClient`'s WeakMap cache. + useEffect(() => { + return events.onError((error) => { + void providerRef.current?.showErrorMessage(error.message); + }); + }, [events]); + useEffect(() => { return () => provider.dispose(); }, [provider]); diff --git a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContextProvider.tsx b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContextProvider.tsx index 94463bb9c..5fe1144e6 100644 --- a/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContextProvider.tsx +++ b/src/webviews/cosmosdb/QueryEditor/state/QueryEditorContextProvider.tsx @@ -5,7 +5,7 @@ import { type PartitionKeyDefinition, type PriorityLevel } from '@azure/cosmos'; import { type JSONSchema } from '@cosmosdb/schema-analyzer'; -import { type TRPCClient } from '@trpc/client'; +import { type TrpcClient } from '@cosmosdb/webview-rpc/react'; import * as l10n from '@vscode/l10n'; import { type CosmosDBRecordIdentifier, @@ -43,7 +43,7 @@ export class QueryEditorContextProvider extends BaseContextProvider void, dispatchToast: DispatchToastFn, - trpcClient: TRPCClient, + trpcClient: TrpcClient, ) { super(dispatchToast, trpcClient); } diff --git a/src/webviews/index.tsx b/src/webviews/index.tsx index ebb2adadc..d37f07ac3 100644 --- a/src/webviews/index.tsx +++ b/src/webviews/index.tsx @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type WebviewState, WithWebviewContext } from '@cosmosdb/webview-rpc/react'; import { AriaLiveAnnouncer, useFocusFinders } from '@fluentui/react-components'; import * as l10n from '@vscode/l10n'; import { type l10nJsonFormat } from '@vscode/l10n'; @@ -13,7 +14,6 @@ import { createRoot } from 'react-dom/client'; import { type WebviewApi } from 'vscode-webview'; import './index.scss'; import { DynamicThemeProvider } from './theme/DynamicThemeProvider'; -import { type WebviewState, WithWebviewContext } from './WebviewContext'; import { WebviewRegistry } from './WebviewRegistry'; export type ViewKey = keyof typeof WebviewRegistry; diff --git a/src/webviews/utils/context/BaseContextProvider.tsx b/src/webviews/utils/context/BaseContextProvider.tsx index 913537a7b..a513e6ab8 100644 --- a/src/webviews/utils/context/BaseContextProvider.tsx +++ b/src/webviews/utils/context/BaseContextProvider.tsx @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type AnyRouter, type TrpcClient } from '@cosmosdb/webview-rpc/react'; import { Link, Toast, ToastBody, ToastTitle, ToastTrigger, type useToastController } from '@fluentui/react-components'; -import { type TRPCClient } from '@trpc/client'; -import { type AnyRouter } from '@trpc/server'; import * as l10n from '@vscode/l10n'; export type DispatchToastFn = ReturnType['dispatchToast']; @@ -37,7 +36,7 @@ interface CommonRoutes { export class BaseContextProvider { constructor( protected readonly dispatchToast: DispatchToastFn, - protected readonly trpcClient: TRPCClient, + protected readonly trpcClient: TrpcClient, ) { this.initEventListeners(); this.init(); diff --git a/tsconfig.base.json b/tsconfig.base.json index 59f3878ea..254df487e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -33,7 +33,11 @@ "@cosmosdb/nosql-language-service/*": [ "./packages/nosql-language-service/src/*.ts", "./packages/nosql-language-service/src/*/index.ts" - ] + ], + "@cosmosdb/webview-rpc": ["./packages/webview-rpc/src/index.ts"], + "@cosmosdb/webview-rpc/server": ["./packages/webview-rpc/src/server/index.ts"], + "@cosmosdb/webview-rpc/client": ["./packages/webview-rpc/src/client/index.ts"], + "@cosmosdb/webview-rpc/react": ["./packages/webview-rpc/src/react/index.ts"] } } } diff --git a/tsconfig.test.json b/tsconfig.test.json index 7b4680050..748a8dfdf 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -13,5 +13,13 @@ "packages/*/src/**/*.ts", "packages/*/src/**/*.tsx" ], - "exclude": ["node_modules", ".vscode-test", "out", "dist", "src/**/*.test.ts", "**/__mocks__"] + "exclude": [ + "node_modules", + ".vscode-test", + "out", + "dist", + "src/**/*.test.ts", + "packages/**/*.test.ts", + "**/__mocks__" + ] } diff --git a/vite.config.ext.mjs b/vite.config.ext.mjs index d89631f66..c272b5ffc 100644 --- a/vite.config.ext.mjs +++ b/vite.config.ext.mjs @@ -188,6 +188,9 @@ export default ({ mode }) => { '@cosmosdb/schema-analyzer/json': path.resolve(__dirname, 'packages/schema-analyzer/src/json/index.ts'), '@cosmosdb/schema-analyzer/bson': path.resolve(__dirname, 'packages/schema-analyzer/src/bson/index.ts'), '@cosmosdb/schema-analyzer': path.resolve(__dirname, 'packages/schema-analyzer/src/index.ts'), + '@cosmosdb/webview-rpc/server': path.resolve(__dirname, 'packages/webview-rpc/src/server/index.ts'), + '@cosmosdb/webview-rpc/client': path.resolve(__dirname, 'packages/webview-rpc/src/client/index.ts'), + '@cosmosdb/webview-rpc': path.resolve(__dirname, 'packages/webview-rpc/src/index.ts'), }, }, define: { diff --git a/vite.config.views.mjs b/vite.config.views.mjs index 46602b0f1..39a773190 100644 --- a/vite.config.views.mjs +++ b/vite.config.views.mjs @@ -159,6 +159,11 @@ export default ({ mode }) => { __dirname, 'packages/nosql-language-service/src/index.ts', ), + // NB: only client + shared (no /server — that's vscode/Node-only and the + // noExtensionImports plugin would refuse it anyway). + '@cosmosdb/webview-rpc/client': path.resolve(__dirname, 'packages/webview-rpc/src/client/index.ts'), + '@cosmosdb/webview-rpc/react': path.resolve(__dirname, 'packages/webview-rpc/src/react/index.ts'), + '@cosmosdb/webview-rpc': path.resolve(__dirname, 'packages/webview-rpc/src/index.ts'), }, }, // CSS/SCSS handled natively by Vite (no css-loader/sass-loader needed). From 199e9395b7535766788475099501b84894e45d8a Mon Sep 17 00:00:00 2001 From: Dmitrii Shilov <6812525+bk201-@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:02:12 +0200 Subject: [PATCH 3/3] chore(package): update dependencies to latest versions --- package-lock.json | 2097 +++++++++--------- package.json | 14 +- packages/nosql-language-service/package.json | 14 +- packages/schema-analyzer/package.json | 2 +- 4 files changed, 1076 insertions(+), 1051 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2b69f2d6..b563b91d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,25 +18,23 @@ "@azure/arm-resources": "~7.0.0", "@azure/cosmos": "~4.9.0", "@azure/identity": "~4.13.0", - "@fluentui/react-components": "~9.73.0", + "@fluentui/react-components": "~9.74.1", "@fluentui/react-icons": "~2.0.313", "@microsoft/vscode-azext-azureauth": "~5.1.1", - "@microsoft/vscode-azext-azureutils": "~4.2.0", + "@microsoft/vscode-azext-azureutils": "~4.3.0", "@microsoft/vscode-azext-utils": "~4.1.0", "@microsoft/vscode-azureresources-api": "~3.1.0", "@monaco-editor/react": "~4.7.0", "@prantlf/jsonlint": "~17.0.0", - "@trpc/client": "~11.17.0", - "@trpc/server": "~11.17.0", "@vscode/l10n": "~0.0.18", - "@vscode/prompt-tsx": "^0.4.0-alpha.7", + "@vscode/prompt-tsx": "^0.4.0-alpha.8", "allotment": "~1.20.4", - "es-toolkit": "~1.46.0", + "es-toolkit": "~1.47.0", "monaco-editor": "~0.52.2", "react-data-grid": "~7.0.0-beta.59", "react-hotkeys-hook": "5.1.0", "semver": "~7.8.0", - "vscode-languageclient": "~9.0.1", + "vscode-languageclient": "~10.0.0", "zod": "~4.4.3" }, "devDependencies": { @@ -50,9 +48,9 @@ "@types/vscode-webview": "~1.57.5", "@vitejs/plugin-react": "^6.0.1", "@vscode/l10n-dev": "~0.0.35", - "@vscode/test-electron": "~2.5.2", + "@vscode/test-electron": "~3.0.0", "@vscode/vsce": "~3.9.1", - "concurrently": "~9.2.1", + "concurrently": "~10.0.3", "cross-env": "~10.1.0", "diff": "~9.0.0", "eslint": "~10.4.0", @@ -60,16 +58,16 @@ "glob": "~13.0.6", "globals": "~17.6.0", "jest-mock-vscode": "~4.12.0", - "oxfmt": "~0.51.0", - "oxlint": "~1.66.0", + "oxfmt": "~0.54.0", + "oxlint": "~1.69.0", "oxlint-tsgolint": "~0.23.0", "react": "~19.2.1", "react-dom": "~19.2.1", "react-refresh": "~0.18.0", "rimraf": "~6.1.0", - "sass": "~1.99.0", + "sass": "~1.100.0", "typescript": "~6.0.2", - "typescript-eslint": "~8.59.0", + "typescript-eslint": "~8.61.0", "vite": "~8.0.10", "vite-bundle-analyzer": "~1.3.7", "vite-plugin-static-copy": "~4.1.0", @@ -747,9 +745,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.43.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.0.tgz", - "integrity": "sha512-V7ZCLQO3Jus9hzh2jVCCPW3mO4IBMr43O37PqSUYautJSnnJF41YlgLw21x0fLJTYvJ+Vkm6Gp+qKGH9pltgXA==", + "version": "6.43.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.1.tgz", + "integrity": "sha512-+BIjw/AG3tDQ4pJgTLPYdAW25eDE66YsvM4LKyVPgGzVgZ4a9Wj1SRX8kPVKgBDdPt8oHtZ15F0qx7p0oOHdHw==", "dev": true, "license": "MIT", "dependencies": { @@ -767,6 +765,10 @@ "resolved": "packages/schema-analyzer", "link": true }, + "node_modules/@cosmosdb/webview-rpc": { + "resolved": "packages/webview-rpc", + "link": true + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -880,45 +882,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@eslint/config-helpers": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", @@ -1022,21 +985,21 @@ } }, "node_modules/@fluentui/react-accordion": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.11.0.tgz", - "integrity": "sha512-mEy73hbJM53tMj3MWqm3ajbBxj48uubnJjumVKI8Z/eXHS8L3GzUy5rf/gUH26xSR2Tl+edpFhYB8PFbJDIKKw==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.12.0.tgz", + "integrity": "sha512-Ay1Cet3qTdpcHQErelG/6tSAhaNCkCojZzNzhpET25ukiMNFeJVK/j/kQbrcjbdClYdz35+8/3hI8q6hSIPD/Q==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1048,18 +1011,18 @@ } }, "node_modules/@fluentui/react-alert": { - "version": "9.0.0-beta.139", - "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.139.tgz", - "integrity": "sha512-R9r4dwwpWpgFmB8wVeWqipjUh/e6lyacnerX39HtVdgcG/PE+kpdHjKGiy8MAD+BGYCzrUxKNhXTQDlpXasJ1Q==", + "version": "9.0.0-beta.140", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.140.tgz", + "integrity": "sha512-IYrS7qNyN6FFya+FBdyHZU3jA+6xcU7SD1FjFbthZMx2QTYN7wnZGUdIRQQc3BQRRwRNWtH2BEF4RZY20TvfWQ==", "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.239", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1071,16 +1034,16 @@ } }, "node_modules/@fluentui/react-aria": { - "version": "9.17.11", - "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.17.11.tgz", - "integrity": "sha512-K9nz+Wn5JliCpG6bIYYPXvKmpOql+w9uyzmYNYkYQ6QHgoCpph7XUFx1HCtsJm2PPNi8WO8g0ZV9jojdGKl1Tg==", + "version": "9.17.12", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.17.12.tgz", + "integrity": "sha512-Nrgj9ND3nqtr33w0ICXs3/VrtSBZNBoFl9FkeWz3SCUeUcC8A9eFIH2HpHjbgwENs9BV+aUPi2J2vZhX1+yqQg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1091,21 +1054,21 @@ } }, "node_modules/@fluentui/react-avatar": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.11.1.tgz", - "integrity": "sha512-y1T67rVQQ/D4FAod8F4crXo9funaptscRIiW81LAsbN82fFVexMPQ9GmXooQQvn6ILvjJtf9IyvSJ195qDsyag==", + "version": "9.11.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.11.2.tgz", + "integrity": "sha512-OGGrpQBKbIfbX5ZDfZezCR2i1TErNopam0rUowuUl/etaiXv6Q8+1qdDPisJUR3OJJkSIXmiDhjdgJ+z/f7nFA==", "license": "MIT", "dependencies": { - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1117,16 +1080,16 @@ } }, "node_modules/@fluentui/react-badge": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.5.2.tgz", - "integrity": "sha512-+UPAK9dCD6Gx+LWr6vqKMIbYOPf7oXX+GXRtCJ5fekCTHD0VgIWuIMuEtxVrHpJQdb2VNaZadY8/dMomk2JaXw==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.5.3.tgz", + "integrity": "sha512-pMvzFTrMP/CvgDzne281pXyrBjSeiFwKRYuAa9Y1NkqK+H5wI0U/SsZu81mAuUA7vRxxqHkqtp5J2/huVK1yEQ==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1138,20 +1101,20 @@ } }, "node_modules/@fluentui/react-breadcrumb": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.4.1.tgz", - "integrity": "sha512-XgUB1yv04GdcL/6kUo6kh+BaN4df1A/Ds/fL1QxNrm5E26Vmvvlc0LN0WV/qb5qhKx0NwhtIXgOZHjfzyt7iCA==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.4.2.tgz", + "integrity": "sha512-IpLlrQkvFnQ7kMzRaVn6lmfb6gDUwRtnMDfhLTfUiJkisvuqdZGeilGTH1Yx4JLqBzCQGnRHMjcYm1DcrwX4aQ==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-link": "^9.8.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-link": "^9.8.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1163,19 +1126,19 @@ } }, "node_modules/@fluentui/react-button": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.9.1.tgz", - "integrity": "sha512-WNzpseiVbqEKKevTkAnyHNoK/8ktYPE6rvf31gGvSDnBBclqfrn4PSYG2ppi+Z7abmClnaNFxpp1OHuOoVQ8Bg==", + "version": "9.9.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.9.2.tgz", + "integrity": "sha512-zQ6EuJCb3hQ7d62lrn+wI3C9ugbi3M1d98SjOmj4WW/xG9gOKIZ+xjg6AYtAm7L94I/6JZbe5al2NvtejQWsHw==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", + "@fluentui/react-aria": "^9.17.12", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1187,18 +1150,18 @@ } }, "node_modules/@fluentui/react-card": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.6.1.tgz", - "integrity": "sha512-KBijjAxi0mBDSgnA1OCglqAVWc+Q0L7A2wCokszX/53oqfJPSvWxWFma7esz9b5MF/kdRrAR0vmy7MiosepNLQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.7.0.tgz", + "integrity": "sha512-OWfkDlCNbxbap5W5TIc+fpSEWnArug2+47yYx2DnSiUkJ+/bSdqBvGAPlQjlONV/fuA/HPWBpsni4Ao9nZicqg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-text": "^9.6.16", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-text": "^9.6.17", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1210,21 +1173,21 @@ } }, "node_modules/@fluentui/react-carousel": { - "version": "9.9.7", - "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.9.7.tgz", - "integrity": "sha512-lummYk+tASL/rM/SXWruoqhUAyJjTiOMgiCz55ncE3q2pSZe/EbsV5WfRw5B3y7pHX8xLusN831TBgUthj/sUw==", + "version": "9.9.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.9.8.tgz", + "integrity": "sha512-NaC7SVZF+dk1xV9FU9hsqQvoXrAzP6KMEcbzW7HLrQfM/qDyA2ERyYPZXeho24mvg4KXDalzEBwHxctASsA8iw==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "embla-carousel": "^8.5.1", @@ -1239,19 +1202,19 @@ } }, "node_modules/@fluentui/react-checkbox": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.6.1.tgz", - "integrity": "sha512-Rsf3TmcNrzLuHan9lyUFUmMZnNyvS7DV8C4Vc9lZnZTFRBo94GRMGzu0BcWKFbr3cCDT/r5RmIyQYz0kc7Jd2w==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.6.2.tgz", + "integrity": "sha512-ONIvYhhIdwAuPD4V5CZYXXjeq0lAtpiwU0PSFP5JAabYrmPVnBALe8km1QFTSnz2pN70AfQsOm92n6PCUFbyrg==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1263,18 +1226,18 @@ } }, "node_modules/@fluentui/react-color-picker": { - "version": "9.2.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.16.tgz", - "integrity": "sha512-+H8Ea8dwoSeUCTLRpUiGLrRsNvBnlHplnwJPU0isp8jdAfrIM/savZTLj6o4rqNFpNHQqAXxGwNuUV9YfHoJuQ==", + "version": "9.2.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.17.tgz", + "integrity": "sha512-cp9WdlrP2miMVNn5s1vjNqJCumezP/OWwGI0TV9tRMO0DvGQ8R1xwbVxxTH/C/wsMYrVIHiJaagQ5U6nzk6XLw==", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^3.3.4", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1286,23 +1249,23 @@ } }, "node_modules/@fluentui/react-combobox": { - "version": "9.17.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.17.1.tgz", - "integrity": "sha512-ezgt6tfOKd3wlG6IHvWl0TPNPpfHRtnEwC2kuqHYH/r1nMNp9edFi8Ya3+1eM7oxai19XW0swt69GPwRu51FVQ==", + "version": "9.17.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.17.2.tgz", + "integrity": "sha512-uYFelRhb+3BOwAIm4lvCfvrIBBi2Q5A66jzTXwZaH4rg5wrTWkpv+eSVkHF5gfcxzoEYRy1Ze2Tf1B2DtYYJyQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1314,71 +1277,71 @@ } }, "node_modules/@fluentui/react-components": { - "version": "9.73.8", - "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.73.8.tgz", - "integrity": "sha512-JG4KQjEvRRfPlh4yt6Rv1/k87ydM2y49r5XPNCnuYHahA7kEM+dY8JdOI7n7FW8bdcvZ7qt4smDrQ2XcPfmxlA==", - "license": "MIT", - "dependencies": { - "@fluentui/react-accordion": "^9.11.0", - "@fluentui/react-alert": "9.0.0-beta.139", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-breadcrumb": "^9.4.1", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-card": "^9.6.1", - "@fluentui/react-carousel": "^9.9.7", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-color-picker": "^9.2.16", - "@fluentui/react-combobox": "^9.17.1", - "@fluentui/react-dialog": "^9.18.0", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-drawer": "^9.12.0", - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-image": "^9.4.1", - "@fluentui/react-infobutton": "9.0.0-beta.115", - "@fluentui/react-infolabel": "^9.4.20", - "@fluentui/react-input": "^9.8.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-link": "^9.8.1", - "@fluentui/react-list": "^9.6.14", - "@fluentui/react-menu": "^9.24.1", - "@fluentui/react-message-bar": "^9.7.0", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-nav": "^9.3.24", - "@fluentui/react-overflow": "^9.7.2", - "@fluentui/react-persona": "^9.7.3", - "@fluentui/react-popover": "^9.14.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", - "@fluentui/react-progress": "^9.5.1", - "@fluentui/react-provider": "^9.22.16", - "@fluentui/react-radio": "^9.6.2", - "@fluentui/react-rating": "^9.4.1", - "@fluentui/react-search": "^9.4.2", - "@fluentui/react-select": "^9.5.1", + "version": "9.74.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.74.1.tgz", + "integrity": "sha512-N7BDd3g3A/ngxq8LKLD9ovd+3eHlOgo6R6QFPxA5pVYvznGSQlg00zQ2WxMz7jxQ8ADdPZYIsc7cfg80og3ckw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-accordion": "^9.12.0", + "@fluentui/react-alert": "9.0.0-beta.140", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-breadcrumb": "^9.4.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-card": "^9.7.0", + "@fluentui/react-carousel": "^9.9.8", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-color-picker": "^9.2.17", + "@fluentui/react-combobox": "^9.17.2", + "@fluentui/react-dialog": "^9.18.1", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-drawer": "^9.13.0", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-image": "^9.4.2", + "@fluentui/react-infobutton": "9.0.0-beta.116", + "@fluentui/react-infolabel": "^9.4.21", + "@fluentui/react-input": "^9.8.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-link": "^9.8.2", + "@fluentui/react-list": "^9.6.15", + "@fluentui/react-menu": "^9.25.0", + "@fluentui/react-message-bar": "^9.7.1", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-nav": "^9.4.0", + "@fluentui/react-overflow": "^9.8.0", + "@fluentui/react-persona": "^9.7.4", + "@fluentui/react-popover": "^9.14.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", + "@fluentui/react-progress": "^9.5.2", + "@fluentui/react-provider": "^9.22.17", + "@fluentui/react-radio": "^9.6.3", + "@fluentui/react-rating": "^9.4.2", + "@fluentui/react-search": "^9.4.3", + "@fluentui/react-select": "^9.5.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-skeleton": "^9.7.2", - "@fluentui/react-slider": "^9.6.2", - "@fluentui/react-spinbutton": "^9.6.2", - "@fluentui/react-spinner": "^9.8.2", - "@fluentui/react-swatch-picker": "^9.5.2", - "@fluentui/react-switch": "^9.7.2", - "@fluentui/react-table": "^9.19.15", - "@fluentui/react-tabs": "^9.12.1", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-tag-picker": "^9.8.6", - "@fluentui/react-tags": "^9.8.1", - "@fluentui/react-teaching-popover": "^9.6.21", - "@fluentui/react-text": "^9.6.16", - "@fluentui/react-textarea": "^9.7.2", + "@fluentui/react-skeleton": "^9.7.3", + "@fluentui/react-slider": "^9.6.3", + "@fluentui/react-spinbutton": "^9.6.3", + "@fluentui/react-spinner": "^9.8.3", + "@fluentui/react-swatch-picker": "^9.5.3", + "@fluentui/react-switch": "^9.7.3", + "@fluentui/react-table": "^9.19.16", + "@fluentui/react-tabs": "^9.12.2", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-tag-picker": "^9.8.8", + "@fluentui/react-tags": "^9.9.1", + "@fluentui/react-teaching-popover": "^9.7.0", + "@fluentui/react-text": "^9.6.17", + "@fluentui/react-textarea": "^9.7.3", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-toast": "^9.7.17", - "@fluentui/react-toolbar": "^9.8.0", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-tree": "^9.16.0", - "@fluentui/react-utilities": "^9.26.3", - "@fluentui/react-virtualizer": "9.0.0-alpha.112", + "@fluentui/react-toast": "^9.8.0", + "@fluentui/react-toolbar": "^9.8.1", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-tree": "^9.16.1", + "@fluentui/react-utilities": "^9.26.4", + "@fluentui/react-virtualizer": "9.0.0-alpha.113", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1390,12 +1353,12 @@ } }, "node_modules/@fluentui/react-context-selector": { - "version": "9.2.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.16.tgz", - "integrity": "sha512-D+/X2liT+eZe0rzXbwddPH333ml2SXz71biR13aeyGJQr8+W+icMAIsYhpwk0CC3KtJ3f1/CLTm7vcIrvqsJ4g==", + "version": "9.2.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.17.tgz", + "integrity": "sha512-pZGIz8vjK9nxHKmztV7y5T8yHseoTjm3a43TdPN6fhup0tlrGE/JUmVFEwulI3j4fMWqa0P2OhJoe+HrDMs44Q==", "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1407,23 +1370,23 @@ } }, "node_modules/@fluentui/react-dialog": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.18.0.tgz", - "integrity": "sha512-i+V2o0NJ1itjVADJFov5AR/JetpD2hCMiLye0vfi3/XsFMgEPZnGzILVxPCO/ovULTiCyThcL1UvY0d/PYrZfA==", + "version": "9.18.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.18.1.tgz", + "integrity": "sha512-tvi5MgUXY6yOySfKSEJobeBNwK3BOXVjRInxDz3ZM7g7FMMyzuf9HrXK/7caqMNRA9uQEQKFXKI9zD03L0kyPA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1435,15 +1398,15 @@ } }, "node_modules/@fluentui/react-divider": { - "version": "9.7.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.7.1.tgz", - "integrity": "sha512-ptymE6iADb/ugezulaMeoAfGxKSwOjHEHBh8N1ydOR3AoOxsSUPkvoPC0mReO/yV5Nas7pz5s5VuJTspmFz0hA==", + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.7.2.tgz", + "integrity": "sha512-rfzGQoGKtLBF5vxiJH2KhRiJGosozdql3d6eS7j11oRczgc5W/h38iLhiXuQzZHpkGaAOd3sY6sq4uGHJheOjA==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1455,20 +1418,20 @@ } }, "node_modules/@fluentui/react-drawer": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.12.0.tgz", - "integrity": "sha512-PUXeXUH6JqwpjqYphHesHl75UAFSvxQJQqrevMFHE78ZF0Cqn59Xpa+8hGwRSuoRcYa90jjfHzJOOjN0iNM2iA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.13.0.tgz", + "integrity": "sha512-Xeh9kW8SiNXobx+5AUb4UVYsaqpE9uqrqFwsb5Z47oupX3zRLw7UCh5rVbJoXowZRc7z6K1FViyORqpsOXnzJw==", "license": "MIT", "dependencies": { - "@fluentui/react-dialog": "^9.18.0", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-dialog": "^9.18.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1480,18 +1443,18 @@ } }, "node_modules/@fluentui/react-field": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.5.1.tgz", - "integrity": "sha512-u8J2d3AWb4yZXvy/mQd95y2lTon890RfybBTCbeBUzApGMI/77WqT5pRJ+zTM3lOMToPHVKylchNFusMpJaX9w==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.5.2.tgz", + "integrity": "sha512-5pZXGtDVXCkoL3/sRMyhCcPd6+TDR9/wYG7/mK82BDuX4viuoSr5llcQ1PkdcXMixFFU+nXa39l7/BLP3f6W8g==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1516,15 +1479,15 @@ } }, "node_modules/@fluentui/react-image": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.4.1.tgz", - "integrity": "sha512-yNd2Wq2xq952UUEVBkWeEmM7bTKdWx6BnsHPYRf0kdTADox2PquApYXsI1xw2pnAh3GSjARrGi9Eto0qxouLqA==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.4.2.tgz", + "integrity": "sha512-E7bOTFds8qoMiT/YDe2+ZL5h13u7M1bm8yoGFfeTw0fmE9Q0gtrx2WzJB/1ZV/4MTmjnaO9Dgx7ysTYxc3RWRw==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1536,18 +1499,18 @@ } }, "node_modules/@fluentui/react-infobutton": { - "version": "9.0.0-beta.115", - "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.115.tgz", - "integrity": "sha512-b+4B0ODzPEb4jNaW9HdT6VVt3CL5FgPL2yuKzALBsYVl3udJdFpyxHsZEPf3JrVTBL/rgF2fRI1iAioX6Fl7DA==", + "version": "9.0.0-beta.116", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.116.tgz", + "integrity": "sha512-bnL8hRs9K8xCKvJU49F0UxcRankGb2sr+KYezdrcrgfbePrh8kyJTFGmxKQSgka8P+SySE5DxFwb2RbfpTjmnw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.237", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-popover": "^9.14.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-popover": "^9.14.3", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1559,19 +1522,19 @@ } }, "node_modules/@fluentui/react-infolabel": { - "version": "9.4.20", - "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.20.tgz", - "integrity": "sha512-w4FOnNP+CtbVdKBEO6wXAcmOuPZWvmB/BJj+7J/8cLAQm7+4kQgitFHncU6rtFhPdGbikVoBf707/0R1mA4aIg==", + "version": "9.4.21", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.21.tgz", + "integrity": "sha512-FDpbxwdEztarJ63NmHCQP5n2XXKvyVgkdIVQIbkVslYqfooy2kql8Q0+5brRN2IsjQJRZ0MpSFRoJSNVT8rJEg==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1583,16 +1546,16 @@ } }, "node_modules/@fluentui/react-input": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.8.2.tgz", - "integrity": "sha512-t9zmqZR4bqeRjpWuCGfI4yrtPoCXFiK2XO4BoV5nNwAesglgz4+Vtso4YXst9QYEAazHtKI73YFJf1mn55hCuA==", + "version": "9.8.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.8.3.tgz", + "integrity": "sha512-nnApEcsPXVXCZZl9qRpS9hc2hy18btUtbG188TYM1FAynqjx5zZC9Ww5/6IOrGT8d12nDxxTu9dp/xqMZtUbbw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1604,12 +1567,12 @@ } }, "node_modules/@fluentui/react-jsx-runtime": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.4.2.tgz", - "integrity": "sha512-y3o0PBg2qzSdvgxDm7rH9BWq7E1h/eUWS+IhjQhd9dRpme6Py01+OLOglHojM5Tc9QjIp2Rjy2mFWBHXOR+8mw==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.4.3.tgz", + "integrity": "sha512-1QwEgITME+X24lnS68pQlU/b4BBdeS7oPdApwwoYQuAGKvImDY2nLAJt8BoHYKs9VFeX5ySEKPRM0rKXGq3EWQ==", "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1618,15 +1581,15 @@ } }, "node_modules/@fluentui/react-label": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.4.1.tgz", - "integrity": "sha512-4O3cPX6dSJVBKlIEbznjJ08utEc98lKbZz/6MZTTQfFgYl0TxAhxEDsIIIyNjj0Xy9eJpqubJsaswucWXTG/qg==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.4.2.tgz", + "integrity": "sha512-FfbOQf5caDA3yc/wukbKY0p6Pv8wkzre7E480VxqTgKrMm12KUoT+0+2S7vi0eCQJCW3pL8XjzVTbGIn8KDE8A==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1638,17 +1601,17 @@ } }, "node_modules/@fluentui/react-link": { - "version": "9.8.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.8.1.tgz", - "integrity": "sha512-ZxrCeX4pMWHujdmYV8b0QW0ztLtu0rHHvRNx67Y3WqSijVyij8QtNNiZ/nab+UDNlz9t8QIXKdWQgYj1uKDpMg==", + "version": "9.8.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.8.2.tgz", + "integrity": "sha512-PDziHdvp717LFc7BgxXDVldnq8UFtyqWM4ZWr0772XtuEc08jVU3MxKMUEsGOclqLRKGyjd0nG7IWKREuSETcg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1660,19 +1623,19 @@ } }, "node_modules/@fluentui/react-list": { - "version": "9.6.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.6.14.tgz", - "integrity": "sha512-B1mUQFvJOUlZysSduVnATNZggrGpgEWnW9ZSJAZ17LM0+9nWEQRi40jpUGI/d3PGKHt5O2df78s+1nEPAk0L6A==", + "version": "9.6.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.6.15.tgz", + "integrity": "sha512-mb2yVQC2gfILLFOZAxsYwo70YgoyacR52Qy2EGuB4wZOQtZ9KMZIOUFlQIztJBSxNIfo869/bF8EUWsVDaTeYg==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1684,24 +1647,24 @@ } }, "node_modules/@fluentui/react-menu": { - "version": "9.24.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.24.1.tgz", - "integrity": "sha512-NLB5EhzKFiwax3O5JTRTtsqdEFDGEXzEuP/suyxNAaaQsIuXygo//Rmdq6dSn7GybTpEOZHKxYDyyG7dj+a4YA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.25.0.tgz", + "integrity": "sha512-aoBlNLv8Ngr9wBiOEhvYVOSLfeen2vvdAdZM10OjJ+mo9uhdRxF4m0Uqd8mcp0bpGf5/Cnz9FIZjdgc5krdwyA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1713,20 +1676,20 @@ } }, "node_modules/@fluentui/react-message-bar": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.7.0.tgz", - "integrity": "sha512-ICFDxZ62r5OG97/FcfK1EfJPxGlyDNyFixLD/a3gOREvEcT/hyZgnlUM9Y30u92HjxChx2SwGWnv3iaQPsvToQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.7.1.tgz", + "integrity": "sha512-8ImzffgVF/DJacOCiP1x75GQHE0wdB+3QoRkGKsgOZcqn6JOXzCEYvM0JplietUsNczmXRtXx9ZE+Otl6HPOHQ==", "license": "MIT", "dependencies": { - "@fluentui/react-button": "^9.9.1", + "@fluentui/react-button": "^9.9.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-link": "^9.8.1", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-link": "^9.8.2", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1738,13 +1701,13 @@ } }, "node_modules/@fluentui/react-motion": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.15.0.tgz", - "integrity": "sha512-ZNQHYzE6MRbLQFT08/mrcqQ9k7F5niktRP93X1v/kmwKfPjvdDofySfbhQXQs3zQw600690C9rfJTKUd3h+zlg==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.16.0.tgz", + "integrity": "sha512-ZhbeRfir3V6+2kQjRqF2Bp8jwZd6TfmA9y1c6IlglsB8aNAbhnewYJsYXLrbZ+gwloiDdf46cVDqWYv5VFAgpg==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@swc/helpers": "^0.5.1" }, "peerDependencies": { @@ -1755,9 +1718,9 @@ } }, "node_modules/@fluentui/react-motion-components-preview": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.15.4.tgz", - "integrity": "sha512-gAHPlyEYylZzUSGwc68VaB+vO8CTX6tgIA3d2+jFrpcwvXZjsdCpF1w1zK1+hTuiipmEaZLZyBz0e0CKH2+3XQ==", + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.15.5.tgz", + "integrity": "sha512-AhDw4/6fjIDWPwx8L1vNDYu3GBJYkyAazNHNrowoRsuxZHn0vK5TMUacT4UW6/QbByCk1x76TLv+CxmwU75FPA==", "license": "MIT", "dependencies": { "@fluentui/react-motion": "*", @@ -1772,25 +1735,25 @@ } }, "node_modules/@fluentui/react-nav": { - "version": "9.3.24", - "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.3.24.tgz", - "integrity": "sha512-OlB5k5Zev5VNjSRfJvJLO09Hjcv2UHAjLpSVa6gKHx+1NqqSJWZeDLSF7r+/nyZ4CWP5jWZYq7whEu3WvzdVZw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.4.0.tgz", + "integrity": "sha512-gyrXwT1NFfRT4WoVXrz7656tuFOmhFgCw1OBmb+0igftXmSxz6XMIj8MlwfUv2/VUymAU4Hs0p3rZwE4l81KKA==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-drawer": "^9.12.0", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-drawer": "^9.13.0", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-tooltip": "^9.10.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tooltip": "^9.10.2", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1802,15 +1765,16 @@ } }, "node_modules/@fluentui/react-overflow": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.7.2.tgz", - "integrity": "sha512-5PA67LgnVmbbOzBN2H5gH3OvSVy1373VJfsHq2+6TLCfm+LXAkWBoFwvBuFI7HsMYae9A0FVlgX7gTsKVfMddw==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.8.0.tgz", + "integrity": "sha512-6lHvfcRNFSnOIrKHUzWc/WCKvSp5ivH8QP/stzyCUyzJpDde8uAbRMfg2iDFgJ8wlySP29BoPiepaH9bHgVLdQ==", "license": "MIT", "dependencies": { "@fluentui/priority-overflow": "^9.3.0", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1822,17 +1786,17 @@ } }, "node_modules/@fluentui/react-persona": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.7.3.tgz", - "integrity": "sha512-OY3xpSD6l4NDdeKihriC+H0q6P1CA2xyZ+pe/WwfKPnatxs2BALoRFtDQduMO7AK/j0w7UAxnaZrvEeftLen2g==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.7.4.tgz", + "integrity": "sha512-CtYA3aElMwTrhZcvdtrSIHWOzZqFcpJlfjchNNFTtvvFvrLGw65/1UPzLf/IUVBD1JO0XLGyQFRLUg/g+rtBfg==", "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-badge": "^9.5.2", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-badge": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1844,23 +1808,23 @@ } }, "node_modules/@fluentui/react-popover": { - "version": "9.14.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.14.2.tgz", - "integrity": "sha512-EDvzLkT98/vcCSGrcZWUACGsvLjrHin0Xf9eowMQKiiHFWbu8HNRmr7W2XB9Eja1W5HSIK6+mV8ro9zrLibG4w==", + "version": "9.14.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.14.3.tgz", + "integrity": "sha512-wR73yLdMm3/pJ92xJEeRnBAJ8tNvNv0LTSmaZvwbTgdcMT1zqfSyNO37qE7a8z+4bcp8kjyM8FR9NRqkr8OYdA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1872,14 +1836,14 @@ } }, "node_modules/@fluentui/react-portal": { - "version": "9.8.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.8.12.tgz", - "integrity": "sha512-+WH0wH/5lsodGP6Mam1alHXpkMCYA5uMcnF98RVOs7/GR69KiFcza1mCnvPJUaJ55AfwLuz/xLxuWdWgQnUdMQ==", + "version": "9.8.13", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.8.13.tgz", + "integrity": "sha512-a4EEt3KMzvW6qMk97K/8TQegmO8Ba4C2TdR7ke7g1SsEDmJGwwOD34hCwVxGi8LtxLcpAEdOx++brXnPsk5+Zw==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1891,16 +1855,16 @@ } }, "node_modules/@fluentui/react-positioning": { - "version": "9.22.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.22.1.tgz", - "integrity": "sha512-/r1BHQKr/WCjEM8UGloiq7bWWBSYB/Uqt7D1sAF9EHd968VH07cAN3RMVKmWWjeJO31rstOZHdgcz0WHhFF+2Q==", + "version": "9.22.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.22.2.tgz", + "integrity": "sha512-Pmio9+lDN+rF4k0mHVXqX6W0+A0ym0dje92UVfXeuassuIuJpKfvQg1xLpgQPrGRbgERr8KgA04xQVoJKaZQmA==", "license": "MIT", "dependencies": { "@floating-ui/devtools": "^0.2.3", "@floating-ui/dom": "^1.6.12", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "use-sync-external-store": "^1.2.0" @@ -1913,17 +1877,17 @@ } }, "node_modules/@fluentui/react-progress": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.5.1.tgz", - "integrity": "sha512-EXJ/Bp67d5+bXPNpPabxdtXUgCMTtvYrBoKtIS6wE5KeUzaek/rgQ3v5wnGfbuLnJ4J/kj+n7XQEc9fhoFPy9w==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.5.2.tgz", + "integrity": "sha512-H2t9Q9qYPm5gGb68RiIukFAZn/IxgoxcpKwZ+AjXKCly0C8x8EWCpyQSdfvswaGbcx7H6fe3SpKytBAAuvOOtA==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1935,17 +1899,17 @@ } }, "node_modules/@fluentui/react-provider": { - "version": "9.22.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.16.tgz", - "integrity": "sha512-S77n5ASUWE/V1I6lX09CrHm4TAKSGENhIrKz9qMKDv2Vrq44/j3eGBLz12k8IW4TJVu9nwGwst9kBpCT+3WHpA==", + "version": "9.22.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.17.tgz", + "integrity": "sha512-VIguLw2Ez9qxYCzrwKe3ttIcIbRdi7qpafImLNdpIAWRacIHw1AXSiDKcL6VFfE1+NxfQEy655wqYABi+7pJfw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/core": "^1.16.0", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" @@ -1958,18 +1922,18 @@ } }, "node_modules/@fluentui/react-radio": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.6.2.tgz", - "integrity": "sha512-Sp2us4eWRopUKOMCQw5/iks7euPKY6FeesBCCUIVGBg5VKZf2/CfEtbCa9hMjn4D4PCHGivnUTf23t238mvvnw==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.6.3.tgz", + "integrity": "sha512-U+funQQvlcOe3BQevUlkxsCoTQKFjw3Z/wnoAXNaNr1lTLIZnB+nesLA3ovZFWyOGTTJ2Mfa+vYpLbyyEpS8eA==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -1981,17 +1945,17 @@ } }, "node_modules/@fluentui/react-rating": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.4.1.tgz", - "integrity": "sha512-DfWipzrT44j+yaShtfHz96/vHEa5ut5IR1kobrO0bSqAcpetOn327gFeY+sG/W6xzork/STcy/T836yK8A2+DQ==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.4.2.tgz", + "integrity": "sha512-jVHv9GFKKhzH1fai4/1ArG1xjFAU/PFsY8UkBikt3LQDL5Cuw2S2uIBanso0AllNwmwaImsd5xb1Uo8mfMayBw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2003,17 +1967,17 @@ } }, "node_modules/@fluentui/react-search": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.4.2.tgz", - "integrity": "sha512-PIb50euHoMsKWLqFymf8wo/+z1jrx1MB7uNuhjNT5DvwTP4VYAy5EtRCSwVRyxWNSaWSL6iy6dDy517EQE96mA==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.4.3.tgz", + "integrity": "sha512-wKRakuodG76MTu2v/8PZiXA3SUFaMJhdJ5OjoVh5TpFtoYnzwJmiyW2TlgDuod2rk2fpJ3v34C6wkdx6tW8oZw==", "license": "MIT", "dependencies": { "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-input": "^9.8.2", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-input": "^9.8.3", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2025,17 +1989,17 @@ } }, "node_modules/@fluentui/react-select": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.5.1.tgz", - "integrity": "sha512-8GocQKiUHEUlAks6zA0HbGGSF2lpjuSZuxPzIBqTyuWof8vFiK6eFAcSXb0hTYIVH3RsTihhfc6G3NRnHoBrzg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.5.2.tgz", + "integrity": "sha512-kbLbF8DAXsbb2UwJxVzV5tS9fpSX2RZdFPZYosvQly6+h5kTojVFeZRrSkyMPYRCkTMVENdAeyahdx4ESa5qHw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2061,16 +2025,16 @@ } }, "node_modules/@fluentui/react-skeleton": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.7.2.tgz", - "integrity": "sha512-PrUgdSGDAZw9FIP5NyvPoPfHDe2N9VxMyBfyTwWfZVg03dzRfnE3vEqr7N5xyfv4JsRs6u1xSqVn/0jdS0IEMQ==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.7.3.tgz", + "integrity": "sha512-4YhAux0OaYs/91xz/K25pNQxFbdQ2FcDRnwTpgsCDFH4XGQtA+rxBsLA5il3chIf++bNWr/78c5PHp6tZQuCDw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2082,17 +2046,17 @@ } }, "node_modules/@fluentui/react-slider": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.6.2.tgz", - "integrity": "sha512-lVavtTg8eqovfRokeYDk4popwCi8nuicacJ/HZdF3ni5e3y/2WT/bVP0eErS/GvC7+90ACQQ8uxdr4sjjY/HWA==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.6.3.tgz", + "integrity": "sha512-r0AP/ZqyMpVEEniIMjQ6AH5DZeCZ/XypBw+21D6mtjiy9vCg0A9lU8U+ay2Y1RyQY4PCShsUVSOb3bNTSTVUxQ==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2104,18 +2068,18 @@ } }, "node_modules/@fluentui/react-spinbutton": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.6.2.tgz", - "integrity": "sha512-P4vvJH7P5yHPFAv6aSo3dZxtErN62DiRJN+nEKS+/XBoRGsOGQdqyyx5Q/PQKOmyQrtwuZdXNHUjcyv8b50T2w==", + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.6.3.tgz", + "integrity": "sha512-wc3GjEB3vBz8uO+Jmdch9gk5effGz6ld2SrfmpHjfTGgww9qIj5S+WbSPZjAKgtqZw/f597DMpiplRE1kvqn/A==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2127,16 +2091,16 @@ } }, "node_modules/@fluentui/react-spinner": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.8.2.tgz", - "integrity": "sha512-0LxykLJGUD/I3XEeIXAWznwdg9XRe0piaByR0nLFOOV3UPwkVc2w5UdPhy2Y0NZDvtPHbNaMCuQAq82+bxg/0w==", + "version": "9.8.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.8.3.tgz", + "integrity": "sha512-knnL3Yx/qC+YoYPLCQLE5iHeNMwj3bLBQrksk85lQK0AFy1rOs8rTQuxUtjg9icn5BOFExhSDOYVwp3diSt1ug==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2148,19 +2112,19 @@ } }, "node_modules/@fluentui/react-swatch-picker": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.5.2.tgz", - "integrity": "sha512-DK6UU9OJY9XaGBPU2ROx+B5/7XdwVtHBdVthOAptyKSsYGOdQt5AQqg3ZOXH6r5WYbMRQDuP2OZ2iKtwidFCVQ==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.5.3.tgz", + "integrity": "sha512-AiybFcvA6in1piIsPn83Wm+w5bOnLlWmqrHiTDFnt6bYb8j2MJZ+dratJVZRtidqlEyfcMS3SByLooaVzwLRLQ==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2172,19 +2136,19 @@ } }, "node_modules/@fluentui/react-switch": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.7.2.tgz", - "integrity": "sha512-j3e5se+3d+befV9MytkxxvJ9nHZOeZ7thKDTF4YVSYf6kcNx9eOlLvPgDjhGO08gzngO4B7aaprhDN7DJc3W1g==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.7.3.tgz", + "integrity": "sha512-/eCYAtaoyUF//6F/OdOGj+GhLtkeJMXJUxaRPiDa6d18DX2eyoGaQ10175ysOjv4CbzIg8xH15flgpB4qUUstQ==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-label": "^9.4.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-label": "^9.4.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2196,23 +2160,23 @@ } }, "node_modules/@fluentui/react-table": { - "version": "9.19.15", - "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.19.15.tgz", - "integrity": "sha512-OdQ2Nwx2nAlPMlJeyAFrKa3Zy5Ya/H87OU8MvtFJhabM/FkHiZoli/DO1mavVI+jqavOlJuQWmJ55D6jjuGa7g==", + "version": "9.19.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.19.16.tgz", + "integrity": "sha512-SdwpJIHwCGg+ALOhZRvixkQhWSakXDgpDGe/OWwv1PiLDPxnBh+gUd+MtveryFaX+WvJvLWzx3u9O1ogQXKx3g==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2224,17 +2188,17 @@ } }, "node_modules/@fluentui/react-tabs": { - "version": "9.12.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.12.1.tgz", - "integrity": "sha512-WvzOtpC6C/7Mo5X+xmE+3stpCbx2iH9BqrEN5KuGrsHJ78DjMDeabYeL90vlrHBdP4VlTpwdORBui/jtWkxnmQ==", + "version": "9.12.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.12.2.tgz", + "integrity": "sha512-k2WsKmNQvFtNSywAb/VxXXlFdLC9fjRaRV4Ha7qDXucXuTCI1eKJuaAteePZiMAByv+AbRqRHevv5k2KMabxrw==", "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2246,18 +2210,18 @@ } }, "node_modules/@fluentui/react-tabster": { - "version": "9.26.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.14.tgz", - "integrity": "sha512-WibgoF67hl6BXfmsY6RSIWSHadeMP/6EDG9gAacfHlwKvK0+FiHp5ernwuXTPAmu2kiHicn2qUZ8EteCFiFryg==", + "version": "9.26.15", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.15.tgz", + "integrity": "sha512-SugQlqXsMueTojtvPU/RIoZg6WaV4bw++NhLjnF7dFvD61/w5pPsVSLCPsLJBD+oU5Kbgx2x3KFbI69kb+kNmQ==", "license": "MIT", "dependencies": { "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", - "keyborg": "^2.6.0", - "tabster": "^8.5.5" + "keyborg": "^2.14.1", + "tabster": "^8.8.0" }, "peerDependencies": { "@types/react": ">=16.14.0 <20.0.0", @@ -2267,25 +2231,25 @@ } }, "node_modules/@fluentui/react-tag-picker": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.8.6.tgz", - "integrity": "sha512-sOZ+wBA3hgGhKrOP7wbjB2yRvAxjcRXtcj1jDTrtSkaDPXb3K0nGmjiqp2mve995ps3wvCGnNKK4EurX842ZbA==", + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.8.8.tgz", + "integrity": "sha512-GkBqUMAxJtOGRNFmkoi6Js4jxvQEc3JScUok1/UKThPHZeMfk4vAKT8aGVx9Sa/Ab4Akr5LhcjOt4TXHPQ2IvQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-combobox": "^9.17.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-field": "^9.5.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-combobox": "^9.17.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-field": "^9.5.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", - "@fluentui/react-tags": "^9.8.1", + "@fluentui/react-tabster": "^9.26.15", + "@fluentui/react-tags": "^9.9.1", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2297,20 +2261,20 @@ } }, "node_modules/@fluentui/react-tags": { - "version": "9.8.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.8.1.tgz", - "integrity": "sha512-6ZTW78fu5eWByKHIM3i+raDrX3hwfZ67ONfZ8wEUXfZHowskxqpMHI8Gw7IAMWkC1scgLqEnht8TnHvZgjo7Ug==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.9.1.tgz", + "integrity": "sha512-WY6Ye5TblwHnMIlRd0DgnPTCH+UyJBafr8bIOszi13KOkN3HFswY5syb4lbQUzP+EslAC5M5cPnJXe89TUXV+Q==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2322,21 +2286,21 @@ } }, "node_modules/@fluentui/react-teaching-popover": { - "version": "9.6.21", - "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.6.21.tgz", - "integrity": "sha512-V86zLB1B8xu3U/02FvvMdsJP+ZC9l3vT9bQ2Gr7hZHxJ4/0NLpVcrYSBFHpON9e/WK3p+A5b5V96p86b5Pavlg==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.7.0.tgz", + "integrity": "sha512-8oKts1w33JbLAgVNt7Ad5vidXsIpXyVkrPwo5aZW6oqEASJGEooAOx1od+bKgwZb2wyjq5/RXxdV22r13nqajg==", "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-popover": "^9.14.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-popover": "^9.14.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1", "use-sync-external-store": "^1.2.0" @@ -2349,15 +2313,15 @@ } }, "node_modules/@fluentui/react-text": { - "version": "9.6.16", - "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.16.tgz", - "integrity": "sha512-ZzCSJWQ6LrVuPqA6sqNEZaXbLvhi2NxBOtlMudWlqYzidLQp038d7mMGSzNnhyeblg+gj+bOVE2eOgWFuVHGYw==", + "version": "9.6.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.17.tgz", + "integrity": "sha512-SqWXOKJNF6EgG4/vZeurl7MqO9OckRwK6tvk9JJVs7kbqOky+d+t1gITaqk9yIOw6LJtb76vm8cZUvKUb0WSqA==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2369,16 +2333,16 @@ } }, "node_modules/@fluentui/react-textarea": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.7.2.tgz", - "integrity": "sha512-awlkZoW81WaOqSoXTT9rZs3mTAzCCHnC9eAm6J8ZxI5+ASX07BTolBfZ82it5wxOHI5GMDfbFOl+xIy8uAMdzA==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.7.3.tgz", + "integrity": "sha512-BNStqBKO2fe3h5VAIPs33/7xj8EAr5msmb9krq02XAmvDndt3aLrQdz25vVEMvbcuUCNQoFsPtN/PrR6nXTIHw==", "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.5.1", - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-field": "^9.5.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2400,22 +2364,22 @@ } }, "node_modules/@fluentui/react-toast": { - "version": "9.7.17", - "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.7.17.tgz", - "integrity": "sha512-DWA5EARWSo1k19iWAulLpKrcUHT+Dq/Bw9zfdpoQEWWybrAZwyN7WiYFkBjKCQRxSp10OjLASSQK91CXfb1wJA==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.8.0.tgz", + "integrity": "sha512-GsLeEjLCLZ+SM2yL4G/hsypecXPn4FK73sH3KXer7Q0MST+ldulcaW8nsppCwqBB6Zf5pwcRU4qnkWwFMQd66Q==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", + "@fluentui/react-aria": "^9.17.12", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-portal": "^9.8.12", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-portal": "^9.8.13", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2427,20 +2391,20 @@ } }, "node_modules/@fluentui/react-toolbar": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.8.0.tgz", - "integrity": "sha512-EIe+QWOaFR1pZzENefsFTmjxGa2yJb4A/by3kGuGqSjx7isqPUllPq0/kFQzfoUYgPDJbJtQ+KyuRDekTL0QpQ==", + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.8.1.tgz", + "integrity": "sha512-ZzjFwFElF3bCsHXgl6YfmHzfZn2gUDe7NoYl4qloHhGacrSStvOt0h94WRz0a5ur/VIG2PDROeBLkcI2MIZQJQ==", "license": "MIT", "dependencies": { - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-context-selector": "^9.2.16", - "@fluentui/react-divider": "^9.7.1", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-context-selector": "^9.2.17", + "@fluentui/react-divider": "^9.7.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2452,19 +2416,19 @@ } }, "node_modules/@fluentui/react-tooltip": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.10.1.tgz", - "integrity": "sha512-IPHBFjqGhaaMDhLt5NSNOE9LEpDOpT7qgEqNz+Mlflo0A4qI2LW/EnkNop7IRmX/bC88A+wUtEONTjjR87dNBw==", + "version": "9.10.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.10.2.tgz", + "integrity": "sha512-1qewqiTNKpbRuoINhytyaMoUsBLE4TRPXf9ilJnvN3UtN5TYtS/8Oe6zMocHEnCLETsFOyCn8sAlufWOo5efpQ==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-portal": "^9.8.12", - "@fluentui/react-positioning": "^9.22.1", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-portal": "^9.8.13", + "@fluentui/react-positioning": "^9.22.2", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2476,26 +2440,26 @@ } }, "node_modules/@fluentui/react-tree": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.16.0.tgz", - "integrity": "sha512-c+Q4AVaYk9U69aGDgmJVNne+CtWKS75YIfGoxs6+9+wE2Wqz4T0E+gE1ng7ARCQQgI7E2NEJlot6DuI6nYYrRw==", + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.16.1.tgz", + "integrity": "sha512-e87Fa+8ttbYh0XY4qxJ9NcmIWSfYouw8Rc68c10UczK2TcsWSII84cV9fHrbL7FtX8DlyncZuSjukoJYm5LD7w==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", - "@fluentui/react-aria": "^9.17.11", - "@fluentui/react-avatar": "^9.11.1", - "@fluentui/react-button": "^9.9.1", - "@fluentui/react-checkbox": "^9.6.1", - "@fluentui/react-context-selector": "^9.2.16", + "@fluentui/react-aria": "^9.17.12", + "@fluentui/react-avatar": "^9.11.2", + "@fluentui/react-button": "^9.9.2", + "@fluentui/react-checkbox": "^9.6.2", + "@fluentui/react-context-selector": "^9.2.17", "@fluentui/react-icons": "^2.0.245", - "@fluentui/react-jsx-runtime": "^9.4.2", - "@fluentui/react-motion": "^9.15.0", - "@fluentui/react-motion-components-preview": "^0.15.4", - "@fluentui/react-radio": "^9.6.2", + "@fluentui/react-jsx-runtime": "^9.4.3", + "@fluentui/react-motion": "^9.16.0", + "@fluentui/react-motion-components-preview": "^0.15.5", + "@fluentui/react-radio": "^9.6.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-tabster": "^9.26.15", "@fluentui/react-theme": "^9.2.1", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2507,9 +2471,9 @@ } }, "node_modules/@fluentui/react-utilities": { - "version": "9.26.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.26.3.tgz", - "integrity": "sha512-bXB3jMm/RroT8c5eGZkijkPbLd4MqMI6biBHjavo0e7OkZHv9IPfH2nDkGhSn5Sh8e6kRcX0IjYhbM10WUK2iQ==", + "version": "9.26.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.26.4.tgz", + "integrity": "sha512-Rg1kg0ZPFOBi6VtQNkgV+K3z3O7PY5QFJQ4Y+qkZv7a8fUSNkEK151coaGOLps4P77fY2DiHhqKqeOehN7vFOA==", "license": "MIT", "dependencies": { "@fluentui/keyboard-keys": "^9.0.8", @@ -2522,14 +2486,14 @@ } }, "node_modules/@fluentui/react-virtualizer": { - "version": "9.0.0-alpha.112", - "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.112.tgz", - "integrity": "sha512-dao/mQssaPFxCXMx7K+G/DrRoZg28kXcE1NGbJ1RPtbkVCzJgwrEEeDhM5/wyOXO/Z5EZ31FIerDDVOyr6FAaw==", + "version": "9.0.0-alpha.113", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.113.tgz", + "integrity": "sha512-MGmdlm+0HwwMypCpUCpddQjgKvZkL9oGvjXNcoIHYhMVy4WSc5ha8XqOxAo2cfWvKGN0jMiW3H3IebLdcFpd7Q==", "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "^9.4.2", + "@fluentui/react-jsx-runtime": "^9.4.3", "@fluentui/react-shared-contexts": "^9.26.2", - "@fluentui/react-utilities": "^9.26.3", + "@fluentui/react-utilities": "^9.26.4", "@griffel/react": "^1.5.32", "@swc/helpers": "^0.5.1" }, @@ -2816,9 +2780,9 @@ } }, "node_modules/@microsoft/vscode-azext-azureutils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-4.2.0.tgz", - "integrity": "sha512-j/YzGI0uRzQjCM+jr9YyLxnJRHl2H9WQCw9Dlw7DhztV4ED3NCoIuG6k6jjKmSS3c5cTF/lqmPaVZ4SxZUssvA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-4.3.0.tgz", + "integrity": "sha512-K7F8Chd9ebzwrVjCJz7wB9jPf48fRBAleeXk0FwB/TtdqFbDugQtt9aO4cmblviU0yAx9TjNj9mOyzCuIIGdjQ==", "license": "MIT", "dependencies": { "@azure/arm-authorization": "^9.0.0", @@ -2826,14 +2790,14 @@ "@azure/arm-msi": "^2.2.0", "@azure/arm-resources": "^5.0.0", "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.1.0", - "@azure/arm-resources-subscriptions": "^2.1.0", + "@azure/arm-resources-subscriptions": "^3.0.0-beta.1", "@azure/arm-storage": "^18.6.0", "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.1.0", "@azure/core-client": "^1.10.1", "@azure/core-rest-pipeline": "^1.23.0", "@azure/logger": "^1.3.0", - "@microsoft/vscode-azext-azureauth": "^6.0.0-alpha.6", - "@microsoft/vscode-azext-utils": "^4.0.4", + "@microsoft/vscode-azext-azureauth": "^6.1.0-alpha.2", + "@microsoft/vscode-azext-utils": "^4.1.1", "@microsoft/vscode-azureresources-api": "^3.1.0", "semver": "^7.7.4" }, @@ -2874,15 +2838,33 @@ "node": ">=14.0.0" } }, + "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources-subscriptions": { + "version": "3.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-3.0.0-beta.1.tgz", + "integrity": "sha512-1u+gSR8Owp4+hIkWuZg8eFAl1iFjkfaaKu0FBoFSwosxNthJvmXoAIJ3xVhwFomp9lBqs37Rbou/UM0DVPmgSQ==", + "license": "MIT", + "dependencies": { + "@azure-rest/core-client": "^2.3.1", + "@azure/core-auth": "^1.9.0", + "@azure/core-rest-pipeline": "^1.20.0", + "@azure/core-util": "^1.12.0", + "@azure/logger": "^1.2.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@microsoft/vscode-azext-azureutils/node_modules/@microsoft/vscode-azext-azureauth": { - "version": "6.0.0-alpha.8", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureauth/-/vscode-azext-azureauth-6.0.0-alpha.8.tgz", - "integrity": "sha512-oOZpeTe4tOupKzQpeKxyHOSG10Bxsyp8YhCeyadQMsz1wICR/JZEdSMKPR0GnXpXYlYSsEDFbSzJWqZUZ/3+Yw==", + "version": "6.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureauth/-/vscode-azext-azureauth-6.1.0-alpha.2.tgz", + "integrity": "sha512-hiEpLpNe/TiV1Cvx5gcgTxybfI1sYIRjKJ361bZyDOz3CchLjbupKiEi1jqyonMq5MvWftVlENBnvk3vq8AT0w==", "license": "MIT", "dependencies": { - "@azure/arm-resources-subscriptions": "^2.1.0", - "@azure/core-rest-pipeline": "^1.22.2", - "@azure/identity": "^4.13.0", + "@azure/arm-resources-subscriptions": "^3.0.0-beta.1", + "@azure/core-auth": "^1.10.1", + "@azure/core-rest-pipeline": "^1.23.0", + "@azure/identity": "^4.13.1", "@azure/ms-rest-azure-env": "^2.0.0" }, "engines": { @@ -2890,12 +2872,12 @@ } }, "node_modules/@microsoft/vscode-azext-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-4.1.0.tgz", - "integrity": "sha512-00/wz3n2W6xNFZK4ur2lGjTqX8RhSrbAIoNwhMreOKk2n6gOpY389XO20oHu77uBxjgoqMTAL5R+SWcMeqD0Gg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-4.1.1.tgz", + "integrity": "sha512-pFvvzqJqAJrI5UTeJNijGrHWB738VTPck6Vsnb77L0agHMGKPqRy28Ela/6fGJRXBc7Yuv14gn39Sogn0qMvkQ==", "license": "MIT", "dependencies": { - "@microsoft/vscode-azureresources-api": "^3.1.0", + "@microsoft/vscode-azureresources-api": "^3.1.1", "@microsoft/vscode-processutils": "^0.2.1", "@vscode/extension-telemetry": "^1.5.2", "dayjs": "^1.11.19", @@ -2917,9 +2899,9 @@ } }, "node_modules/@microsoft/vscode-azureresources-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-3.1.0.tgz", - "integrity": "sha512-jcx5VdDiOftjkjQ+ZXuGQ7xpy7WSKnB7oRLdmGuW3ykaB/PrBSHwStkItSg8l8ycJ0t1kaPOz3eDJP0Ol309jg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azureresources-api/-/vscode-azureresources-api-3.1.1.tgz", + "integrity": "sha512-koV1+XvWSzA+pOc1g17Kbw9Gm26SIvg+j5puT5vB/T9vNiE2oeAlxlAatfZOT3tRHN1qGqPLl90HHs5mQAPkew==", "license": "MIT", "engines": { "vscode": "^1.105.0" @@ -3064,9 +3046,9 @@ } }, "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.51.0.tgz", - "integrity": "sha512-Ni0sCqg5CIHaLIYFGj+ncbcumylvNC6FE4rfD0KfdmnWHbPJ+zev0qZCXKxy2hFVa0fYRK0yPzf5nzPbkZou7g==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.54.0.tgz", + "integrity": "sha512-NAtpl/SiaeU103e7/OmZw0MvUnsUUopW7hEm/ecegJg7YM0skQaA0IXEZoyTV6NUdiNPupdIUreRqUZTShbn/g==", "cpu": [ "arm" ], @@ -3081,9 +3063,9 @@ } }, "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.51.0.tgz", - "integrity": "sha512-eu5lAZjuo0KAkp+M24EhDqfOwA8owQ8d7wyBlOUUGRbDLHpU3IRlDHp8Dif+YqGlxs6jra7yS6WQu/NkPhAxeg==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.54.0.tgz", + "integrity": "sha512-B4VZfBUlKK1rmMChsssNZbkZjE8+FzG3avMjGgMDwbGxXRoXkoeXiAZ+78Oa+eyDPHvDCiUb4zH/vmCOUSafLQ==", "cpu": [ "arm64" ], @@ -3098,9 +3080,9 @@ } }, "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.51.0.tgz", - "integrity": "sha512-6LsUNIdURhhcIfIn8+xsOb61mSTa9msAHTeSGx9Jf4rsP/gN8PGCF+SKWPAQZbND2w/WBkqQ6303jqEEIXzMdQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.54.0.tgz", + "integrity": "sha512-i02vF75b+ePsQP3tHqSxVYI5S6b8X/xqdPu7/mDHXtpgXLTYXi3jJmfHU0j+dnZZDKaYTx/ioCK7QYJmtiJR2g==", "cpu": [ "arm64" ], @@ -3115,9 +3097,9 @@ } }, "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.51.0.tgz", - "integrity": "sha512-9aUMGmVxdHjYMsEAW1tNRoieTJXlVNDFkRvIR1J7LttJXWjVYCu2ekclLij2KJtxBxSQOYSHd12ME/adVGVbZg==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.54.0.tgz", + "integrity": "sha512-8VMFvGvooXj7mswkbrhdVZ2/sgiDaBzWpkkbtO+qGDLV4EfJd67nQadHkQC0ZNbaWA9ajXfqI6i7PZLIeDzxEQ==", "cpu": [ "x64" ], @@ -3132,9 +3114,9 @@ } }, "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.51.0.tgz", - "integrity": "sha512-mkY1nhZTqYb+NHaAWxOCKISN6FwdrwMNsu17vTUA3wzUV2VJ+Paq15ZokRcsMU/2PUdHO73prxyeJpjXQ3MPpQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.54.0.tgz", + "integrity": "sha512-0cRHnp43WN1Jrc5s0BdbdKgR1XirdvHy7TAFi3JEsoEVQVJxTXMbpVd76sxXlgRswNMDhVFSJw+y7Eb8mEavFQ==", "cpu": [ "x64" ], @@ -3149,9 +3131,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.51.0.tgz", - "integrity": "sha512-wtFwNwE4+YCNuPaWoGDZeGsKvD6D1YSUNBJNn/rJBh7CrDBThFE+TBI5kY7vRW9rIOQRsbW2IpyyL3Du4Zqwiw==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.54.0.tgz", + "integrity": "sha512-JyQAk3hK/OEtup7Rw6kZwfdzbKqTVD5jXXb8Xpfay29suwZyfBDMVW/bj4RqEPySYWc6zCp198pOluf8n5uYzg==", "cpu": [ "arm" ], @@ -3166,9 +3148,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.51.0.tgz", - "integrity": "sha512-rnOaNx86G7iRKM6lsCIQMux0SMGNC/TEbFR+r7lpruJ12bnrIWgxd5w1PLqOvgR9r8ZJbpK/zfRKctJnh8/Jfg==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.54.0.tgz", + "integrity": "sha512-qnvLatTpM8vtvjOfcckBOzJjk+n6ce/wwpP8OFeUrD5aNLYcKyWAitwj+Rk3PK9jGanbZvKsJnv14JGQ6XqFdw==", "cpu": [ "arm" ], @@ -3183,9 +3165,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.51.0.tgz", - "integrity": "sha512-jOgDzSqWcICGRjsp4mc08FxKMN8vzP2Kgs4E0d2HUP99F+nJDQKklRV4Zuj+0gcBgjrzx2CbpqaIdUVPepCojA==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.54.0.tgz", + "integrity": "sha512-SMkhnCzIYZYDk9vw3W/80eeYKmrMpGF0Giuxt4HruFlCH7jEtnPeb3SdQKMfgYi/dgtaf+hZAb5XWPYnxqCQ3w==", "cpu": [ "arm64" ], @@ -3203,9 +3185,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.51.0.tgz", - "integrity": "sha512-KBUCdrH5bwVrAvI9gU/1S55oH6fzXjr++J/oVocdu7bYTks1l7DNNT+rLd/1TDdAEjObGwmfWamn7LC1m8A0DQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.54.0.tgz", + "integrity": "sha512-QrwJlBFFKnxOd95TAaszpMbZBLzMoYMpGaQTZF8oibacnF5rv8l12IhILhQRPmksWiBqg0YSe2Mnl7ayeJAHSA==", "cpu": [ "arm64" ], @@ -3223,9 +3205,9 @@ } }, "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.51.0.tgz", - "integrity": "sha512-NapfjYsABFqTJ1Dn9Efq6sN5esaHconVKwVLbDGNQLrwpOx/g17mkwErHzU72PutL67nf3wNAkbq122H+zLxag==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.54.0.tgz", + "integrity": "sha512-WILatiol/TUHTlhod7R09+7Az/XlhKwmY1MHfLZNmewltPWNN/EwxP2rQSHahibZ/cB8gmckEBjBOByD+5bYsQ==", "cpu": [ "ppc64" ], @@ -3243,9 +3225,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.51.0.tgz", - "integrity": "sha512-5dlDt1dUZCVi6elIhiK1PWg9wpTzTcIuj0IZnSurvIoMrhOWqqTcc1dSTxcSkNaBZhfsNqRZdINI1zAgbKkJNQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.54.0.tgz", + "integrity": "sha512-f05YMG4BH4G8S4ME6UM6fi1MnJ9094mrnvO5Pa4SJlMfWlUM+1/ZWMEF4NnjM7shZAvbHsHRuVYpUo0PHC4P9Q==", "cpu": [ "riscv64" ], @@ -3263,9 +3245,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.51.0.tgz", - "integrity": "sha512-pgdWUJn0S5nulyiVdlFV8DzCUnGXkU99W5PSkkmbaZW+LrZBPxpezun4G0DDHbQaVYuJeCuKsXsGKGo77CkUTQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.54.0.tgz", + "integrity": "sha512-UfL+2hj1ClNqcCRT9s8vBU4axDpjxgVxX96G+9DYAYjoc5b0u15CJtn2jgsi9iM+EbGNc5CW1HVRgwVu76UsSA==", "cpu": [ "riscv64" ], @@ -3283,9 +3265,9 @@ } }, "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.51.0.tgz", - "integrity": "sha512-2XTFUe97CbDGAI8vjwDfZ1HdakO0XIADyJ24idEg64SC4/K4in/OisXVnrW4NMK7I6TgC7EqRhC0Ln/nKhAemA==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.54.0.tgz", + "integrity": "sha512-3/XZe931Hka+J6NjnaqJzYpsWWxDTuRdUdwSQHnOuJEgbC+SehIMFJS8hsEjV7LBhVSL2OCnRLvbVW8O97XIyw==", "cpu": [ "s390x" ], @@ -3303,9 +3285,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.51.0.tgz", - "integrity": "sha512-kQ1OuCqqt/yyf0ZN9VFxW1/JnlgJgii3Dr7pWf9vNBvrX1hv6g39/+mc5oGRHRGJFZtl3zsGDWR9c5N2B/gwBw==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.54.0.tgz", + "integrity": "sha512-Ik93RlObtu43GbxApafayFjwYE06L6Xr08cSwpBPYbDrLp2ReZx0Jm1DqwRyYRnukUJy+rK2WaEvUQOxdytU9Q==", "cpu": [ "x64" ], @@ -3323,9 +3305,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.51.0.tgz", - "integrity": "sha512-ARTYqxHF475o96Gbn41hvSWSSRygPlRDXZZgZ9I2scU1y0qiWpCQyZCoefaQa0mwv+wwtZ+luS4YOzsRzM/izg==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.54.0.tgz", + "integrity": "sha512-yZcakmPlD86CNymknd7KfW+FH+qfbqJH+i0h69CYfV1+KMoVeM9UED+8+TDVoU4haxI0NxY7RPCvRLy3Sqd2Qg==", "cpu": [ "x64" ], @@ -3343,9 +3325,9 @@ } }, "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.51.0.tgz", - "integrity": "sha512-QiC1XrCl6a6BmqMzduO8hdIRMf1m44hCkt2Q68KWkTvUB/E7fd2iomyNh6KnnRca5w6eBrRAAtLFqTh+xjsjJA==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.54.0.tgz", + "integrity": "sha512-GiVBZNnEZnKu00f1jTg49nomv187d0GQX+O+ocykoLeiaALuEO+swoTehHn9TehTfi7V8H0i0e/yvUjCqnwk1w==", "cpu": [ "arm64" ], @@ -3360,9 +3342,9 @@ } }, "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.51.0.tgz", - "integrity": "sha512-NC/hJb9dtU23Zf8L7IVK95xnFjiQ7AfcLO2l5pb69TDEr958qxrtnB2CveeeNSCBFNIkgaTCfd/vHNSoG78l9g==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.54.0.tgz", + "integrity": "sha512-J0SSB8Z1Fre2sxRolYcW6Rl1RQmKdQ2hnHyq4YJrfBRiXTObLw4DXnIVraM/UyqGqwOi7yTrQA4VT7DPxlHVKA==", "cpu": [ "arm64" ], @@ -3377,9 +3359,9 @@ } }, "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.51.0.tgz", - "integrity": "sha512-2C45za4Rj36n8YIbhRL1PQbxmXJYf81WEcAgvj5I4ptRROG+A+81hREEN5bmCHADE1UfYaN312U6tkILoZZy6w==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.54.0.tgz", + "integrity": "sha512-O61UDVj8zz6yXJjkHPf05VaMLOXmEF8P5kf/N0W7AQMmd6bcQogl+KJc7rMutKTL524oE9iH32JXZClBFmEQIg==", "cpu": [ "ia32" ], @@ -3394,9 +3376,9 @@ } }, "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.51.0.tgz", - "integrity": "sha512-73RqdAuVKQTkjZIDw08JaDHUM4lav5Qu+CaPwg4QbbA7k8o7LEW0p3UsfZ/F8dsO/pwVYh3RzFcanwLRTTahbQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.54.0.tgz", + "integrity": "sha512-1MDpqJPiFqxWtIHas8vkb1VZ7f7eKyTffAwmO8isxQYMaG1OFKsH666BWLeXQLO+IWNfiMssLD55hbR1lIPTqg==", "cpu": [ "x64" ], @@ -3495,9 +3477,9 @@ ] }, "node_modules/@oxlint/binding-android-arm-eabi": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.66.0.tgz", - "integrity": "sha512-f7kq8N51T4phpzqfBpA2qaVTI/KrkCmNwaj3t/97I/WLTDI+UhlP5GL9eER+zVxBhtlx5rKXWByJU1/zDAvyaw==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.69.0.tgz", + "integrity": "sha512-DKQQbD5cZ/MYfDgDI7YGyGD9FSxABlsBsYFo5p26lloob543tP9+4N3guwdXIYJN+7HSZxLe8YJuwcOWw5qnHg==", "cpu": [ "arm" ], @@ -3512,9 +3494,9 @@ } }, "node_modules/@oxlint/binding-android-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.66.0.tgz", - "integrity": "sha512-xu6QO71tdDS9mjmLZ3AqhtaVHBvdmsOKkYnReNNDgh+XiwnsipeQOIxbiYOOO0iAXycJ+GK0wdMSZP/2j/AmSg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.69.0.tgz", + "integrity": "sha512-lEhb+I5pr4inux+JFwfCa1HRq3Os7NirEFQ0H1I35SVEHPm6byX0Ah47xmRha3qi6LAkxUcxViL8o/9PivjzBg==", "cpu": [ "arm64" ], @@ -3529,9 +3511,9 @@ } }, "node_modules/@oxlint/binding-darwin-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.66.0.tgz", - "integrity": "sha512-HZ24VimSOC7mxuEA99e0H2FS0C1yO3+iW13jPRAk+e2njsUs3QeAXsafCDyaIrV/MirdOVez+etQNQsJE43zNQ==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.69.0.tgz", + "integrity": "sha512-GY2YE8lOZW59BW1Ia1y+1gR0XyjrZRvVWHAr8LGeGhYHE0OQJ/7cRKXTkx1P+E9/6awEc3SX8a68SFTjh/E//A==", "cpu": [ "arm64" ], @@ -3546,9 +3528,9 @@ } }, "node_modules/@oxlint/binding-darwin-x64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.66.0.tgz", - "integrity": "sha512-awhj8ZvJrrRSnXj7V++rpZvTmnl99L6mi0B7gg7Cp7BN6cKpzuI481bHNLvXGA9GB1/oEgA3ponuyoAc6Md12A==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.69.0.tgz", + "integrity": "sha512-ax1oZnOjHX3LB7myQyHEaQkDwfLb6str3/nSP6O7EVUviQGNkEGzGV0EqcBJWK+Ufwx0l4xPgyYayurvhAdl2Q==", "cpu": [ "x64" ], @@ -3563,9 +3545,9 @@ } }, "node_modules/@oxlint/binding-freebsd-x64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.66.0.tgz", - "integrity": "sha512-KQF0oVV21/FjIqkRuL8Q1vh8ECsE5+ocdH5tcqTQ4ZnYuDVoYibQUNfqBjQaUsP6UIIda5Y75Wpm5p4RgQWiWw==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.69.0.tgz", + "integrity": "sha512-kHWeHv4g2h8NY+mpCxzCtY4uerMJWTN/TSnNj1CPbakFpHEJ6cTya2wWV0pDSYWOJ2+0UiEbhn3AtXxHtsnKjg==", "cpu": [ "x64" ], @@ -3580,9 +3562,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-gnueabihf": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.66.0.tgz", - "integrity": "sha512-9u1rgwZSEXWb30vbFZzQ78HVXBo0WCKNwJ3a2InRUTNMRng+PUDIoSFmA+m4HdUfBaIqftShq8J8qHc+eE/Vig==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.69.0.tgz", + "integrity": "sha512-gq84vM1a1oEehXo27YCDzGVcxPsZDI1yswZwz2Da1/cbnWtrL16XZZnz0G/+gIU8edtHpfjxq5c+vWEHqJfWoQ==", "cpu": [ "arm" ], @@ -3597,9 +3579,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-musleabihf": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.66.0.tgz", - "integrity": "sha512-Ynot2HR1bHxUaNWoC280MVTDfZuaWuP3XfSMRDhyuZrVjhzoaBCVFlw8h8qeZjWKVUBhPWFIxB7AQTlK8Z2WWg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.69.0.tgz", + "integrity": "sha512-kIqEa98JQ0VRyrcncxA417m2AzasqTlD+FyVT1AksjvjkqQcvm7pBWYvoW3/mpyOP2XYvi5nSCCTIe6De1yu5g==", "cpu": [ "arm" ], @@ -3614,9 +3596,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.66.0.tgz", - "integrity": "sha512-xCbgzciGgo+A4aQZEknsNrNiIwY7sU5SfRuMmRjPIvZAgdF34cIHiKvwOsS5XRLjlTVSFwitmq6YclTtHTfU+g==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.69.0.tgz", + "integrity": "sha512-j+xYiXozxGWx2cpjCrwwGR4awTxPFsRv3JZrv23RCogEPMc4R7UqjHW47p/RG0aRlbWiROCJ8coUfCwy0dvzHA==", "cpu": [ "arm64" ], @@ -3634,9 +3616,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.66.0.tgz", - "integrity": "sha512-hmo+ZB/lHkR1HdDmnziNpzSLmulnUSu10VEqX2Yex7OwvoBAbjJQLvy4gIBRV3AAwWnCvAxKp5Nv1GE6LU1QMg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.69.0.tgz", + "integrity": "sha512-xEPpNppTfN1l/nM7gYSf9iocscu/as+p/7vxkLeLEKnYU+09Dm+5V6IhDYDh+Uz6FajEupWwCLt5SOG0y1PCKg==", "cpu": [ "arm64" ], @@ -3654,9 +3636,9 @@ } }, "node_modules/@oxlint/binding-linux-ppc64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.66.0.tgz", - "integrity": "sha512-2Invd4Uyy81mVooQC5FBtfxSNrvcX1OxbMlVQ6M2erRrNI2awFYF26YNW2yFxdVFZ4ffNOWKghtMjhnUPsXsVA==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.69.0.tgz", + "integrity": "sha512-Ug0+eU7HJBlek+SjklYH62IlOMirEJsdxpihH0kSqX0XdrDD4NdHpQc10fK1JC35yn6KrrcN+uYzlHD38XAf8Q==", "cpu": [ "ppc64" ], @@ -3674,9 +3656,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.66.0.tgz", - "integrity": "sha512-s0iXPDQVdgayE3RGa/N2DZF7tjgg0TwEtD1sGoDxqPDGrIXgo45H0yHknT0f9A0yteASsweYZtDyTuVlM4aSag==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.69.0.tgz", + "integrity": "sha512-iEyI3GIg0l/s3G4qy2TlaaWKdzj4PJJStwtlocpDTC00PY9hZueotf6OKUj9+yfQh0lrpBW/pLMgTztbAHKJEg==", "cpu": [ "riscv64" ], @@ -3694,9 +3676,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.66.0.tgz", - "integrity": "sha512-OekL4XFiu7RPK0JIZi8VeHgtIXPREf42t8Cy/rKEsC+P3gcqDgNAAGiyuUOpdbG4wwbfue1q4CHcCO7spSve6w==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.69.0.tgz", + "integrity": "sha512-NjHjpiI4WIKSMwuoJSZi5VToPeoYOS1FR52HLIDG6lidMdqquusgtODb4iLk0+lb1q3Z0nv2/aPRcC/olmpQGg==", "cpu": [ "riscv64" ], @@ -3714,9 +3696,9 @@ } }, "node_modules/@oxlint/binding-linux-s390x-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.66.0.tgz", - "integrity": "sha512-Ga1D0kj1SFslm34ThA/BdkUlyAYEnTsXyRC4pF0C5agZSwtGdHYWMTQWemUfBGp4RCG4QWXgdO+HmmmKqOtlBg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.69.0.tgz", + "integrity": "sha512-Ai/prDewoItkDXbp38gwGZi41DycZbUTZJ3UidwoHgQC0/DaqC2TGdtBTQLJ6hSD+SAxASzh8+/eSBPmxfOacA==", "cpu": [ "s390x" ], @@ -3734,9 +3716,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-gnu": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.66.0.tgz", - "integrity": "sha512-p5jfP1wUZe/IC3qpQO84n9DRnf9g3lKRtLBlQq23ykyrDglHcVx7sWmVTlPuU6SBw8mNnPzyOn022G3XZHnlww==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.69.0.tgz", + "integrity": "sha512-Gt3KHgp46mRKz4sJeaASmKvD8ayXookRw07RMf+NowhEztGGDZ7VrXpoW96XuKJLjFukWizOFVNjmYb/u7caNQ==", "cpu": [ "x64" ], @@ -3754,9 +3736,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-musl": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.66.0.tgz", - "integrity": "sha512-vUB/sYlYZorDL1ZD+o9mRv7zbsykrrFRtmgS6R8musZqLtrPRQn1gc1eGpuX+sfdccz42STl/AqldY6XRb2upQ==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.69.0.tgz", + "integrity": "sha512-7tQhJ2+p/oHv1zcfnjYI7YVzC/7iBaVOfIvFYtxdJ5F45mWgEdrCyXZXZGfiLey5t/5JhOhsaMnnv1kAzckd7g==", "cpu": [ "x64" ], @@ -3774,9 +3756,9 @@ } }, "node_modules/@oxlint/binding-openharmony-arm64": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.66.0.tgz", - "integrity": "sha512-yde+6p/F59xRkGR9H1HfngWRif1QRJjynZK349l+UI0H6w9hL3G8/AVaTHFyTtLVQ56qtNbX2/5Dc77n1ovnOg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.69.0.tgz", + "integrity": "sha512-vmWz6TKp/3hfA4lksR0zHBv/6xuX1jhym6eqOjdH2DXsDDHZWcp2f0KG0VCAnlVbIrjk29G4wAWMXb/Hn1YobA==", "cpu": [ "arm64" ], @@ -3791,9 +3773,9 @@ } }, "node_modules/@oxlint/binding-win32-arm64-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.66.0.tgz", - "integrity": "sha512-O9GLucgoTdmOrbBX+EjzNe7o/Ze5TFOvXcib6bzUOtBOmj6cV+zw18NgB+cGKAkDw1Pdqs8vGkfHbbsLuDtXWg==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.69.0.tgz", + "integrity": "sha512-9RExaLgmaw6IoIkU9cTpT71mLfI0xZ86iZH8x518LVsOkjquJMYqb9P7KpC8lgd1t0Dxs41p2pxynq4XR3Ttzw==", "cpu": [ "arm64" ], @@ -3808,9 +3790,9 @@ } }, "node_modules/@oxlint/binding-win32-ia32-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.66.0.tgz", - "integrity": "sha512-m3Pjwc2MfTcom4E4gOv7DyuGyt7OfGNCbmqDHd+N7EzXmP+ppHuudm2NjcA3AjV5TSeGxaguVF4SbTKHe1USYA==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.69.0.tgz", + "integrity": "sha512-1907kRPF8/PrcIw1E7LMs9JbVrpgnt/MvFdss3an8oDkYNAACXzTntV3t3869ZZhMZxb2AzRGbz1pA/jdFatXA==", "cpu": [ "ia32" ], @@ -3825,9 +3807,9 @@ } }, "node_modules/@oxlint/binding-win32-x64-msvc": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.66.0.tgz", - "integrity": "sha512-/DbBvw8UFBhja6PqudUjV4UtfsJr0Oa7jUjWVKB0g86lj/VwnPrkngn0sFql3c9RDA0O16dh7ozsXb6GjNAzBQ==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.69.0.tgz", + "integrity": "sha512-w8SOXv3mT9Fi6jY8OXdXCfnvX/3KNLXGNr4HEz2TA7S4Mv/PYAOmpB8y/ge40mxvBMgGNaSaaDwZpAsQn7HtWA==", "cpu": [ "x64" ], @@ -4692,9 +4674,9 @@ "license": "MIT" }, "node_modules/@swc/helpers": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", - "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -4946,17 +4928,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz", - "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/type-utils": "8.59.4", - "@typescript-eslint/utils": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -4969,7 +4951,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.59.4", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -4985,16 +4967,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.4.tgz", - "integrity": "sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -5010,14 +4992,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.4.tgz", - "integrity": "sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.4", - "@typescript-eslint/types": "^8.59.4", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -5032,14 +5014,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz", - "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5050,9 +5032,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.4.tgz", - "integrity": "sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -5067,15 +5049,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.4.tgz", - "integrity": "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -5092,9 +5074,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", - "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -5106,16 +5088,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz", - "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.4", - "@typescript-eslint/tsconfig-utils": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -5133,56 +5115,17 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.4.tgz", - "integrity": "sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5197,13 +5140,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.4.tgz", - "integrity": "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5418,9 +5361,9 @@ "license": "MIT" }, "node_modules/@vscode/test-electron": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", - "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-3.0.0.tgz", + "integrity": "sha512-TY5mC7aAjxSLDXsyjhrG8cJHgc/HLdiE5lvtW7hABYQrY24Qwozzr5UoO3HiuAM4Hzz4b7K/eZlwrCILj94CcA==", "dev": true, "license": "MIT", "dependencies": { @@ -5431,7 +5374,7 @@ "semver": "^7.6.2" }, "engines": { - "node": ">=16" + "node": ">=22" } }, "node_modules/@vscode/vsce": { @@ -5881,6 +5824,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -5978,12 +5922,24 @@ "license": "BSD-2-Clause" }, "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -6373,44 +6329,140 @@ "license": "MIT" }, "node_modules/concurrently": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", - "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.3.tgz", + "integrity": "sha512-hc3LH4UaKWd/bbyDK/IGVa4RB6PtQ3CUYwtrkzqHn+wIG3Hr5fhpRlk0L/gCa8ZE1L/Ufj50Zho69cI5w8SQBA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "4.1.2", + "chalk": "5.6.2", "rxjs": "7.8.2", - "shell-quote": "1.8.3", - "supports-color": "8.1.1", + "shell-quote": "1.8.4", + "supports-color": "10.2.2", "tree-kill": "1.2.2", - "yargs": "17.7.2" + "yargs": "18.0.0" }, "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" + "conc": "dist/bin/index.js", + "concurrently": "dist/bin/index.js" }, "engines": { - "node": ">=18" + "node": ">=22" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "dev": true, + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=10" + "node": ">=20" + } + }, + "node_modules/concurrently/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concurrently/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/convert-source-map": { @@ -6966,9 +7018,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", - "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", + "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", "license": "MIT", "workspaces": [ "docs", @@ -7116,29 +7168,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -7159,22 +7188,6 @@ "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/espree": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", @@ -7594,45 +7607,6 @@ "node": ">= 6" } }, - "node_modules/glob/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { "version": "17.6.0", "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", @@ -8870,6 +8844,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -8906,9 +8895,9 @@ "license": "MIT" }, "node_modules/mongodb": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.2.0.tgz", - "integrity": "sha512-F/2+BMZtLVhY30ioZp0dAmZ+IRZMBqI+nrv6t5+9/1AIwCa8sMRC3jBf81lpxMhnZgqq8CoUD503Z1oZWq1/sw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.3.0.tgz", + "integrity": "sha512-WpCqSx7JAU9vcyjm/SU7ydnHls2YrfU3Y3sx4Ml9D7sPe4mXPlaapndiurDXrQ7/VvJkB4/i7b7WovHb8bd8sg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9358,9 +9347,9 @@ } }, "node_modules/oxfmt": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.51.0.tgz", - "integrity": "sha512-l/AoAnaEOV7Q5/Z9kHOMDehVJnCgYN7wRoooWCTUMBMi16BJhLZqd9cmCnwcVFfVlzkt53zK2KLPFNp8vSsoDg==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.54.0.tgz", + "integrity": "sha512-DjnMwn7smSLF+Mc2+pRItnuPftm/dkUFpY/d4+33y9TfKrsHZo8GLhmUg9BrOIUEy94Rlom1Q11N6vuhE+e0oQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9376,39 +9365,43 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.51.0", - "@oxfmt/binding-android-arm64": "0.51.0", - "@oxfmt/binding-darwin-arm64": "0.51.0", - "@oxfmt/binding-darwin-x64": "0.51.0", - "@oxfmt/binding-freebsd-x64": "0.51.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.51.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.51.0", - "@oxfmt/binding-linux-arm64-gnu": "0.51.0", - "@oxfmt/binding-linux-arm64-musl": "0.51.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-musl": "0.51.0", - "@oxfmt/binding-linux-s390x-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-musl": "0.51.0", - "@oxfmt/binding-openharmony-arm64": "0.51.0", - "@oxfmt/binding-win32-arm64-msvc": "0.51.0", - "@oxfmt/binding-win32-ia32-msvc": "0.51.0", - "@oxfmt/binding-win32-x64-msvc": "0.51.0" + "@oxfmt/binding-android-arm-eabi": "0.54.0", + "@oxfmt/binding-android-arm64": "0.54.0", + "@oxfmt/binding-darwin-arm64": "0.54.0", + "@oxfmt/binding-darwin-x64": "0.54.0", + "@oxfmt/binding-freebsd-x64": "0.54.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.54.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.54.0", + "@oxfmt/binding-linux-arm64-gnu": "0.54.0", + "@oxfmt/binding-linux-arm64-musl": "0.54.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.54.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.54.0", + "@oxfmt/binding-linux-riscv64-musl": "0.54.0", + "@oxfmt/binding-linux-s390x-gnu": "0.54.0", + "@oxfmt/binding-linux-x64-gnu": "0.54.0", + "@oxfmt/binding-linux-x64-musl": "0.54.0", + "@oxfmt/binding-openharmony-arm64": "0.54.0", + "@oxfmt/binding-win32-arm64-msvc": "0.54.0", + "@oxfmt/binding-win32-ia32-msvc": "0.54.0", + "@oxfmt/binding-win32-x64-msvc": "0.54.0" }, "peerDependencies": { - "svelte": "^5.0.0" + "svelte": "^5.0.0", + "vite-plus": "*" }, "peerDependenciesMeta": { "svelte": { "optional": true + }, + "vite-plus": { + "optional": true } } }, "node_modules/oxlint": { - "version": "1.66.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.66.0.tgz", - "integrity": "sha512-N4LLxYLd94KEBqXDMDM5f+2PUpItTjDLreXe2Gn5KhjhCK4Qp2YUXaBi8Yu325ryOgKwt22m45fpD7nPOn69Yw==", + "version": "1.69.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.69.0.tgz", + "integrity": "sha512-ypZkK/aDc5NQV8zIR6s2H2Tl3aNW8FmJ1m9+2qsaYuRenl8vgnHNCGwTHviWJdUQzglOlHFchgopdtGhSy17Rw==", "dev": true, "license": "MIT", "bin": { @@ -9421,32 +9414,36 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxlint/binding-android-arm-eabi": "1.66.0", - "@oxlint/binding-android-arm64": "1.66.0", - "@oxlint/binding-darwin-arm64": "1.66.0", - "@oxlint/binding-darwin-x64": "1.66.0", - "@oxlint/binding-freebsd-x64": "1.66.0", - "@oxlint/binding-linux-arm-gnueabihf": "1.66.0", - "@oxlint/binding-linux-arm-musleabihf": "1.66.0", - "@oxlint/binding-linux-arm64-gnu": "1.66.0", - "@oxlint/binding-linux-arm64-musl": "1.66.0", - "@oxlint/binding-linux-ppc64-gnu": "1.66.0", - "@oxlint/binding-linux-riscv64-gnu": "1.66.0", - "@oxlint/binding-linux-riscv64-musl": "1.66.0", - "@oxlint/binding-linux-s390x-gnu": "1.66.0", - "@oxlint/binding-linux-x64-gnu": "1.66.0", - "@oxlint/binding-linux-x64-musl": "1.66.0", - "@oxlint/binding-openharmony-arm64": "1.66.0", - "@oxlint/binding-win32-arm64-msvc": "1.66.0", - "@oxlint/binding-win32-ia32-msvc": "1.66.0", - "@oxlint/binding-win32-x64-msvc": "1.66.0" + "@oxlint/binding-android-arm-eabi": "1.69.0", + "@oxlint/binding-android-arm64": "1.69.0", + "@oxlint/binding-darwin-arm64": "1.69.0", + "@oxlint/binding-darwin-x64": "1.69.0", + "@oxlint/binding-freebsd-x64": "1.69.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.69.0", + "@oxlint/binding-linux-arm-musleabihf": "1.69.0", + "@oxlint/binding-linux-arm64-gnu": "1.69.0", + "@oxlint/binding-linux-arm64-musl": "1.69.0", + "@oxlint/binding-linux-ppc64-gnu": "1.69.0", + "@oxlint/binding-linux-riscv64-gnu": "1.69.0", + "@oxlint/binding-linux-riscv64-musl": "1.69.0", + "@oxlint/binding-linux-s390x-gnu": "1.69.0", + "@oxlint/binding-linux-x64-gnu": "1.69.0", + "@oxlint/binding-linux-x64-musl": "1.69.0", + "@oxlint/binding-openharmony-arm64": "1.69.0", + "@oxlint/binding-win32-arm64-msvc": "1.69.0", + "@oxlint/binding-win32-ia32-msvc": "1.69.0", + "@oxlint/binding-win32-x64-msvc": "1.69.0" }, "peerDependencies": { - "oxlint-tsgolint": ">=0.22.1" + "oxlint-tsgolint": ">=0.22.1", + "vite-plus": "*" }, "peerDependenciesMeta": { "oxlint-tsgolint": { "optional": true + }, + "vite-plus": { + "optional": true } } }, @@ -10407,13 +10404,13 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.99.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", - "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", + "chokidar": "^5.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, @@ -10421,36 +10418,36 @@ "sass": "sass.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" } }, "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14.18.0" + "node": ">= 20.19.0" }, "funding": { "type": "individual", @@ -10525,9 +10522,9 @@ } }, "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10567,9 +10564,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", "dev": true, "license": "MIT", "engines": { @@ -10950,6 +10947,19 @@ "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", "license": "MIT" }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/supports-hyperlinks": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", @@ -11352,16 +11362,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.4.tgz", - "integrity": "sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.4", - "@typescript-eslint/parser": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11728,54 +11738,49 @@ } }, "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.0.tgz", + "integrity": "sha512-+VvMmQPJhtvJ+8O+zu2JKIRiLxXF8NW7krWgyMGeOHrp4Cn23T5hc0v2LknNeopDOB70wghHAds7mKtcZ0I4Sg==", "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-10.0.0.tgz", + "integrity": "sha512-3yRHFkktZQCCg8ehHnD2Z4DZ4mZ17FNo8bxM4OFt8wtpxNBAOZGHmpbIflZSkicvCxi+ozuWntbdeWiY0gP77w==", "license": "MIT", "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" + "minimatch": "^10.2.5", + "semver": "^7.8.1", + "vscode-languageserver-protocol": "3.18.0", + "vscode-languageserver-textdocument": "1.0.13" }, "engines": { - "vscode": "^1.82.0" - } - }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" + "vscode": "^1.91.0" } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.0.tgz", + "integrity": "sha512-Zdz+kJ12Iz6tc11xfZyEo501bBATHXrCjmMfnaR3pMnf1CoqZBKIynba3P+/bi9VEdrMbNtAVKYpKhbODvqy+Q==", "license": "MIT", "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "vscode-jsonrpc": "9.0.0", + "vscode-languageserver-types": "3.18.0" } }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.13.tgz", + "integrity": "sha512-nx0ZHwMGIsVkzFG3/VLeJYBLTaFBRuNdGDvevvjuoayU5EOS2fEYazOhtCM3PI9ClMMg5igc0uwXtAq4tJj+Dw==", + "license": "MIT" + }, "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", + "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", "license": "MIT" }, "node_modules/vscode-tas-client": { @@ -12087,17 +12092,17 @@ "license": "MIT", "dependencies": { "@cosmosdb/schema-analyzer": "*", - "chevrotain": "~12.0.0" + "chevrotain": "^12.0.0" }, "devDependencies": { - "@codemirror/autocomplete": "~6.20.2", - "@codemirror/language": "~6.12.3", - "@codemirror/lint": "~6.9.6", - "@codemirror/state": "~6.6.0", - "@codemirror/view": "~6.42.1", + "@codemirror/autocomplete": "^6.18.0", + "@codemirror/language": "^6.10.0", + "@codemirror/lint": "^6.8.0", + "@codemirror/state": "^6.5.0", + "@codemirror/view": "^6.43.0", "@types/vscode": "~1.109.0", "monaco-editor": "~0.52.2", - "vitest": "~4.1.0" + "vitest": "^4.1.0" }, "engines": { "node": ">=22" @@ -12131,19 +12136,6 @@ } } }, - "packages/nosql-language-service/node_modules/@codemirror/view": { - "version": "6.42.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", - "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.6.0", - "crelt": "^1.0.6", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, "packages/schema-analyzer": { "name": "@cosmosdb/schema-analyzer", "version": "0.1.0", @@ -12153,7 +12145,7 @@ }, "devDependencies": { "@types/json-schema": "~7.0.15", - "mongodb": "~7.2.0", + "mongodb": "~7.3.0", "vitest": "~4.1.0" }, "engines": { @@ -12167,6 +12159,39 @@ "optional": true } } + }, + "packages/webview-rpc": { + "name": "@cosmosdb/webview-rpc", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@trpc/client": "~11.17.0", + "@trpc/server": "~11.17.0" + }, + "devDependencies": { + "@types/node": "~25.9.1", + "@types/react": "~19.2.15", + "@types/vscode": "~1.109.0", + "@types/vscode-webview": "~1.57.5", + "@vscode/l10n": "~0.0.18", + "react": "~19.2.1", + "vitest": "~4.1.7" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "@vscode/l10n": ">=0.0.18", + "react": ">=18.0.0" + }, + "peerDependenciesMeta": { + "@vscode/l10n": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 901d67c1c..737586821 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "@types/vscode-webview": "~1.57.5", "@vitejs/plugin-react": "^6.0.1", "@vscode/l10n-dev": "~0.0.35", - "@vscode/test-electron": "~2.5.2", + "@vscode/test-electron": "~3.0.0", "@vscode/vsce": "~3.9.1", "concurrently": "~10.0.3", "cross-env": "~10.1.0", @@ -126,8 +126,8 @@ "glob": "~13.0.6", "globals": "~17.6.0", "jest-mock-vscode": "~4.12.0", - "oxfmt": "~0.51.0", - "oxlint": "~1.66.0", + "oxfmt": "~0.54.0", + "oxlint": "~1.69.0", "oxlint-tsgolint": "~0.23.0", "react": "~19.2.1", "react-dom": "~19.2.1", @@ -135,7 +135,7 @@ "rimraf": "~6.1.0", "sass": "~1.100.0", "typescript": "~6.0.2", - "typescript-eslint": "~8.60.1", + "typescript-eslint": "~8.61.0", "vite": "~8.0.10", "vite-bundle-analyzer": "~1.3.7", "vite-plugin-static-copy": "~4.1.0", @@ -151,20 +151,20 @@ "@fluentui/react-components": "~9.74.1", "@fluentui/react-icons": "~2.0.313", "@microsoft/vscode-azext-azureauth": "~5.1.1", - "@microsoft/vscode-azext-azureutils": "~4.2.0", + "@microsoft/vscode-azext-azureutils": "~4.3.0", "@microsoft/vscode-azext-utils": "~4.1.0", "@microsoft/vscode-azureresources-api": "~3.1.0", "@monaco-editor/react": "~4.7.0", "@prantlf/jsonlint": "~17.0.0", "@vscode/l10n": "~0.0.18", - "@vscode/prompt-tsx": "^0.4.0-alpha.7", + "@vscode/prompt-tsx": "^0.4.0-alpha.8", "allotment": "~1.20.4", "es-toolkit": "~1.47.0", "monaco-editor": "~0.52.2", "react-data-grid": "~7.0.0-beta.59", "react-hotkeys-hook": "5.1.0", "semver": "~7.8.0", - "vscode-languageclient": "~9.0.1", + "vscode-languageclient": "~10.0.0", "zod": "~4.4.3" }, "overrides": { diff --git a/packages/nosql-language-service/package.json b/packages/nosql-language-service/package.json index 673efeb72..a17d36272 100644 --- a/packages/nosql-language-service/package.json +++ b/packages/nosql-language-service/package.json @@ -62,17 +62,17 @@ }, "dependencies": { "@cosmosdb/schema-analyzer": "*", - "chevrotain": "~12.0.0" + "chevrotain": "^12.0.0" }, "devDependencies": { - "@codemirror/autocomplete": "~6.20.2", - "@codemirror/language": "~6.12.3", - "@codemirror/lint": "~6.9.6", - "@codemirror/state": "~6.6.0", - "@codemirror/view": "~6.42.1", + "@codemirror/autocomplete": "^6.18.0", + "@codemirror/language": "^6.10.0", + "@codemirror/lint": "^6.8.0", + "@codemirror/state": "^6.5.0", + "@codemirror/view": "^6.43.0", "@types/vscode": "~1.109.0", "monaco-editor": "~0.52.2", - "vitest": "~4.1.0" + "vitest": "^4.1.0" }, "peerDependencies": { "@codemirror/autocomplete": "^6.0.0", diff --git a/packages/schema-analyzer/package.json b/packages/schema-analyzer/package.json index c98be7236..70180c0f8 100644 --- a/packages/schema-analyzer/package.json +++ b/packages/schema-analyzer/package.json @@ -53,7 +53,7 @@ }, "devDependencies": { "@types/json-schema": "~7.0.15", - "mongodb": "~7.2.0", + "mongodb": "~7.3.0", "vitest": "~4.1.0" }, "engines": {