diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..932a2f7e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,127 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Is + +A **Grafana App Plugin** (`type: "app"`) that integrates OpenNMS® Horizon™/Meridian™ with Grafana 12.x for monitoring dashboards. It includes 3 data sources, 5 custom panels, and bundled dashboards. The `opennms` npm library handles all REST API communication with OpenNMS. + +## Commands + +```bash +# Development +npm run dev # One-time development build +npm run watch # Watch mode (webpack -w) +npm run server # Start Grafana via docker-compose + +# Production +npm run build # Production webpack build +npm run typecheck # TypeScript type checking (tsc --noEmit) + +# Testing +npm test # Run all Jest tests +npm run test:watch # Watch mode (changed files only) +npx jest src/test/react/function_formatter.spec.ts # Single test file +npx jest --testNamePattern="parenthesize" # Tests matching pattern + +# Linting +npm run lint # ESLint +npm run lint:fix # Auto-fix ESLint issues + +# E2E +npm run e2e # Playwright tests +``` + +Tests live in `src/test/react/*.spec.ts`. + +## Architecture + +### Plugin Structure + +``` +src/ + datasources/ + entity-ds/ # Alarms, nodes, IP/SNMP interfaces, outages, services + perf-ds/ # Time-series performance metrics + flow-ds/ # NetFlow v5/v9, IPFIX, sFlow + panels/ + alarm-table/ # Interactive alarm management table + alarm-histogram/ + filter-panel/ # Global dashboard filter (uses localStorage for cross-panel state) + flow-histogram/ + dashboard-convert/ + components/ # Root App and AppConfig components + lib/ # Shared utilities + hooks/ # React hooks + dashboards/ # Bundled JSON dashboard definitions +``` + +### OpenNMS Client Layer + +Each datasource instantiates two request objects in its constructor: +- **`ClientDelegate`** (`src/lib/client_delegate.ts`) — wraps the `opennms.Client` with `Rest.GrafanaHTTP`, handles auth decoding, timeouts. Used for structured model queries (nodes, alarms, etc.) +- **`SimpleOpenNMSRequest`** (`src/lib/simpleRequest.ts`) — thin wrapper around `getBackendSrv()` for direct REST calls (flows, resources, etc.) + +### Data Source Pattern + +Each datasource (e.g., `perf-ds`) has: +- `*DataSource.ts` — extends `DataSourceApi`, implements `query()` and `testDatasource()` +- `*QueryEditor.tsx` — query builder UI +- `*ConfigEditor.tsx` — datasource settings UI +- `queries/` — query building logic separated from the datasource class +- `types.ts` — TypeScript interfaces for the datasource + +### Filter Panel / Entity DS Cross-Panel State + +The Filter Panel stores active filters in **localStorage**. The Entity DS reads these in `query()` via `loadFilterEditorData()` and merges them with the query's own filters using `mergeFilterPanelFilters()`. The dashboard UID is used as the storage key. + +## Key Conventions + +### Critical: `opennms` Model Objects and `toJSON()` + +**Never** pass `OnmsNode[]`, `OnmsEnum`, or other `opennms` model objects directly to Grafana `SelectableValue` components. Grafana uses `json-source-map` to diff panel state; it expects `toJSON()` to return a `String`, but `opennms` models return objects — causing runtime `TypeError`. + +Always convert to plain objects: +```typescript +const selectableValues = nodes.map(n => ({ + id: n.id, + label: n.label, + value: { id: n.id, label: n.label } +})) +``` + +### Config Extension Pattern + +Do **not** modify files in `.config/`. Override at the root level: +- ESLint → `eslint.config.mjs` +- TypeScript → `tsconfig.json` +- Jest → `jest.config.js` +- Webpack → `webpack.config.ts` (merges with `.config/webpack/webpack.config`) + +### Webpack: Help README Copying + +`webpack.config.ts` copies `datasources/*/help-README.md` → `README.md` in `dist/`. The `help-README.md` files are the end-user-facing docs shown in Grafana's "?" tooltip; the top-level `README.md` is developer-facing. + +### Jest: ESM Transform + +The `opennms` package is ESM and must be included in the transform list: +```javascript +transformIgnorePatterns: [nodeModulesToTransform([...grafanaESModules, 'opennms'])] +``` + +### Security: `npm overrides` + +Transitive dependency CVEs are fixed via `overrides` in `package.json`. To fix a new transient dep vulnerability, add an entry under `overrides`, delete `package-lock.json`, and re-run `npm install`. Run `osv-scanner -L package-lock.json` to check. + +## CI/CD Notes + +- CI runs `@grafana/plugin-validator` with `grafana-plugin-validator-config.yaml` +- `osv-scanner` checks CVEs in `package-lock.json`; to temporarily disable: set `osv-scanner.enabled: false` in the config yaml (revert before production builds) +- Build artifacts are RPM/DEB/ZIP via `makerpm.js`, `makedeb.js`, `makezip.js` +- `makerpm.js` has `const isDebug = false` — set `true` for CircleCI debugging + +## Support Matrix + +- **Grafana**: 12.0.0+ +- **OpenNMS**: Horizon 33+ or Meridian 2024+ +- **Node.js**: 22.x (>=22 <25) diff --git a/package-lock.json b/package-lock.json index e17a3e46..8bcd8852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,11 @@ "license": "MIT", "dependencies": { "@emotion/css": "^11.13.5", - "@grafana/data": "^12.3.3", - "@grafana/i18n": "^12.3.3", - "@grafana/runtime": "^12.3.3", - "@grafana/schema": "^12.3.3", - "@grafana/ui": "^12.3.3", + "@grafana/data": "^12.4.0", + "@grafana/i18n": "^12.4.0", + "@grafana/runtime": "^12.4.0", + "@grafana/schema": "^12.4.0", + "@grafana/ui": "^12.4.0", "async": "^3.2.3", "flot": "^0.8.3", "flot-axislabels": "https://github.com/j-white/flot-axislabels#master", @@ -33,13 +33,13 @@ "@antora/site-generator": "^3.1.14", "@antora/site-generator-default": "^3.1.12", "@babel/core": "^7.28.3", - "@grafana/e2e-selectors": "^12.3.3", + "@grafana/e2e-selectors": "^12.4.0", "@grafana/eslint-config": "^8.2.0", - "@grafana/plugin-e2e": "^2.2.3", + "@grafana/plugin-e2e": "^3.4.0", "@grafana/tsconfig": "^2.0.1", "@opennms/style": "github:OpenNMS/opennms-style#v0.4.0", "@playwright/test": "^1.56.1", - "@stylistic/eslint-plugin-ts": "^2.13.0", + "@stylistic/eslint-plugin-ts": "^4.4.1", "@swc/core": "^1.15.13", "@swc/helpers": "^0.5.19", "@swc/jest": "^0.2.39", @@ -49,7 +49,7 @@ "@types/grafana": "github:CorpGlory/types-grafana", "@types/jest": "^29.5.14", "@types/jquery": "^3.5.33", - "@types/node": "^20.19.23", + "@types/node": "^22.19.13", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.2", "@types/react-router-dom": "^5.3.3", @@ -92,7 +92,7 @@ "which": "^4.0.0" }, "engines": { - "node": ">=22 <23" + "node": ">=22 <25" } }, "node_modules/@adobe/css-tools": { @@ -369,6 +369,18 @@ "yarn": ">=1.1.0" } }, + "node_modules/@axe-core/playwright": { + "version": "4.11.1", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "axe-core": "~4.11.1" + }, + "peerDependencies": { + "playwright-core": ">= 1.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "license": "MIT", @@ -1316,20 +1328,32 @@ } }, "node_modules/@grafana/plugin-e2e": { - "version": "2.2.3", + "version": "3.4.1", "dev": true, "license": "Apache-2.0", "dependencies": { - "@grafana/e2e-selectors": "^12.2.0-255920", + "@grafana/e2e-selectors": "13.0.0-22358195095", "semver": "^7.5.4", "uuid": "^13.0.0", "yaml": "^2.3.4" }, "engines": { - "node": ">=18 <=22" + "node": ">=20 <=24" }, "peerDependencies": { - "@playwright/test": "^1.52.0" + "@axe-core/playwright": "^4.11.1", + "@playwright/test": "^1.52.0", + "axe-core": "^4.11.1" + } + }, + "node_modules/@grafana/plugin-e2e/node_modules/@grafana/e2e-selectors": { + "version": "13.0.0-22358195095", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "semver": "^7.7.0", + "tslib": "2.8.1", + "typescript": "5.9.2" } }, "node_modules/@grafana/plugin-e2e/node_modules/semver": { @@ -1343,6 +1367,18 @@ "node": ">=10" } }, + "node_modules/@grafana/plugin-e2e/node_modules/typescript": { + "version": "5.9.2", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@grafana/runtime": { "version": "12.4.0", "license": "Apache-2.0", @@ -1521,8 +1557,6 @@ }, "node_modules/@grafana/ui/node_modules/react-router-dom/node_modules/react-router": { "version": "7.13.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", - "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -1613,7 +1647,7 @@ "license": "ISC" }, "node_modules/@internationalized/date": { - "version": "3.11.0", + "version": "3.12.0", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -3286,16 +3320,16 @@ } }, "node_modules/@react-aria/i18n": { - "version": "3.12.15", + "version": "3.12.16", "license": "Apache-2.0", "dependencies": { - "@internationalized/date": "^3.11.0", + "@internationalized/date": "^3.12.0", "@internationalized/message": "^3.1.8", "@internationalized/number": "^3.6.5", "@internationalized/string": "^3.2.7", "@react-aria/ssr": "^3.9.10", - "@react-aria/utils": "^3.33.0", - "@react-types/shared": "^3.33.0", + "@react-aria/utils": "^3.33.1", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3304,13 +3338,13 @@ } }, "node_modules/@react-aria/i18n/node_modules/@react-aria/utils": { - "version": "3.33.0", + "version": "3.33.1", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", - "@react-types/shared": "^3.33.0", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3320,13 +3354,13 @@ } }, "node_modules/@react-aria/interactions": { - "version": "3.27.0", + "version": "3.27.1", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", - "@react-aria/utils": "^3.33.0", + "@react-aria/utils": "^3.33.1", "@react-stately/flags": "^3.1.2", - "@react-types/shared": "^3.33.0", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3335,13 +3369,13 @@ } }, "node_modules/@react-aria/interactions/node_modules/@react-aria/utils": { - "version": "3.33.0", + "version": "3.33.1", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", - "@react-types/shared": "^3.33.0", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3401,12 +3435,12 @@ } }, "node_modules/@react-aria/visually-hidden": { - "version": "3.8.30", + "version": "3.8.31", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.27.0", - "@react-aria/utils": "^3.33.0", - "@react-types/shared": "^3.33.0", + "@react-aria/interactions": "^3.27.1", + "@react-aria/utils": "^3.33.1", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3415,13 +3449,13 @@ } }, "node_modules/@react-aria/visually-hidden/node_modules/@react-aria/utils": { - "version": "3.33.0", + "version": "3.33.1", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", - "@react-types/shared": "^3.33.0", + "@react-types/shared": "^3.33.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3438,11 +3472,11 @@ } }, "node_modules/@react-stately/overlays": { - "version": "3.6.22", + "version": "3.6.23", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.11.0", - "@react-types/overlays": "^3.9.3", + "@react-types/overlays": "^3.9.4", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3460,38 +3494,38 @@ } }, "node_modules/@react-types/button": { - "version": "3.15.0", + "version": "3.15.1", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.33.0" + "@react-types/shared": "^3.33.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/dialog": { - "version": "3.5.23", + "version": "3.5.24", "license": "Apache-2.0", "dependencies": { - "@react-types/overlays": "^3.9.3", - "@react-types/shared": "^3.33.0" + "@react-types/overlays": "^3.9.4", + "@react-types/shared": "^3.33.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/overlays": { - "version": "3.9.3", + "version": "3.9.4", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.33.0" + "@react-types/shared": "^3.33.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/shared": { - "version": "3.33.0", + "version": "3.33.1", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -3526,11 +3560,11 @@ } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "2.13.0", + "version": "4.4.1", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.13.0", + "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0" }, @@ -3538,7 +3572,7 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": ">=8.40.0" + "eslint": ">=9.0.0" } }, "node_modules/@swc/core": { @@ -3944,7 +3978,7 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.35", + "version": "22.19.13", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -4584,42 +4618,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, @@ -4971,6 +4969,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.11.1", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/axios": { "version": "1.13.6", "license": "MIT", @@ -7419,6 +7426,8 @@ }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", + "integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==", "dev": true, "license": "MIT", "dependencies": { @@ -7443,31 +7452,10 @@ "webpack": "^5.11.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "8.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7477,6 +7465,8 @@ }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "license": "MIT", "dependencies": { @@ -7502,6 +7492,8 @@ }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7513,13 +7505,10 @@ "node": ">=12" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -7529,25 +7518,10 @@ "node": "*" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -7603,6 +7577,18 @@ "dev": true, "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "license": "MIT", @@ -8089,7 +8075,7 @@ "license": "BSD-3-Clause" }, "node_modules/i18next": { - "version": "25.8.13", + "version": "25.8.14", "funding": [ { "type": "individual", @@ -8199,7 +8185,9 @@ } }, "node_modules/immutable": { - "version": "5.1.4", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "license": "MIT" }, "node_modules/import-fresh": { @@ -12397,7 +12385,7 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", + "version": "2.0.36", "dev": true, "license": "MIT" }, @@ -13042,6 +13030,18 @@ "node": ">=18" } }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/portfinder": { "version": "1.0.38", "dev": true, @@ -13688,8 +13688,6 @@ }, "node_modules/react-router": { "version": "7.13.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", - "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -14399,6 +14397,24 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/schema-utils/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/schema-utils/node_modules/ajv-keywords": { "version": "5.1.0", "dev": true, diff --git a/package.json b/package.json index ab9b0d29..d4acbcda 100644 --- a/package.json +++ b/package.json @@ -38,13 +38,13 @@ "@antora/site-generator": "^3.1.14", "@antora/site-generator-default": "^3.1.12", "@babel/core": "^7.28.3", - "@grafana/e2e-selectors": "^12.3.3", + "@grafana/e2e-selectors": "^12.4.0", "@grafana/eslint-config": "^8.2.0", - "@grafana/plugin-e2e": "^2.2.3", + "@grafana/plugin-e2e": "^3.4.0", "@grafana/tsconfig": "^2.0.1", "@opennms/style": "github:OpenNMS/opennms-style#v0.4.0", "@playwright/test": "^1.56.1", - "@stylistic/eslint-plugin-ts": "^2.13.0", + "@stylistic/eslint-plugin-ts": "^4.4.1", "@swc/core": "^1.15.13", "@swc/helpers": "^0.5.19", "@swc/jest": "^0.2.39", @@ -54,7 +54,7 @@ "@types/grafana": "github:CorpGlory/types-grafana", "@types/jest": "^29.5.14", "@types/jquery": "^3.5.33", - "@types/node": "^20.19.23", + "@types/node": "^22.19.13", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.2", "@types/react-router-dom": "^5.3.3", @@ -98,11 +98,11 @@ }, "dependencies": { "@emotion/css": "^11.13.5", - "@grafana/data": "^12.3.3", - "@grafana/i18n": "^12.3.3", - "@grafana/runtime": "^12.3.3", - "@grafana/schema": "^12.3.3", - "@grafana/ui": "^12.3.3", + "@grafana/data": "^12.4.0", + "@grafana/i18n": "^12.4.0", + "@grafana/runtime": "^12.4.0", + "@grafana/schema": "^12.4.0", + "@grafana/ui": "^12.4.0", "async": "^3.2.3", "flot": "^0.8.3", "flot-axislabels": "https://github.com/j-white/flot-axislabels#master", @@ -117,7 +117,7 @@ "react-router-dom": "^7.13.0" }, "engines": { - "node": ">=22 <23" + "node": ">=22 <25" }, "overrides": { "@antora/cli": { @@ -134,6 +134,7 @@ "minimatch": "^3.1.4" }, "@grafana/ui": { + "immutable": "^5.1.5", "react": "~18.3.1", "react-dom": "~18.3.1", "react-router": "^7.13.0" @@ -158,7 +159,9 @@ }, "fork-ts-checker-webpack-plugin": { "ajv": "^8.18.0", - "ajv-formats": "^2.1.1", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0", + "schema-utils": "^4.3.3", "minimatch": "^3.1.4" }, "glob": {