fix: ACE editor integration crash — React 19 compat, Vite ?url pattern, Error Boundary

Root causes:
- react-ace v12 doesn't support React 19 (project uses ^19.2.5)
- Dynamic import(`ace-builds/src-noconflict/mode-${language}`) broken with Vite
  (template-literal dynamic imports can't be statically analyzed)
- No React Error Boundaries — ACE render crash whitescreens entire app
- ace-builds/react-ace duplicated in backend package.json

Fixes:
1. Upgrade react-ace ^12.0.0 → ^14.0.1 (React 19 support)
2. Upgrade ace-builds ^1.36.0 → ^1.43.6
3. Remove ACE deps from backend package.json (not used by Express)
4. Replace broken dynamic imports with Vite ?url + ace.config.setModuleUrl()
   pattern (canonical Vite solution per ace#4597)
5. Add ErrorBoundary component wrapping EditorPanel
6. Add vite.d.ts type declarations for ?url/?raw/?worker imports
7. Fix worker-typescript import (doesn't exist — TS uses worker-javascript)
8. Register 24 language modes, 4 workers, 1 theme, 2 extensions

Verified: TypeScript clean, production build passes, heartbeat worker intact.
This commit is contained in:
Rob Colbert 2026-05-12 21:36:22 -04:00
parent fb8f15aeec
commit c14c3a235a
8 changed files with 253 additions and 85 deletions

View File

@ -11,9 +11,9 @@
"author": "Robert Colbert <rob.colbert@openplatform.us>",
"license": "Apache-2.0",
"dependencies": {
"ace-builds": "^1.36.0",
"ace-builds": "^1.44.0",
"marked": "^16.0.0",
"react-ace": "^12.0.0",
"react-ace": "^14.0.1",
"slug": "^11.0.1"
}
}

View File

@ -1,8 +1,108 @@
import { useState, useCallback, useEffect } from 'react';
import Ace from 'react-ace';
import 'ace-builds/src-noconflict/mode-text';
import 'ace-builds/src-noconflict/theme-tomorrow';
import 'ace-builds/src-noconflict/ext-language_tools';
import ace from 'ace-builds';
// ── Vite ?url imports for ACE modes ──────────────────────────────────────
// These resolve at build time to asset URLs. We register them with ACE's
// module system via setModuleUrl() so that ACE can lazy-load them at runtime
// without relying on broken dynamic import() or script-tag detection.
//
// See: https://github.com/ajaxorg/ace/issues/4597
// ─────────────────────────────────────────────────────────────────────────
import modeJavascriptUrl from 'ace-builds/src-noconflict/mode-javascript?url';
import modeTypescriptUrl from 'ace-builds/src-noconflict/mode-typescript?url';
import modePythonUrl from 'ace-builds/src-noconflict/mode-python?url';
import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url';
import modeHtmlUrl from 'ace-builds/src-noconflict/mode-html?url';
import modeCssUrl from 'ace-builds/src-noconflict/mode-css?url';
import modeYamlUrl from 'ace-builds/src-noconflict/mode-yaml?url';
import modeMarkdownUrl from 'ace-builds/src-noconflict/mode-markdown?url';
import modeShUrl from 'ace-builds/src-noconflict/mode-sh?url';
import modeSqlUrl from 'ace-builds/src-noconflict/mode-sql?url';
import modeJavaUrl from 'ace-builds/src-noconflict/mode-java?url';
import modeGolangUrl from 'ace-builds/src-noconflict/mode-golang?url';
import modeRustUrl from 'ace-builds/src-noconflict/mode-rust?url';
import modeCsharpUrl from 'ace-builds/src-noconflict/mode-csharp?url';
import modePhpUrl from 'ace-builds/src-noconflict/mode-php?url';
import modeRubyUrl from 'ace-builds/src-noconflict/mode-ruby?url';
import modeCcppUrl from 'ace-builds/src-noconflict/mode-c_cpp?url';
import modeScssUrl from 'ace-builds/src-noconflict/mode-scss?url';
import modeLessUrl from 'ace-builds/src-noconflict/mode-less?url';
import modeXmlUrl from 'ace-builds/src-noconflict/mode-xml?url';
import modeDockerfileUrl from 'ace-builds/src-noconflict/mode-dockerfile?url';
import modeMakefileUrl from 'ace-builds/src-noconflict/mode-makefile?url';
import modeSassUrl from 'ace-builds/src-noconflict/mode-sass?url';
import modeTextUrl from 'ace-builds/src-noconflict/mode-text?url';
// Workers (for syntax validation — currently disabled via useWorker:false,
// but registered in case we want to enable them later)
import workerJavascriptUrl from 'ace-builds/src-noconflict/worker-javascript?url';
import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url';
import workerCssUrl from 'ace-builds/src-noconflict/worker-css?url';
import workerHtmlUrl from 'ace-builds/src-noconflict/worker-html?url';
// Theme
import themeTomorrowUrl from 'ace-builds/src-noconflict/theme-tomorrow?url';
// Extensions
import extLanguageToolsUrl from 'ace-builds/src-noconflict/ext-language_tools?url';
import extSearchboxUrl from 'ace-builds/src-noconflict/ext-searchbox?url';
// ── Register all modules with ACE ────────────────────────────────────────
const MODE_URLS: Record<string, string> = {
javascript: modeJavascriptUrl,
typescript: modeTypescriptUrl,
python: modePythonUrl,
json: modeJsonUrl,
html: modeHtmlUrl,
css: modeCssUrl,
yaml: modeYamlUrl,
markdown: modeMarkdownUrl,
sh: modeShUrl,
sql: modeSqlUrl,
java: modeJavaUrl,
golang: modeGolangUrl,
rust: modeRustUrl,
csharp: modeCsharpUrl,
php: modePhpUrl,
ruby: modeRubyUrl,
c_cpp: modeCcppUrl,
scss: modeScssUrl,
less: modeLessUrl,
xml: modeXmlUrl,
dockerfile: modeDockerfileUrl,
makefile: modeMakefileUrl,
sass: modeSassUrl,
text: modeTextUrl,
};
const WORKER_URLS: Record<string, string> = {
javascript: workerJavascriptUrl,
typescript: workerJavascriptUrl, // TS mode shares the JS worker
json: workerJsonUrl,
css: workerCssUrl,
html: workerHtmlUrl,
};
// Register modes
for (const [mode, url] of Object.entries(MODE_URLS)) {
ace.config.setModuleUrl(`ace/mode/${mode}`, url);
}
// Register workers
for (const [mode, url] of Object.entries(WORKER_URLS)) {
ace.config.setModuleUrl(`ace/mode/${mode}_worker`, url);
}
// Register theme and extensions
ace.config.setModuleUrl('ace/theme/tomorrow', themeTomorrowUrl);
ace.config.setModuleUrl('ace/ext/language_tools', extLanguageToolsUrl);
ace.config.setModuleUrl('ace/ext/searchbox', extSearchboxUrl);
// ── Component ────────────────────────────────────────────────────────────
import { WorkspaceMode } from '../lib/types';
import { socketClient } from '../lib/socket';
@ -100,13 +200,7 @@ export default function EditorPanel({ workspaceMode, filePath, onCloseFile }: Ed
if (result.success && result.content !== undefined) {
const language = detectLanguage(path);
// Dynamically import the language mode
try {
await import(`ace-builds/src-noconflict/mode-${language}`);
} catch (e) {
console.warn(`Could not load ACE mode for ${language}, falling back to text`);
}
// No dynamic import needed — all modes are registered via setModuleUrl at module load time
setState({
content: result.content,

View File

@ -0,0 +1,56 @@
import { Component, type ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
}
/**
* React Error Boundary catches render errors from child components
* and displays a fallback UI instead of crashing the entire app.
*
* Use this to wrap components that may throw during render (e.g., ACE editor).
*/
export default class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('[ErrorBoundary] caught render error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
if (this.props.fallback) return this.props.fallback;
return (
<div className="flex-1 flex items-center justify-center bg-bg-secondary">
<div className="text-center max-w-md">
<svg className="w-16 h-16 mx-auto mb-4 text-red-500 opacity-75" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
</svg>
<h2 className="text-lg font-medium text-text-primary mb-2">Something went wrong</h2>
<p className="text-sm text-text-muted mb-4">{this.state.error?.message || 'An unexpected error occurred.'}</p>
<button
onClick={() => this.setState({ hasError: false, error: null })}
className="px-4 py-2 text-sm font-medium bg-brand text-white rounded hover:bg-brand/80 transition-colors"
>
Try Again
</button>
</div>
</div>
);
}
return this.props.children;
}
}

View File

@ -8,6 +8,7 @@ import FilesPanel from '../components/FilesPanel';
import LogPanel from '../components/LogPanel';
import ChatTurnComponent from '../components/ChatTurn';
import EditorPanel from '../components/EditorPanel';
import ErrorBoundary from '../components/ErrorBoundary';
import { AppContext } from '../App';
interface LogEntry {
@ -1091,11 +1092,13 @@ export default function ChatSessionView() {
{/* File Editor View (replaces Chat View when file is open) */}
{editorFilePath ? (
<EditorPanel
workspaceMode={workspaceMode}
filePath={editorFilePath}
onCloseFile={() => setEditorFilePath(undefined)}
/>
<ErrorBoundary>
<EditorPanel
workspaceMode={workspaceMode}
filePath={editorFilePath}
onCloseFile={() => setEditorFilePath(undefined)}
/>
</ErrorBoundary>
) : (
/* Chat View (75%) */
<div className="flex-1 flex flex-col overflow-hidden">

View File

@ -0,0 +1,17 @@
// Type declarations for Vite-specific import suffixes
// These allow TypeScript to understand Vite's ?url and ?raw import patterns
declare module '*?url' {
const url: string;
export default url;
}
declare module '*?raw' {
const content: string;
export default content;
}
declare module '*?worker' {
const worker: new () => Worker;
export default worker;
}

View File

@ -27,8 +27,6 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@gadget/ai": "workspace:*",
"ace-builds": "^1.36.0",
"react-ace": "^12.0.0",
"@gadget/api": "workspace:*",
"@gadget/config": "workspace:*",
"@react-three/drei": "^10.7.7",

View File

@ -231,9 +231,15 @@ importers:
frontend:
dependencies:
ace-builds:
specifier: ^1.44.0
version: 1.44.0
marked:
specifier: ^16.0.0
version: 16.0.0
react-ace:
specifier: ^14.0.1
version: 14.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
slug:
specifier: ^11.0.1
version: 11.0.1
@ -1123,6 +1129,9 @@ packages:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
ace-builds@1.44.0:
resolution: {integrity: sha512-PFNMSYqFdEUkul2Ntud0HvA09AgY+F1ag0UYdpMH60wNI/qOA8cB8tlTgoALMEwIdUPJK2CjrIQ7OnbiSS/ugQ==}
acorn@7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
@ -1515,6 +1524,9 @@ packages:
diacritics@1.3.0:
resolution: {integrity: sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==}
diff-match-patch@1.0.5:
resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@ -2075,6 +2087,10 @@ packages:
lodash.defaults@4.2.0:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
lodash.get@4.4.2:
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
deprecated: This package is deprecated. Use the optional chaining (?.) operator instead.
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
@ -2084,6 +2100,10 @@ packages:
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
lodash.isfinite@3.3.2:
resolution: {integrity: sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==}
@ -2105,6 +2125,10 @@ packages:
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
lru-cache@11.3.5:
resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==}
engines: {node: 20 || >=22}
@ -2432,6 +2456,9 @@ packages:
promise@7.3.1:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@ -2514,11 +2541,20 @@ packages:
resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
engines: {node: '>= 0.8'}
react-ace@14.0.1:
resolution: {integrity: sha512-z6YAZ20PNf/FqmYEic//G/UK6uw0rn21g58ASgHJHl9rfE4nITQLqthr9rHMVQK4ezwohJbp2dGrZpkq979PYQ==}
peerDependencies:
react: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom@19.2.5:
resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies:
react: ^19.2.5
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
@ -3830,6 +3866,8 @@ snapshots:
mime-types: 3.0.1
negotiator: 1.0.0
ace-builds@1.44.0: {}
acorn@7.4.1: {}
ansi-regex@5.0.1: {}
@ -4237,6 +4275,8 @@ snapshots:
diacritics@1.3.0: {}
diff-match-patch@1.0.5: {}
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
@ -4906,12 +4946,16 @@ snapshots:
lodash.defaults@4.2.0: {}
lodash.get@4.4.2: {}
lodash.includes@4.3.0: {}
lodash.isarguments@3.1.0: {}
lodash.isboolean@3.0.3: {}
lodash.isequal@4.5.0: {}
lodash.isfinite@3.3.2: {}
lodash.isinteger@4.0.4: {}
@ -4926,6 +4970,10 @@ snapshots:
lodash@4.17.21: {}
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
lru-cache@11.3.5: {}
luxon@3.6.1: {}
@ -5220,6 +5268,12 @@ snapshots:
dependencies:
asap: 2.0.6
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@ -5335,11 +5389,23 @@ snapshots:
iconv-lite: 0.6.3
unpipe: 1.0.0
react-ace@14.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies:
ace-builds: 1.44.0
diff-match-patch: 1.0.5
lodash.get: 4.4.2
lodash.isequal: 4.5.0
prop-types: 15.8.1
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
react-dom@19.2.5(react@19.2.5):
dependencies:
react: 19.2.5
scheduler: 0.27.0
react-is@16.13.1: {}
react-is@17.0.2: {}
react-router-dom@7.14.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5):

View File

@ -28,9 +28,6 @@ importers:
'@react-three/fiber':
specifier: ^9.6.1
version: 9.6.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(three@0.184.0)
ace-builds:
specifier: ^1.36.0
version: 1.44.0
ansicolor:
specifier: ^2.0.3
version: 2.0.3
@ -112,9 +109,6 @@ importers:
react:
specifier: ^19.2.5
version: 19.2.5
react-ace:
specifier: ^12.0.0
version: 12.0.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
react-dom:
specifier: ^19.2.5
version: 19.2.5(react@19.2.5)
@ -1561,9 +1555,6 @@ packages:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
ace-builds@1.44.0:
resolution: {integrity: sha512-PFNMSYqFdEUkul2Ntud0HvA09AgY+F1ag0UYdpMH60wNI/qOA8cB8tlTgoALMEwIdUPJK2CjrIQ7OnbiSS/ugQ==}
acorn@7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
@ -1984,9 +1975,6 @@ packages:
diacritics@1.3.0:
resolution: {integrity: sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==}
diff-match-patch@1.0.5:
resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@ -2629,10 +2617,6 @@ packages:
lodash.defaults@4.2.0:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
lodash.get@4.4.2:
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
deprecated: This package is deprecated. Use the optional chaining (?.) operator instead.
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
@ -2642,10 +2626,6 @@ packages:
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
lodash.isfinite@3.3.2:
resolution: {integrity: sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==}
@ -2667,10 +2647,6 @@ packages:
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
lru-cache@11.3.5:
resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==}
engines: {node: 20 || >=22}
@ -3052,9 +3028,6 @@ packages:
promise@7.3.1:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@ -3137,20 +3110,11 @@ packages:
resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==}
engines: {node: '>= 0.10'}
react-ace@12.0.0:
resolution: {integrity: sha512-PstU6CSMfYIJknb4su2Fa0WgLXzq2ufQgR6fjcSWuGT1hGTHkBzuKw+SncV8PuLCdSJBJc1VehPhyeXlWByG/g==}
peerDependencies:
react: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0
react-dom: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0
react-dom@19.2.5:
resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies:
react: ^19.2.5
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
@ -4837,8 +4801,6 @@ snapshots:
mime-types: 3.0.2
negotiator: 1.0.0
ace-builds@1.44.0: {}
acorn@7.4.1: {}
agent-base@7.1.4: {}
@ -5262,8 +5224,6 @@ snapshots:
diacritics@1.3.0: {}
diff-match-patch@1.0.5: {}
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
@ -6054,16 +6014,12 @@ snapshots:
lodash.defaults@4.2.0: {}
lodash.get@4.4.2: {}
lodash.includes@4.3.0: {}
lodash.isarguments@3.1.0: {}
lodash.isboolean@3.0.3: {}
lodash.isequal@4.5.0: {}
lodash.isfinite@3.3.2: {}
lodash.isinteger@4.0.4: {}
@ -6078,10 +6034,6 @@ snapshots:
lodash@4.18.1: {}
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
lru-cache@11.3.5: {}
luxon@3.7.2: {}
@ -6408,12 +6360,6 @@ snapshots:
dependencies:
asap: 2.0.6
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@ -6529,23 +6475,11 @@ snapshots:
iconv-lite: 0.7.2
unpipe: 1.0.0
react-ace@12.0.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies:
ace-builds: 1.44.0
diff-match-patch: 1.0.5
lodash.get: 4.4.2
lodash.isequal: 4.5.0
prop-types: 15.8.1
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
react-dom@19.2.5(react@19.2.5):
dependencies:
react: 19.2.5
scheduler: 0.27.0
react-is@16.13.1: {}
react-is@17.0.2: {}
react-router-dom@7.14.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5):