From 6ca8a6bcb384562fe0246c205b792967148854b1 Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Fri, 24 Oct 2025 13:06:45 +0200 Subject: [PATCH 1/7] add grafana types based on test fixtures --- src/grafana.ts | 252 ++++++++++++++++++ .../alert/{alert.mock.js => alert.mock.ts} | 6 +- ...h_condition.js => alert_with_condition.ts} | 6 +- .../{simple_alert.js => simple_alert.ts} | 6 +- ...imple_condition.js => simple_condition.ts} | 6 +- ...rride_graphite.js => override_graphite.ts} | 6 +- ...{simple_graphite.js => simple_graphite.ts} | 6 +- .../{external_link.js => external_link.ts} | 6 +- ...ide_dashboard.js => override_dashboard.ts} | 7 +- .../{override_row.js => override_row.ts} | 6 +- ...raph_with_alert.js => graph_with_alert.ts} | 6 +- ...ard_list.js => override_dashboard_list.ts} | 6 +- .../{override_graph.js => override_graph.ts} | 6 +- ...e_singlestat.js => override_singlestat.ts} | 6 +- .../{override_table.js => override_table.ts} | 6 +- .../{override_text.js => override_text.ts} | 6 +- ...board_list.js => simple_dashboard_list.ts} | 6 +- .../{simple_graph.js => simple_graph.ts} | 6 +- ...ple_singlestat.js => simple_singlestat.ts} | 6 +- .../{simple_table.js => simple_table.ts} | 6 +- .../panels/{simple_text.js => simple_text.ts} | 6 +- ...imple_dashboard.js => simple_dashboard.ts} | 7 +- .../fixtures/{simple_row.js => simple_row.ts} | 6 +- ...{override_custom.js => override_custom.ts} | 6 +- ...value.js => override_custom_text_value.ts} | 6 +- .../{override_query.js => override_query.ts} | 6 +- .../{simple_custom.js => simple_custom.ts} | 6 +- .../{simple_query.js => simple_query.ts} | 6 +- test/panels/dashboard_list.test.js | 4 +- test/panels/graph.test.js | 8 +- test/panels/singlestat.test.js | 4 +- test/panels/table.test.js | 4 +- test/panels/text.test.js | 4 +- test/row.test.js | 4 +- 34 files changed, 390 insertions(+), 54 deletions(-) create mode 100644 src/grafana.ts rename test/fixtures/alert/{alert.mock.js => alert.mock.ts} (59%) rename test/fixtures/alert/{alert_with_condition.js => alert_with_condition.ts} (83%) rename test/fixtures/alert/{simple_alert.js => simple_alert.ts} (67%) rename test/fixtures/alert/{simple_condition.js => simple_condition.ts} (65%) rename test/fixtures/annotations/{override_graphite.js => override_graphite.ts} (88%) rename test/fixtures/annotations/{simple_graphite.js => simple_graphite.ts} (88%) rename test/fixtures/{external_link.js => external_link.ts} (90%) rename test/fixtures/{override_dashboard.js => override_dashboard.ts} (96%) rename test/fixtures/{override_row.js => override_row.ts} (92%) rename test/fixtures/panels/{graph_with_alert.js => graph_with_alert.ts} (95%) rename test/fixtures/panels/{override_dashboard_list.js => override_dashboard_list.ts} (88%) rename test/fixtures/panels/{override_graph.js => override_graph.ts} (94%) rename test/fixtures/panels/{override_singlestat.js => override_singlestat.ts} (92%) rename test/fixtures/panels/{override_table.js => override_table.ts} (93%) rename test/fixtures/panels/{override_text.js => override_text.ts} (90%) rename test/fixtures/panels/{simple_dashboard_list.js => simple_dashboard_list.ts} (88%) rename test/fixtures/panels/{simple_graph.js => simple_graph.ts} (94%) rename test/fixtures/panels/{simple_singlestat.js => simple_singlestat.ts} (92%) rename test/fixtures/panels/{simple_table.js => simple_table.ts} (93%) rename test/fixtures/panels/{simple_text.js => simple_text.ts} (90%) rename test/fixtures/{simple_dashboard.js => simple_dashboard.ts} (92%) rename test/fixtures/{simple_row.js => simple_row.ts} (92%) rename test/fixtures/templates/{override_custom.js => override_custom.ts} (90%) rename test/fixtures/templates/{override_custom_text_value.js => override_custom_text_value.ts} (90%) rename test/fixtures/templates/{override_query.js => override_query.ts} (90%) rename test/fixtures/templates/{simple_custom.js => simple_custom.ts} (90%) rename test/fixtures/templates/{simple_query.js => simple_query.ts} (90%) diff --git a/src/grafana.ts b/src/grafana.ts new file mode 100644 index 0000000..9ec17ba --- /dev/null +++ b/src/grafana.ts @@ -0,0 +1,252 @@ +interface GrafanaSharedProps { + // allowing to add properties undeclared in the types below, as those are incomplete + [k: string]: any; +} + +export interface GrafanaQueryTemplate extends GrafanaSharedProps { + type: string; + query: string; + name: string; + datasource: string; + options: any[]; + current: object; + includeAll: boolean; + allFormat: string; + allValue: null | string; + refresh: boolean; + multi: boolean; +} + +export interface GrafanaCustomTemplate extends GrafanaSharedProps { + name: string; + type: string; + options: any[]; + datasource: null; + refresh: number; + refresh_on_load: boolean; + includeAll: boolean; + allValue: string; + allFormat: string; + query: null | string; + current: object; +} + +export interface GrafanaGraphiteAnnotation extends GrafanaSharedProps { + name: string; + datasource: string; + showLine: boolean; + iconColor: string; + lineColor: string; + iconSize: number; + enable: boolean; + target: string; +} + +export interface GrafanaDashboardListPanel extends GrafanaSharedProps { + title: string; + error: boolean; + span: number; + editable: boolean; + type: 'dashlist'; + isNew: boolean; + id: number; + mode: string; + query: string; + limit: number; + tags: any[]; + links: any[]; +} + +export interface GrafanaCondition extends GrafanaSharedProps { + type: string; + query: { params: string[] }; + reducer: { type: string; params: any[] }; + evaluator: { type: string; params: any[] }; + operator: { type: string }; +} + +export interface GrafanaAlert extends GrafanaSharedProps { + name: string; + conditions: GrafanaCondition[]; + for: string; + frequency: string; + message: string; + notifications: any[]; + executionErrorState: string; + noDataState: string; + alertRuleTags: object; + handler: number; +} + +export interface GrafanaGraphPanel extends GrafanaSharedProps { + alert?: GrafanaAlert; + aliasColors: any; + bars: boolean; + editable: boolean; + error: boolean; + fill: number; + grid: { + leftMax: null; + leftMin: null; + rightMax: null; + rightMin: null; + threshold1: null; + threshold1Color: string; + threshold2: null; + threshold2Color: string; + }; + id: number; + legend: { + avg: boolean; + current: boolean; + max: boolean; + min: boolean; + show: boolean; + total: boolean; + values: boolean; + }; + lines: boolean; + linewidth: number; + links: any[]; + nullPointMode: string; + percentage: boolean; + pointradius: number; + points: boolean; + renderer: string; + seriesOverrides: any[]; + span: number; + stack: boolean; + steppedLine: boolean; + targets: any[]; + title: string; + tooltip: { shared: boolean; value_type: string }; + type: 'graph'; + 'x-axis': boolean; + 'y-axis': boolean; + y_formats: string[]; + datasource: string; +} + +export interface GrafanaSingleStatPanel extends GrafanaSharedProps { + cacheTimeout: null; + colorBackground: boolean; + colorValue: boolean; + colors: string[]; + editable: boolean; + error: boolean; + format: string; + id: number; + interval: null; + links: any[]; + maxDataPoints: number; + nullPointMode: string; + nullText: null; + postfix: string; + postfixFontSize: string; + prefix: string; + prefixFontSize: string; + span: number; + sparkline: { + fillColor: string; + full: boolean; + lineColor: string; + show: boolean; + }; + targets: any[]; + thresholds: string; + title: string; + type: 'singlestat'; + valueFontSize: string; + valueMaps: { op: string; text: string; value: string }[]; + valueName: string; + datasource: string; +} + +export interface GrafanaTablePanel extends GrafanaSharedProps { + title: string; + error: boolean; + span: number; + editable: boolean; + type: 'table'; + isNew: boolean; + id: number; + // todo: should this be required? + datasource?: string; + styles: ( + | { type: 'date'; pattern: string; dateFormat: string } + | { + unit: string; + type: 'number'; + decimals: number; + colors: string[]; + colorMode: null; + pattern: string; + thresholds: any[]; + } + )[]; + targets: any[]; + transform: string; + pageSize: null; + showHeader: boolean; + columns: { text: string; value: string }[]; + scroll: boolean; + fontSize: string; + sort: { col: number; desc: boolean }; + links: any[]; +} + +export interface GrafanaTextPanel extends GrafanaSharedProps { + title: string; + error: boolean; + span: number; + editable: boolean; + type: 'text'; + id: number; + mode: string; + content: string; + style: any; + links: any[]; +} + +export interface GrafanaRow extends GrafanaSharedProps { + title: string; + showTitle: boolean; + height: string; + editable: boolean; + collapse: boolean; + panels: any[]; +} + +export interface GrafanaExternalLink extends GrafanaSharedProps { + title: string; + tooltip: string; + url: string; + tags: any[]; + icon: string; + targetBlank: boolean; + type: string; + includeVars: boolean; + keepTime: boolean; +} + +export interface GrafanaDashboard extends GrafanaSharedProps { + id: null; + title: string; + originalTitle: string; + tags: any[]; + style: string; + timezone: string; + editable: boolean; + hideControls: boolean; + sharedCrosshair: boolean; + refresh: boolean | string; + schemaVersion: number; + hideAllLegends: boolean; + rows: GrafanaRow[]; + annotations: { list: any[]; enable: boolean }; + templating: { list: any[]; enable: boolean }; + time: null; + links: GrafanaExternalLink[]; +} + +export {}; diff --git a/test/fixtures/alert/alert.mock.js b/test/fixtures/alert/alert.mock.ts similarity index 59% rename from test/fixtures/alert/alert.mock.js rename to test/fixtures/alert/alert.mock.ts index f0ba15d..06442bf 100644 --- a/test/fixtures/alert/alert.mock.js +++ b/test/fixtures/alert/alert.mock.ts @@ -1,5 +1,5 @@ -const Condition = require('../../../src/alert/condition'); -const Alert = require('../../../src/alert/alert'); +import Condition = require('../../../src/alert/condition'); +import Alert = require('../../../src/alert/alert'); const getAlert = () => { const condition = new Condition() @@ -10,4 +10,4 @@ const getAlert = () => { return new Alert().addCondition(condition); }; -module.exports.getAlert = getAlert; +export = { getAlert }; diff --git a/test/fixtures/alert/alert_with_condition.js b/test/fixtures/alert/alert_with_condition.ts similarity index 83% rename from test/fixtures/alert/alert_with_condition.js rename to test/fixtures/alert/alert_with_condition.ts index 52c55a2..c5ca3bd 100644 --- a/test/fixtures/alert/alert_with_condition.js +++ b/test/fixtures/alert/alert_with_condition.ts @@ -1,4 +1,6 @@ -module.exports = { +import { GrafanaAlert } from '../../../src/grafana'; + +const alertWithCondition: GrafanaAlert = { name: 'Panel Title alert', conditions: [ { @@ -28,3 +30,5 @@ module.exports = { alertRuleTags: {}, handler: 1, }; + +export = alertWithCondition; diff --git a/test/fixtures/alert/simple_alert.js b/test/fixtures/alert/simple_alert.ts similarity index 67% rename from test/fixtures/alert/simple_alert.js rename to test/fixtures/alert/simple_alert.ts index 17f01f5..cc5485a 100644 --- a/test/fixtures/alert/simple_alert.js +++ b/test/fixtures/alert/simple_alert.ts @@ -1,4 +1,6 @@ -module.exports = { +import { GrafanaAlert } from '../../../src/grafana'; + +const simpleAlert: GrafanaAlert = { name: 'Panel Title alert', for: '15m', frequency: '5m', @@ -10,3 +12,5 @@ module.exports = { alertRuleTags: {}, handler: 1, }; + +export = simpleAlert; diff --git a/test/fixtures/alert/simple_condition.js b/test/fixtures/alert/simple_condition.ts similarity index 65% rename from test/fixtures/alert/simple_condition.js rename to test/fixtures/alert/simple_condition.ts index ee06feb..d4a5381 100644 --- a/test/fixtures/alert/simple_condition.js +++ b/test/fixtures/alert/simple_condition.ts @@ -1,4 +1,6 @@ -module.exports = { +import { GrafanaCondition } from '../../../src/grafana'; + +const simpleCondition: GrafanaCondition = { type: 'query', query: { params: ['A', '5m', 'now'], @@ -15,3 +17,5 @@ module.exports = { type: 'and', }, }; + +export = simpleCondition; diff --git a/test/fixtures/annotations/override_graphite.js b/test/fixtures/annotations/override_graphite.ts similarity index 88% rename from test/fixtures/annotations/override_graphite.js rename to test/fixtures/annotations/override_graphite.ts index 7b06041..a471e52 100644 --- a/test/fixtures/annotations/override_graphite.js +++ b/test/fixtures/annotations/override_graphite.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaGraphiteAnnotation } from '../../../src/grafana'; -module.exports = { +const overrideGraphiteAnnotation: GrafanaGraphiteAnnotation = { name: 'custom name', datasource: 'custom datasource', showLine: false, @@ -31,3 +31,5 @@ module.exports = { target: 'custom.target', arbitraryProperty: 'foo', }; + +export = overrideGraphiteAnnotation; diff --git a/test/fixtures/annotations/simple_graphite.js b/test/fixtures/annotations/simple_graphite.ts similarity index 88% rename from test/fixtures/annotations/simple_graphite.js rename to test/fixtures/annotations/simple_graphite.ts index 2448ad1..044e197 100644 --- a/test/fixtures/annotations/simple_graphite.js +++ b/test/fixtures/annotations/simple_graphite.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaGraphiteAnnotation } from '../../../src/grafana'; -module.exports = { +const simpleGraphiteAnnotation: GrafanaGraphiteAnnotation = { name: 'name', datasource: 'graphite', showLine: true, @@ -30,3 +30,5 @@ module.exports = { enable: true, target: 'target', }; + +export = simpleGraphiteAnnotation; diff --git a/test/fixtures/external_link.js b/test/fixtures/external_link.ts similarity index 90% rename from test/fixtures/external_link.js rename to test/fixtures/external_link.ts index 6b31618..012d7ed 100644 --- a/test/fixtures/external_link.js +++ b/test/fixtures/external_link.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaExternalLink } from '../../src/grafana'; + +const externalLink: GrafanaExternalLink = { title: 'Uber Home Page', tooltip: '', url: 'www.uber.com', @@ -29,3 +31,5 @@ module.exports = { includeVars: false, keepTime: false, }; + +export = externalLink; diff --git a/test/fixtures/override_dashboard.js b/test/fixtures/override_dashboard.ts similarity index 96% rename from test/fixtures/override_dashboard.js rename to test/fixtures/override_dashboard.ts index 872cb2f..01c227f 100644 --- a/test/fixtures/override_dashboard.js +++ b/test/fixtures/override_dashboard.ts @@ -18,8 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; -module.exports = { +import type { GrafanaDashboard } from '../../src/grafana'; + +const overrideDashboard: GrafanaDashboard = { id: null, title: 'custom title', originalTitle: 'Generated Dashboard', @@ -118,3 +119,5 @@ module.exports = { time: null, links: [], }; + +export = overrideDashboard; diff --git a/test/fixtures/override_row.js b/test/fixtures/override_row.ts similarity index 92% rename from test/fixtures/override_row.js rename to test/fixtures/override_row.ts index bb4cbce..d13f23a 100644 --- a/test/fixtures/override_row.js +++ b/test/fixtures/override_row.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import { GrafanaRow } from '../../src/grafana'; + +const overrideRow: GrafanaRow = { title: 'My Row', height: '1000px', editable: false, @@ -32,3 +34,5 @@ module.exports = { }, ], }; + +export = overrideRow; diff --git a/test/fixtures/panels/graph_with_alert.js b/test/fixtures/panels/graph_with_alert.ts similarity index 95% rename from test/fixtures/panels/graph_with_alert.js rename to test/fixtures/panels/graph_with_alert.ts index edc84bf..baeadae 100644 --- a/test/fixtures/panels/graph_with_alert.js +++ b/test/fixtures/panels/graph_with_alert.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaGraphPanel } from '../../../src/grafana'; + +const graphWithAlertPanel: GrafanaGraphPanel = { alert: { name: 'Panel Title alert', conditions: [ @@ -98,3 +100,5 @@ module.exports = { y_formats: ['short', 'short'], datasource: 'graphite', }; + +export = graphWithAlertPanel; diff --git a/test/fixtures/panels/override_dashboard_list.js b/test/fixtures/panels/override_dashboard_list.ts similarity index 88% rename from test/fixtures/panels/override_dashboard_list.js rename to test/fixtures/panels/override_dashboard_list.ts index d0b531d..2580872 100644 --- a/test/fixtures/panels/override_dashboard_list.js +++ b/test/fixtures/panels/override_dashboard_list.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaDashboardListPanel } from '../../../src/grafana'; + +const overrideDashboardListPanel: GrafanaDashboardListPanel = { title: 'dashboard list', error: false, span: 3, @@ -32,3 +34,5 @@ module.exports = { tags: [], links: [], }; + +export = overrideDashboardListPanel; diff --git a/test/fixtures/panels/override_graph.js b/test/fixtures/panels/override_graph.ts similarity index 94% rename from test/fixtures/panels/override_graph.js rename to test/fixtures/panels/override_graph.ts index 06dfd5e..79608ea 100644 --- a/test/fixtures/panels/override_graph.js +++ b/test/fixtures/panels/override_graph.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaGraphPanel } from '../../../src/grafana'; -module.exports = { +const overrideGraphPanel: GrafanaGraphPanel = { aliasColors: {}, bars: false, editable: true, @@ -77,3 +77,5 @@ module.exports = { datasource: 'M3', arbitraryProperty: 'foo', }; + +export = overrideGraphPanel; diff --git a/test/fixtures/panels/override_singlestat.js b/test/fixtures/panels/override_singlestat.ts similarity index 92% rename from test/fixtures/panels/override_singlestat.js rename to test/fixtures/panels/override_singlestat.ts index 5464e9e..7921a30 100644 --- a/test/fixtures/panels/override_singlestat.js +++ b/test/fixtures/panels/override_singlestat.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaSingleStatPanel } from '../../../src/grafana'; -module.exports = { +const overrideSingleStatPanel: GrafanaSingleStatPanel = { cacheTimeout: null, colorBackground: false, colorValue: false, @@ -69,3 +69,5 @@ module.exports = { datasource: 'M3', arbitraryProperty: 'foo', }; + +export = overrideSingleStatPanel; diff --git a/test/fixtures/panels/override_table.js b/test/fixtures/panels/override_table.ts similarity index 93% rename from test/fixtures/panels/override_table.js rename to test/fixtures/panels/override_table.ts index 01e76fa..bda8828 100644 --- a/test/fixtures/panels/override_table.js +++ b/test/fixtures/panels/override_table.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaTablePanel } from '../../../src/grafana'; -module.exports = { +const overrideTablePanel: GrafanaTablePanel = { title: 'custom title', error: false, span: 4, @@ -73,3 +73,5 @@ module.exports = { links: [], arbitraryProperty: 'foo', }; + +export = overrideTablePanel; diff --git a/test/fixtures/panels/override_text.js b/test/fixtures/panels/override_text.ts similarity index 90% rename from test/fixtures/panels/override_text.js rename to test/fixtures/panels/override_text.ts index 54b3650..2591b33 100644 --- a/test/fixtures/panels/override_text.js +++ b/test/fixtures/panels/override_text.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import { GrafanaTextPanel } from '../../../src/grafana'; + +const overrideTextPanel: GrafanaTextPanel = { title: '', error: false, span: 4, @@ -32,3 +34,5 @@ module.exports = { height: '100px', transparent: true, }; + +export = overrideTextPanel; diff --git a/test/fixtures/panels/simple_dashboard_list.js b/test/fixtures/panels/simple_dashboard_list.ts similarity index 88% rename from test/fixtures/panels/simple_dashboard_list.js rename to test/fixtures/panels/simple_dashboard_list.ts index 3981be1..4103812 100644 --- a/test/fixtures/panels/simple_dashboard_list.js +++ b/test/fixtures/panels/simple_dashboard_list.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaDashboardListPanel } from '../../../src/grafana'; + +const simpleDashboardListPanel: GrafanaDashboardListPanel = { title: 'dashboard list', error: false, span: 3, @@ -32,3 +34,5 @@ module.exports = { tags: [], links: [], }; + +export = simpleDashboardListPanel; diff --git a/test/fixtures/panels/simple_graph.js b/test/fixtures/panels/simple_graph.ts similarity index 94% rename from test/fixtures/panels/simple_graph.js rename to test/fixtures/panels/simple_graph.ts index 046bc1a..52f675e 100644 --- a/test/fixtures/panels/simple_graph.js +++ b/test/fixtures/panels/simple_graph.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaGraphPanel } from '../../../src/grafana'; + +const simpleGraphPanel: GrafanaGraphPanel = { aliasColors: {}, bars: false, editable: true, @@ -68,3 +70,5 @@ module.exports = { y_formats: ['short', 'short'], datasource: 'graphite', }; + +export = simpleGraphPanel; diff --git a/test/fixtures/panels/simple_singlestat.js b/test/fixtures/panels/simple_singlestat.ts similarity index 92% rename from test/fixtures/panels/simple_singlestat.js rename to test/fixtures/panels/simple_singlestat.ts index 854130e..f8bd29c 100644 --- a/test/fixtures/panels/simple_singlestat.js +++ b/test/fixtures/panels/simple_singlestat.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaSingleStatPanel } from '../../../src/grafana'; + +const simpleSingleStatPanel: GrafanaSingleStatPanel = { cacheTimeout: null, colorBackground: false, colorValue: false, @@ -62,3 +64,5 @@ module.exports = { valueName: 'current', datasource: 'graphite', }; + +export = simpleSingleStatPanel; diff --git a/test/fixtures/panels/simple_table.js b/test/fixtures/panels/simple_table.ts similarity index 93% rename from test/fixtures/panels/simple_table.js rename to test/fixtures/panels/simple_table.ts index a9ee94b..152d21e 100644 --- a/test/fixtures/panels/simple_table.js +++ b/test/fixtures/panels/simple_table.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaTablePanel } from '../../../src/grafana'; + +const simpleTablePanel: GrafanaTablePanel = { title: 'Panel Title', error: false, span: 12, @@ -64,3 +66,5 @@ module.exports = { }, links: [], }; + +export = simpleTablePanel; diff --git a/test/fixtures/panels/simple_text.js b/test/fixtures/panels/simple_text.ts similarity index 90% rename from test/fixtures/panels/simple_text.js rename to test/fixtures/panels/simple_text.ts index ebc6f41..deae47c 100644 --- a/test/fixtures/panels/simple_text.js +++ b/test/fixtures/panels/simple_text.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import { GrafanaTextPanel } from '../../../src/grafana'; + +const simpleTextPanel: GrafanaTextPanel = { title: '', error: false, span: 12, @@ -30,3 +32,5 @@ module.exports = { style: {}, links: [], }; + +export = simpleTextPanel; diff --git a/test/fixtures/simple_dashboard.js b/test/fixtures/simple_dashboard.ts similarity index 92% rename from test/fixtures/simple_dashboard.js rename to test/fixtures/simple_dashboard.ts index 14da4d1..661e713 100644 --- a/test/fixtures/simple_dashboard.js +++ b/test/fixtures/simple_dashboard.ts @@ -18,8 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; -module.exports = { +import type { GrafanaDashboard } from '../../src/grafana'; + +const simpleDashboard: GrafanaDashboard = { id: null, title: 'Generated Grafana Dashboard', originalTitle: 'Generated Dashboard', @@ -38,3 +39,5 @@ module.exports = { time: null, links: [], }; + +export = simpleDashboard; diff --git a/test/fixtures/simple_row.js b/test/fixtures/simple_row.ts similarity index 92% rename from test/fixtures/simple_row.js rename to test/fixtures/simple_row.ts index a248015..63b0357 100644 --- a/test/fixtures/simple_row.js +++ b/test/fixtures/simple_row.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaRow } from '../../src/grafana'; + +const simpleRow: GrafanaRow = { title: 'New row', showTitle: true, height: '250px', @@ -26,3 +28,5 @@ module.exports = { collapse: false, panels: [], }; + +export = simpleRow; diff --git a/test/fixtures/templates/override_custom.js b/test/fixtures/templates/override_custom.ts similarity index 90% rename from test/fixtures/templates/override_custom.js rename to test/fixtures/templates/override_custom.ts index 483be25..975a086 100644 --- a/test/fixtures/templates/override_custom.js +++ b/test/fixtures/templates/override_custom.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaCustomTemplate } from '../../../src/grafana'; -module.exports = { +const overrideCustomTemplate: GrafanaCustomTemplate = { name: 'custom', type: 'custom', options: [ @@ -46,3 +46,5 @@ module.exports = { }, arbitraryProperty: 'foo', }; + +export = overrideCustomTemplate; diff --git a/test/fixtures/templates/override_custom_text_value.js b/test/fixtures/templates/override_custom_text_value.ts similarity index 90% rename from test/fixtures/templates/override_custom_text_value.js rename to test/fixtures/templates/override_custom_text_value.ts index 7116509..7e86583 100644 --- a/test/fixtures/templates/override_custom_text_value.js +++ b/test/fixtures/templates/override_custom_text_value.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaCustomTemplate } from '../../../src/grafana'; -module.exports = { +const overrideCustomTextValue: GrafanaCustomTemplate = { name: 'custom', type: 'custom', options: [ @@ -42,3 +42,5 @@ module.exports = { }, arbitraryProperty: 'foo', }; + +export = overrideCustomTextValue; diff --git a/test/fixtures/templates/override_query.js b/test/fixtures/templates/override_query.ts similarity index 90% rename from test/fixtures/templates/override_query.js rename to test/fixtures/templates/override_query.ts index bdb068c..84a7b2c 100644 --- a/test/fixtures/templates/override_query.js +++ b/test/fixtures/templates/override_query.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import { GrafanaQueryTemplate } from '../../../src/grafana'; -module.exports = { +const overrideQueryTemplate: GrafanaQueryTemplate = { type: 'query', query: 'stats.*', name: 'template', @@ -33,3 +33,5 @@ module.exports = { refresh: true, multi: true, }; + +export = overrideQueryTemplate; diff --git a/test/fixtures/templates/simple_custom.js b/test/fixtures/templates/simple_custom.ts similarity index 90% rename from test/fixtures/templates/simple_custom.js rename to test/fixtures/templates/simple_custom.ts index 106e6ff..99e2e10 100644 --- a/test/fixtures/templates/simple_custom.js +++ b/test/fixtures/templates/simple_custom.ts @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -module.exports = { +import type { GrafanaCustomTemplate } from '../../../src/grafana'; + +const customTemplate: GrafanaCustomTemplate = { name: 'template', type: 'custom', options: [], @@ -31,3 +33,5 @@ module.exports = { query: null, current: {}, }; + +export = customTemplate; diff --git a/test/fixtures/templates/simple_query.js b/test/fixtures/templates/simple_query.ts similarity index 90% rename from test/fixtures/templates/simple_query.js rename to test/fixtures/templates/simple_query.ts index 1cdc602..95e5aa4 100644 --- a/test/fixtures/templates/simple_query.js +++ b/test/fixtures/templates/simple_query.ts @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -'use strict'; +import type { GrafanaQueryTemplate } from '../../../src/grafana'; -module.exports = { +const simpleQueryTemplate: GrafanaQueryTemplate = { type: 'query', query: 'servers.*', name: 'foo', @@ -33,3 +33,5 @@ module.exports = { refresh: false, multi: false, }; + +export = simpleQueryTemplate; diff --git a/test/panels/dashboard_list.test.js b/test/panels/dashboard_list.test.js index ab517cb..f41b1d9 100644 --- a/test/panels/dashboard_list.test.js +++ b/test/panels/dashboard_list.test.js @@ -22,8 +22,8 @@ var DashboardList = require('../../src/panels/dashboard_list'); -var dashboardList = require('../fixtures/panels/simple_dashboard_list.js'); -var overrideDashboardList = require('../fixtures/panels/override_dashboard_list.js'); +var dashboardList = require('../fixtures/panels/simple_dashboard_list'); +var overrideDashboardList = require('../fixtures/panels/override_dashboard_list'); test('simple DashboardList panel', function () { var graph = new DashboardList(); diff --git a/test/panels/graph.test.js b/test/panels/graph.test.js index 76bf311..b2100a7 100644 --- a/test/panels/graph.test.js +++ b/test/panels/graph.test.js @@ -23,10 +23,10 @@ const Graph = require('../../src/panels/graph'); const getAlert = require('../fixtures/alert/alert.mock').getAlert; -const simpleGraph = require('../fixtures/panels/simple_graph.js'); -const overrideGraph = require('../fixtures/panels/override_graph.js'); -const simpleGraphWithAlert = require('../fixtures/panels/graph_with_alert.js'); -const alertWithCondition = require('../fixtures/alert/alert_with_condition.js'); +const simpleGraph = require('../fixtures/panels/simple_graph'); +const overrideGraph = require('../fixtures/panels/override_graph'); +const simpleGraphWithAlert = require('../fixtures/panels/graph_with_alert'); +const alertWithCondition = require('../fixtures/alert/alert_with_condition'); test('simple graph', () => { const graph = new Graph(); diff --git a/test/panels/singlestat.test.js b/test/panels/singlestat.test.js index ecbee5e..85d9407 100644 --- a/test/panels/singlestat.test.js +++ b/test/panels/singlestat.test.js @@ -22,8 +22,8 @@ var SingleStat = require('../../src/panels/singlestat'); -var simpleSingleStat = require('../fixtures/panels/simple_singlestat.js'); -var overrideSingleStat = require('../fixtures/panels/override_singlestat.js'); +var simpleSingleStat = require('../fixtures/panels/simple_singlestat'); +var overrideSingleStat = require('../fixtures/panels/override_singlestat'); test('simple SingleStat panel', function () { var graph = new SingleStat(); diff --git a/test/panels/table.test.js b/test/panels/table.test.js index bc63037..0f8bd03 100644 --- a/test/panels/table.test.js +++ b/test/panels/table.test.js @@ -22,8 +22,8 @@ var Table = require('../../src/panels/table'); -var simpleTable = require('../fixtures/panels/simple_table.js'); -var overrideTable = require('../fixtures/panels/override_table.js'); +var simpleTable = require('../fixtures/panels/simple_table'); +var overrideTable = require('../fixtures/panels/override_table'); test('simple table', function () { var table = new Table(); diff --git a/test/panels/text.test.js b/test/panels/text.test.js index 6ab95f7..dd6dda6 100644 --- a/test/panels/text.test.js +++ b/test/panels/text.test.js @@ -22,8 +22,8 @@ var Text = require('../../src/panels/text'); -var simpleText = require('../fixtures/panels/simple_text.js'); -var overrideText = require('../fixtures/panels/override_text.js'); +var simpleText = require('../fixtures/panels/simple_text'); +var overrideText = require('../fixtures/panels/override_text'); test('simple Text panel', function () { var graph = new Text(); diff --git a/test/row.test.js b/test/row.test.js index 356d207..c298bc5 100644 --- a/test/row.test.js +++ b/test/row.test.js @@ -22,8 +22,8 @@ var Row = require('../src/row'); -var simpleRow = require('./fixtures/simple_row.js'); -var overrideRow = require('./fixtures/override_row.js'); +var simpleRow = require('./fixtures/simple_row'); +var overrideRow = require('./fixtures/override_row'); var panelData = { foo: 'foo', bar: 'bar', From b42a3ff1c14774ba4c7a17d20ce10b4e03b551d8 Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Fri, 24 Oct 2025 16:02:38 +0200 Subject: [PATCH 2/7] use grafana types --- src/alert/alert.ts | 8 +++++--- src/alert/condition.ts | 7 +++++-- src/annotations/graphite.ts | 3 ++- src/external-link.ts | 6 ++++-- src/panels/dashboard_list.ts | 3 ++- src/panels/graph.ts | 5 +++-- src/panels/singlestat.ts | 5 +++-- src/panels/table.ts | 5 +++-- src/panels/text.ts | 5 +++-- src/row.ts | 3 ++- src/templates/custom.ts | 4 +++- src/templates/query.ts | 4 +++- test/dashboard.test.js | 1 + 13 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/alert/alert.ts b/src/alert/alert.ts index 0c0356e..f1f67db 100644 --- a/src/alert/alert.ts +++ b/src/alert/alert.ts @@ -1,9 +1,11 @@ +import type { GrafanaAlert, GrafanaCondition } from '../grafana'; + class Alert { - private conditions: any[]; + private conditions: GrafanaCondition[]; - private state: any; + private state: GrafanaAlert; - constructor(opts: any = {}) { + constructor(opts = {}) { this.conditions = []; this.state = { diff --git a/src/alert/condition.ts b/src/alert/condition.ts index f059149..00d0d04 100644 --- a/src/alert/condition.ts +++ b/src/alert/condition.ts @@ -1,10 +1,13 @@ +import type { GrafanaCondition } from '../grafana'; + class Condition { - private state: object; + private state: GrafanaCondition; private _evaluator: { params: any[]; type: string }; private _operator: { type: string }; - private _query: { params: any[] }; + private _query: { params: string[] }; private _reducer: { params: any[]; type: string }; constructor(opts = {}) { + // @ts-expect-error todo: should fields be optional? this.state = {}; this._evaluator = { diff --git a/src/annotations/graphite.ts b/src/annotations/graphite.ts index de541a2..79cc3e8 100644 --- a/src/annotations/graphite.ts +++ b/src/annotations/graphite.ts @@ -19,9 +19,10 @@ // THE SOFTWARE. import errors = require('../errors'); +import type { GrafanaGraphiteAnnotation } from '../grafana'; class Graphite { - private state: any; + state: GrafanaGraphiteAnnotation; constructor(opts: any = {}) { if (!opts.name) { throw errors.UnfulfilledRequirement.create( diff --git a/src/external-link.ts b/src/external-link.ts index 23e1c51..659885a 100644 --- a/src/external-link.ts +++ b/src/external-link.ts @@ -18,10 +18,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import type { GrafanaExternalLink } from './grafana'; + class ExternalLink { - private state: any; + private state: GrafanaExternalLink; constructor(opts = {}) { - const defaults = { + const defaults: GrafanaExternalLink = { title: '', tooltip: '', url: '', diff --git a/src/panels/dashboard_list.ts b/src/panels/dashboard_list.ts index 4ca1772..23b2776 100644 --- a/src/panels/dashboard_list.ts +++ b/src/panels/dashboard_list.ts @@ -19,9 +19,10 @@ // THE SOFTWARE. import generateGraphId = require('../id'); +import type { GrafanaDashboardListPanel } from '../grafana'; class DashboardList { - state: any; + state: GrafanaDashboardListPanel; constructor(opts: any = {}) { this.state = { title: 'dashboard list', diff --git a/src/panels/graph.ts b/src/panels/graph.ts index 87978ab..bd1e2eb 100644 --- a/src/panels/graph.ts +++ b/src/panels/graph.ts @@ -19,14 +19,15 @@ // THE SOFTWARE. import generateGraphId = require('../id'); +import type { GrafanaGraphPanel } from '../grafana'; class Graph { private _currentRefIndex: number; - state: any; + state: GrafanaGraphPanel; constructor(opts: any = {}) { this._currentRefIndex = 0; - const defaults = { + const defaults: GrafanaGraphPanel = { type: 'graph', id: generateGraphId(), renderer: 'flot', diff --git a/src/panels/singlestat.ts b/src/panels/singlestat.ts index e836f88..eb72b52 100644 --- a/src/panels/singlestat.ts +++ b/src/panels/singlestat.ts @@ -19,11 +19,12 @@ // THE SOFTWARE. import generateGraphId = require('../id'); +import type { GrafanaSingleStatPanel } from '../grafana'; class SingleStat { - state: any; + state: GrafanaSingleStatPanel; constructor(opts: any = {}) { - const defaults = { + const defaults: GrafanaSingleStatPanel = { id: generateGraphId(), title: 'single stat', targets: [], diff --git a/src/panels/table.ts b/src/panels/table.ts index ee5e3e9..e1b357f 100644 --- a/src/panels/table.ts +++ b/src/panels/table.ts @@ -19,11 +19,12 @@ // THE SOFTWARE. import generateGraphId = require('../id'); +import type { GrafanaTablePanel } from '../grafana'; class Table { - state: any; + state: GrafanaTablePanel; constructor(opts: any = {}) { - const defaults = { + const defaults: GrafanaTablePanel = { title: 'Panel Title', error: false, span: 12, diff --git a/src/panels/text.ts b/src/panels/text.ts index 63ce143..3a61f61 100644 --- a/src/panels/text.ts +++ b/src/panels/text.ts @@ -19,11 +19,12 @@ // THE SOFTWARE. import generateGraphId = require('../id'); +import type { GrafanaTextPanel } from '../grafana'; class Text { - state: any; + state: GrafanaTextPanel; constructor(opts: any = {}) { - const defaults = { + const defaults: GrafanaTextPanel = { title: '', id: generateGraphId(), error: false, diff --git a/src/row.ts b/src/row.ts index 2ba9045..e4da962 100644 --- a/src/row.ts +++ b/src/row.ts @@ -19,9 +19,10 @@ // THE SOFTWARE. import xtend = require('xtend'); +import type { GrafanaRow } from './grafana'; class Row { - state: any; + state: GrafanaRow; panels: any[]; constructor(opts) { opts = opts || {}; diff --git a/src/templates/custom.ts b/src/templates/custom.ts index 74c547f..9f18a8d 100644 --- a/src/templates/custom.ts +++ b/src/templates/custom.ts @@ -18,10 +18,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import type { GrafanaCustomTemplate } from '../grafana'; + const DEFAULT_VARIABLE_ALL = '$__all'; class Custom { - state: any; + state: GrafanaCustomTemplate; private defaultValue: string; constructor(opts = {}) { this.state = { diff --git a/src/templates/query.ts b/src/templates/query.ts index e0c54dd..0288995 100644 --- a/src/templates/query.ts +++ b/src/templates/query.ts @@ -18,6 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import type { GrafanaQueryTemplate } from '../grafana'; + /** * Provide a query to populate template variable. * @@ -38,7 +40,7 @@ * @see http://docs.grafana.org/reference/templating/ */ class Query { - state: any; + state: GrafanaQueryTemplate; private _required: string[]; private _overridable: string[]; constructor(query: any, opts: any = {}) { diff --git a/test/dashboard.test.js b/test/dashboard.test.js index 61e7065..013397b 100644 --- a/test/dashboard.test.js +++ b/test/dashboard.test.js @@ -129,6 +129,7 @@ test('Dashboard can generate correct body', function () { }, }; dashboard.addRow(row); + // @ts-expect-error todo: incomplete mock simpleDashboard.rows = [rowData]; var json = dashboard.generate(); From d978ee393a8d80640b801aea5d91f99062933e3a Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Fri, 24 Oct 2025 22:15:39 +0200 Subject: [PATCH 3/7] type coverage improvements --- src/alert/alert.ts | 19 ++++++++---- src/alert/condition.ts | 2 +- src/annotations/graphite.ts | 2 +- src/dashboard.ts | 48 ++++++++++++++++++++---------- src/external-link.ts | 4 +-- src/grafana.ts | 13 ++++++-- src/panels/dashboard_list.ts | 13 ++++++-- src/panels/graph.ts | 11 ++++++- src/panels/index.ts | 8 ++++- src/panels/singlestat.ts | 13 ++++++-- src/panels/table.ts | 13 ++++++-- src/panels/text.ts | 13 ++++++-- src/row.ts | 14 +++++---- src/templates/custom.ts | 2 +- src/templates/index.ts | 4 ++- test/dashboard.test.js | 6 ++++ test/fixtures/override_row.ts | 1 + test/panels/dashboard_list.test.js | 2 ++ test/panels/graph.test.js | 2 ++ test/panels/singlestat.test.js | 2 ++ test/panels/table.test.js | 2 ++ test/panels/text.test.js | 2 ++ test/publish.test.js | 2 ++ test/row.test.js | 5 ++++ 24 files changed, 158 insertions(+), 45 deletions(-) diff --git a/src/alert/alert.ts b/src/alert/alert.ts index f1f67db..04b611f 100644 --- a/src/alert/alert.ts +++ b/src/alert/alert.ts @@ -1,11 +1,18 @@ -import type { GrafanaAlert, GrafanaCondition } from '../grafana'; +import type { GrafanaAlert } from '../grafana'; +import type Condition from './condition'; + +type AlertOptions = Partial< + Omit & { + conditions: Condition[]; + } +>; class Alert { - private conditions: GrafanaCondition[]; + private conditions: Condition[]; private state: GrafanaAlert; - constructor(opts = {}) { + constructor(opts: AlertOptions = {}) { this.conditions = []; this.state = { @@ -25,13 +32,13 @@ class Alert { this._initConditions(opts); } - _init(opts) { + _init(opts: AlertOptions) { Object.keys(opts).forEach((opt) => { this.state[opt] = opts[opt]; }); } - _initConditions(opts) { + _initConditions(opts: AlertOptions) { this.state.conditions = this.state.conditions || []; if (opts.conditions) { @@ -39,7 +46,7 @@ class Alert { } } - addCondition(condition) { + addCondition(condition: Condition) { this.conditions.push(condition); return this; } diff --git a/src/alert/condition.ts b/src/alert/condition.ts index 00d0d04..048a25f 100644 --- a/src/alert/condition.ts +++ b/src/alert/condition.ts @@ -6,7 +6,7 @@ class Condition { private _operator: { type: string }; private _query: { params: string[] }; private _reducer: { params: any[]; type: string }; - constructor(opts = {}) { + constructor(opts: Partial = {}) { // @ts-expect-error todo: should fields be optional? this.state = {}; diff --git a/src/annotations/graphite.ts b/src/annotations/graphite.ts index 79cc3e8..4929e2b 100644 --- a/src/annotations/graphite.ts +++ b/src/annotations/graphite.ts @@ -23,7 +23,7 @@ import type { GrafanaGraphiteAnnotation } from '../grafana'; class Graphite { state: GrafanaGraphiteAnnotation; - constructor(opts: any = {}) { + constructor(opts: Partial = {}) { if (!opts.name) { throw errors.UnfulfilledRequirement.create( '{component} missing requirement: {unfulfilledArg}', diff --git a/src/dashboard.ts b/src/dashboard.ts index e6b7ad9..b818651 100644 --- a/src/dashboard.ts +++ b/src/dashboard.ts @@ -21,12 +21,30 @@ import Templates = require('./templates'); import Annotations = require('./annotations'); import ExternalLink = require('./external-link'); +import type { + GrafanaCustomTemplate, + GrafanaDashboard, + GrafanaGraphiteAnnotation, +} from './grafana'; +import type Row from './row'; +import type Graphite from './annotations/graphite'; +import type Query from './templates/query'; +import type Custom from './templates/custom'; + +type DashboardOptions = Partial< + Omit & { + rows: Row[]; + templating: GrafanaCustomTemplate[]; + annotations: GrafanaGraphiteAnnotation[]; + } +>; class Dashboard { - state: any; - rows: any[]; - links: any[]; - constructor(opts = {}) { + state: GrafanaDashboard; + rows: Row[]; + links: ExternalLink[]; + constructor(opts: DashboardOptions = {}) { + // @ts-expect-error initialized in init calls below this.state = {}; this._init(opts); this._initRows(opts); @@ -35,7 +53,7 @@ class Dashboard { this._initAnnotations(opts); } - _init(opts) { + _init(opts: DashboardOptions) { this.state.id = opts.id || null; this.state.title = opts.title || 'Generated Grafana Dashboard'; this.state.originalTitle = opts.originalTitle || 'Generated Dashboard'; @@ -54,7 +72,7 @@ class Dashboard { } } - _initRows(opts) { + _initRows(opts: DashboardOptions) { this.rows = []; this.state.rows = []; @@ -65,12 +83,12 @@ class Dashboard { } } - _initLinks(opts) { + _initLinks(opts: DashboardOptions) { this.links = opts.links || []; this.state.links = []; } - _initTemplating(opts) { + _initTemplating(opts: DashboardOptions) { this.state.templating = { list: [], enable: true, @@ -78,13 +96,12 @@ class Dashboard { if (opts.templating) { opts.templating.forEach((template) => { - template = new Templates.Custom(template); - this.addTemplate(template); + this.addTemplate(new Templates.Custom(template)); }); } } - _initAnnotations(opts) { + _initAnnotations(opts: DashboardOptions) { this.state.annotations = { list: [], enable: true, @@ -92,21 +109,20 @@ class Dashboard { if (opts.annotations) { opts.annotations.forEach((annotation) => { - annotation = new Annotations.Graphite(annotation); - this.addAnnotation(annotation); + this.addAnnotation(new Annotations.Graphite(annotation)); }); } } - addRow(row) { + addRow(row: Row) { this.rows.push(row); } - addTemplate(template) { + addTemplate(template: Custom | Query) { this.state.templating.list.push(template.generate()); } - addAnnotation(annotation) { + addAnnotation(annotation: Graphite) { this.state.annotations.list.push(annotation.generate()); } diff --git a/src/external-link.ts b/src/external-link.ts index 659885a..6dbe395 100644 --- a/src/external-link.ts +++ b/src/external-link.ts @@ -22,7 +22,7 @@ import type { GrafanaExternalLink } from './grafana'; class ExternalLink { private state: GrafanaExternalLink; - constructor(opts = {}) { + constructor(opts: Partial = {}) { const defaults: GrafanaExternalLink = { title: '', tooltip: '', @@ -58,7 +58,7 @@ class ExternalLink { return this; } - withIcon(iconName) { + withIcon(iconName: string) { this.state.icon = iconName; return this; } diff --git a/src/grafana.ts b/src/grafana.ts index 9ec17ba..9fe8344 100644 --- a/src/grafana.ts +++ b/src/grafana.ts @@ -208,13 +208,20 @@ export interface GrafanaTextPanel extends GrafanaSharedProps { links: any[]; } +export type GrafanaPanel = + | GrafanaDashboardListPanel + | GrafanaGraphPanel + | GrafanaSingleStatPanel + | GrafanaTablePanel + | GrafanaTextPanel; + export interface GrafanaRow extends GrafanaSharedProps { title: string; showTitle: boolean; height: string; editable: boolean; collapse: boolean; - panels: any[]; + panels: GrafanaPanel[]; } export interface GrafanaExternalLink extends GrafanaSharedProps { @@ -229,6 +236,8 @@ export interface GrafanaExternalLink extends GrafanaSharedProps { keepTime: boolean; } +export type GrafanaTemplate = GrafanaQueryTemplate | GrafanaCustomTemplate; + export interface GrafanaDashboard extends GrafanaSharedProps { id: null; title: string; @@ -244,7 +253,7 @@ export interface GrafanaDashboard extends GrafanaSharedProps { hideAllLegends: boolean; rows: GrafanaRow[]; annotations: { list: any[]; enable: boolean }; - templating: { list: any[]; enable: boolean }; + templating: { list: GrafanaTemplate[]; enable: boolean }; time: null; links: GrafanaExternalLink[]; } diff --git a/src/panels/dashboard_list.ts b/src/panels/dashboard_list.ts index 23b2776..d62f347 100644 --- a/src/panels/dashboard_list.ts +++ b/src/panels/dashboard_list.ts @@ -20,10 +20,19 @@ import generateGraphId = require('../id'); import type { GrafanaDashboardListPanel } from '../grafana'; +import type Row from '../row'; +import type Dashboard from '../dashboard'; + +type DashboardListPanelOptions = Partial< + GrafanaDashboardListPanel & { + row: Row; + dashboard: Dashboard; + } +>; class DashboardList { state: GrafanaDashboardListPanel; - constructor(opts: any = {}) { + constructor(opts: DashboardListPanelOptions = {}) { this.state = { title: 'dashboard list', error: false, @@ -51,7 +60,7 @@ class DashboardList { } } - setTitle(title) { + setTitle(title: string) { this.state.title = title; } diff --git a/src/panels/graph.ts b/src/panels/graph.ts index bd1e2eb..b9a78af 100644 --- a/src/panels/graph.ts +++ b/src/panels/graph.ts @@ -20,11 +20,20 @@ import generateGraphId = require('../id'); import type { GrafanaGraphPanel } from '../grafana'; +import type Row from '../row'; +import type Dashboard from '../dashboard'; + +type GraphPanelOptions = Partial< + GrafanaGraphPanel & { + row: Row; + dashboard: Dashboard; + } +>; class Graph { private _currentRefIndex: number; state: GrafanaGraphPanel; - constructor(opts: any = {}) { + constructor(opts: GraphPanelOptions = {}) { this._currentRefIndex = 0; const defaults: GrafanaGraphPanel = { diff --git a/src/panels/index.ts b/src/panels/index.ts index d21d424..f72ac2c 100644 --- a/src/panels/index.ts +++ b/src/panels/index.ts @@ -24,10 +24,16 @@ import Text = require('./text'); import Table = require('./table'); import DashboardList = require('./dashboard_list'); -export = { +const panels = { Graph: Graph, SingleStat: SingleStat, Text: Text, Table: Table, DashboardList: DashboardList, }; + +// eslint-disable-next-line @typescript-eslint/no-namespace +namespace panels { + export type Panel = Graph | SingleStat | Text | Table | DashboardList; +} +export = panels; diff --git a/src/panels/singlestat.ts b/src/panels/singlestat.ts index eb72b52..3747e44 100644 --- a/src/panels/singlestat.ts +++ b/src/panels/singlestat.ts @@ -20,10 +20,19 @@ import generateGraphId = require('../id'); import type { GrafanaSingleStatPanel } from '../grafana'; +import type Row from '../row'; +import type Dashboard from '../dashboard'; + +type SingleStatOptions = Partial< + GrafanaSingleStatPanel & { + row: Row; + dashboard: Dashboard; + } +>; class SingleStat { state: GrafanaSingleStatPanel; - constructor(opts: any = {}) { + constructor(opts: SingleStatOptions = {}) { const defaults: GrafanaSingleStatPanel = { id: generateGraphId(), title: 'single stat', @@ -93,7 +102,7 @@ class SingleStat { return this.state; } - setTitle(title) { + setTitle(title: string) { this.state.title = title; } diff --git a/src/panels/table.ts b/src/panels/table.ts index e1b357f..d94d38b 100644 --- a/src/panels/table.ts +++ b/src/panels/table.ts @@ -20,10 +20,19 @@ import generateGraphId = require('../id'); import type { GrafanaTablePanel } from '../grafana'; +import type Row from '../row'; +import type Dashboard from '../dashboard'; + +type TableOptions = Partial< + GrafanaTablePanel & { + row: Row; + dashboard: Dashboard; + } +>; class Table { state: GrafanaTablePanel; - constructor(opts: any = {}) { + constructor(opts: TableOptions = {}) { const defaults: GrafanaTablePanel = { title: 'Panel Title', error: false, @@ -95,7 +104,7 @@ class Table { return this.state; } - setTitle(title) { + setTitle(title: string) { this.state.title = title; } diff --git a/src/panels/text.ts b/src/panels/text.ts index 3a61f61..fe48467 100644 --- a/src/panels/text.ts +++ b/src/panels/text.ts @@ -20,10 +20,19 @@ import generateGraphId = require('../id'); import type { GrafanaTextPanel } from '../grafana'; +import type Dashboard from '../dashboard'; +import type Row from '../row'; + +type TextPanelOptions = Partial< + GrafanaTextPanel & { + row: Row; + dashboard: Dashboard; + } +>; class Text { state: GrafanaTextPanel; - constructor(opts: any = {}) { + constructor(opts: TextPanelOptions = {}) { const defaults: GrafanaTextPanel = { title: '', id: generateGraphId(), @@ -54,7 +63,7 @@ class Text { return this.state; } - setTitle(title) { + setTitle(title: string) { this.state.title = title; } } diff --git a/src/row.ts b/src/row.ts index e4da962..4863de5 100644 --- a/src/row.ts +++ b/src/row.ts @@ -20,13 +20,17 @@ import xtend = require('xtend'); import type { GrafanaRow } from './grafana'; +import { Panel } from './panels'; + +type RowOptions = Omit, 'panels'> & { + panels?: Panel[]; +}; class Row { state: GrafanaRow; - panels: any[]; - constructor(opts) { - opts = opts || {}; - const state = { + panels: Panel[]; + constructor(opts: RowOptions = {}) { + const state: GrafanaRow = { title: 'New row', height: '250px', editable: true, @@ -50,7 +54,7 @@ class Row { return this.state; } - addPanel(panel) { + addPanel(panel: Panel) { this.panels.push(panel); } } diff --git a/src/templates/custom.ts b/src/templates/custom.ts index 9f18a8d..40bfe82 100644 --- a/src/templates/custom.ts +++ b/src/templates/custom.ts @@ -25,7 +25,7 @@ const DEFAULT_VARIABLE_ALL = '$__all'; class Custom { state: GrafanaCustomTemplate; private defaultValue: string; - constructor(opts = {}) { + constructor(opts: Partial = {}) { this.state = { allFormat: 'glob', current: {}, diff --git a/src/templates/index.ts b/src/templates/index.ts index ab890b3..5323a32 100644 --- a/src/templates/index.ts +++ b/src/templates/index.ts @@ -21,7 +21,9 @@ import Custom = require('./custom'); import Query = require('./query'); -export = { +const templates = { Custom: Custom, Query: Query, }; + +export = templates; diff --git a/test/dashboard.test.js b/test/dashboard.test.js index 013397b..c0ff8d1 100644 --- a/test/dashboard.test.js +++ b/test/dashboard.test.js @@ -38,16 +38,19 @@ test('Dashboard with overriden information', function () { title: 'custom title', tags: ['foo', 'bar'], templating: [ + // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'myvar', options: ['a', 'b'], }, + // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'smoothing', options: ['30min', '10min', '5min', '2min', '1min'], }, ], annotations: [ + // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'Deploy Completed', target: 'path.to.metric.with.annotation', @@ -56,6 +59,7 @@ test('Dashboard with overriden information', function () { refresh: '1m', rows: [ { + // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() title: 'New row', height: '250px', editable: true, @@ -72,6 +76,7 @@ test('Dashboard with overriden information', function () { test('Dashboard can add rows', function () { var dashboard = new Dashboard(); var row = { foo: 'foo' }; + // @ts-expect-error todo: bad mock dashboard.addRow(row); expect(dashboard.rows).toEqual([row]); }); @@ -128,6 +133,7 @@ test('Dashboard can generate correct body', function () { return rowData; }, }; + // @ts-expect-error incomplete mock dashboard.addRow(row); // @ts-expect-error todo: incomplete mock simpleDashboard.rows = [rowData]; diff --git a/test/fixtures/override_row.ts b/test/fixtures/override_row.ts index d13f23a..0b64be7 100644 --- a/test/fixtures/override_row.ts +++ b/test/fixtures/override_row.ts @@ -27,6 +27,7 @@ const overrideRow: GrafanaRow = { showTitle: true, collapse: true, panels: [ + // @ts-expect-error todo: unexpected type { foo: 'foo', bar: 'bar', diff --git a/test/panels/dashboard_list.test.js b/test/panels/dashboard_list.test.js index f41b1d9..0c32ef7 100644 --- a/test/panels/dashboard_list.test.js +++ b/test/panels/dashboard_list.test.js @@ -55,12 +55,14 @@ test('add graph to row and dashboard when passed', function () { var calledAddRow = 0; new DashboardList({ + // @ts-expect-error incomplete mock row: { addPanel: function addPanel() { calledAddPanel += 1; }, }, + // @ts-expect-error incomplete mock dashboard: { addRow: function addRow() { calledAddRow += 1; diff --git a/test/panels/graph.test.js b/test/panels/graph.test.js index b2100a7..9f8a0a9 100644 --- a/test/panels/graph.test.js +++ b/test/panels/graph.test.js @@ -53,12 +53,14 @@ test('add graph to row and dashboard when passed', () => { let calledAddRow = 0; new Graph({ + // @ts-expect-error incomplete mock row: { addPanel: function addPanel() { calledAddPanel += 1; }, }, + // @ts-expect-error incomplete mock dashboard: { addRow: function addRow() { calledAddRow += 1; diff --git a/test/panels/singlestat.test.js b/test/panels/singlestat.test.js index 85d9407..d11139c 100644 --- a/test/panels/singlestat.test.js +++ b/test/panels/singlestat.test.js @@ -57,12 +57,14 @@ test('add graph to row and dashboard when passed', function () { var calledAddRow = 0; new SingleStat({ + // @ts-expect-error incomplete mock row: { addPanel: function addPanel() { calledAddPanel += 1; }, }, + // @ts-expect-error incomplete mock dashboard: { addRow: function addRow() { calledAddRow += 1; diff --git a/test/panels/table.test.js b/test/panels/table.test.js index 0f8bd03..a70716f 100644 --- a/test/panels/table.test.js +++ b/test/panels/table.test.js @@ -49,12 +49,14 @@ test('add graph to row and dashboard when passed', function () { var calledAddRow = 0; new Table({ + // @ts-expect-error incomplete mock row: { addPanel: function addPanel() { calledAddPanel += 1; }, }, + // @ts-expect-error incomplete mock dashboard: { addRow: function addRow() { calledAddRow += 1; diff --git a/test/panels/text.test.js b/test/panels/text.test.js index dd6dda6..5ea8bf5 100644 --- a/test/panels/text.test.js +++ b/test/panels/text.test.js @@ -56,11 +56,13 @@ test('add graph to row and dashboard when passed', function () { var calledAddRow = 0; new Text({ + // @ts-expect-error incomplete mock row: { addPanel: function addPanel() { calledAddPanel += 1; }, }, + // @ts-expect-error incomplete mock dashboard: { addRow: function addRow() { calledAddRow += 1; diff --git a/test/publish.test.js b/test/publish.test.js index 055f6e8..fc1a8b8 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -57,7 +57,9 @@ const dashboard = new Dashboard({ title: title, tags: tags, refresh: refresh, + // @ts-expect-error todo: figure optional fields templating: [templateconst1, templateconst2], + // @ts-expect-error todo: figure optional fields annotations: [annotation1], links: externalLinks, }); diff --git a/test/row.test.js b/test/row.test.js index c298bc5..2def800 100644 --- a/test/row.test.js +++ b/test/row.test.js @@ -46,6 +46,7 @@ test('Row with overriden information', function () { height: '1000px', editable: false, collapse: true, + // @ts-expect-error incomplete mock panels: [panel1], }); expect(row.generate()).toEqual(overrideRow); @@ -63,6 +64,7 @@ test('Add panels to row when passed', function () { baz: 2, }; var row = new Row({ + // @ts-expect-error incomplete mock panels: [panel1, panel2], }); @@ -87,7 +89,9 @@ test('Row can add panels', function () { baz: 2, }; + // @ts-expect-error bad mock type row.addPanel(panel1); + // @ts-expect-error bad mock type row.addPanel(panel2); expect(row.panels).toEqual([panel1, panel2]); }); @@ -103,6 +107,7 @@ test('Row generates state', function () { height: '1000px', editable: false, collapse: true, + // @ts-expect-error incomplete mock panels: [panel], }); From 70534b77841bc714cf1ec57d3da4adcd6ee5f844 Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Fri, 24 Oct 2025 22:59:48 +0200 Subject: [PATCH 4/7] type coverage improvements --- src/annotations/graphite.ts | 2 +- src/config.ts | 14 +++++++++++--- src/publish.ts | 6 +++++- src/target.ts | 30 +++++++++++++++++++++++------- src/templates/query.ts | 5 +++-- test/publish.test.js | 6 ++++++ test/target.test.js | 1 + 7 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/annotations/graphite.ts b/src/annotations/graphite.ts index 4929e2b..0da60b6 100644 --- a/src/annotations/graphite.ts +++ b/src/annotations/graphite.ts @@ -44,7 +44,7 @@ class Graphite { ); } - const defaults = { + const defaults: GrafanaGraphiteAnnotation = { name: 'no name', datasource: 'graphite', showLine: true, diff --git a/src/config.ts b/src/config.ts index 59a40cb..18f2e48 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,7 +27,7 @@ import xtend = require('xtend'); * `cookie` - Key/value pair for auth, defaults to"auth-openid=" * `headers` - Map of header keys/values, defaults to no headers */ -let configurations = { +let configurations: Config = { user: 'guest', group: 'guest', url: 'https://your.graphite.url.com/elasticsearch/grafana-dash/dashboard/', @@ -35,11 +35,19 @@ let configurations = { headers: {}, }; -function configure(opts) { +type Config = { + user: string; + group: string; + url: string; + cookie: string; + headers: Record; +}; + +function configure(opts: Partial = {}) { configurations = xtend(configurations, opts); } -function getConfig() { +function getConfig(): Config { return configurations; } diff --git a/src/publish.ts b/src/publish.ts index 3cd3f99..f85a61a 100644 --- a/src/publish.ts +++ b/src/publish.ts @@ -21,8 +21,12 @@ import fetch = require('node-fetch'); import config = require('./config'); import errors = require('./errors'); +import type Dashboard from './dashboard'; -function publish(dashboard, opts: any = {}) { +function publish( + dashboard: Dashboard, + opts: Partial<{ timeout: number }> = {} +) { if (!dashboard) { throw errors.UnfulfilledRequirement.create( '{component} missing requirement: {unfulfilledArg}', diff --git a/src/target.ts b/src/target.ts index 279955b..0f1be3a 100644 --- a/src/target.ts +++ b/src/target.ts @@ -24,11 +24,14 @@ import _ = require('underscore'); import util = require('util'); class Target { - source: any; - private func: any; + source: string | { toString(): string }; + func?: [string, ...args: (string | number | boolean)[]]; constructor(template: string, ...substitutions: any[]); - constructor(source: Target, func: (string | number | boolean)[]); + constructor( + source: { toString(): string }, + func: (string | number | boolean)[] + ); constructor() { if (arguments.length === 0) { @@ -50,7 +53,7 @@ class Target { static PRIMITIVES: typeof PRIMITIVES; static COLORS: typeof COLORS; - toString() { + toString(): string { if (this.func) { const args = _.reduce( this.func.slice(1), @@ -66,7 +69,7 @@ class Target { ); return this.func[0] + '(' + this.source.toString() + args + ')'; } else { - return this.source; + return this.source as string; } } @@ -198,7 +201,7 @@ const PRIMITIVES = { transformNull: 0, useSeriesAbove: 3, weightedAverage: 2, -}; +} as const; Target.PRIMITIVES = PRIMITIVES; interface Target { @@ -319,10 +322,23 @@ const COLORS = [ 'purple', 'pink', 'aqua', -]; +] as const; Target.COLORS = COLORS; +interface Target { + orange(): Target; + blue(): Target; + green(): Target; + red(): Target; + white(): Target; + yellow(): Target; + brown(): Target; + purple(): Target; + pink(): Target; + aqua(): Target; +} + _.each(Target.COLORS, function each(color) { Target.prototype[color] = function t() { return this.color(color); diff --git a/src/templates/query.ts b/src/templates/query.ts index 0288995..72f3dbf 100644 --- a/src/templates/query.ts +++ b/src/templates/query.ts @@ -43,10 +43,11 @@ class Query { state: GrafanaQueryTemplate; private _required: string[]; private _overridable: string[]; - constructor(query: any, opts: any = {}) { + constructor(query: string, opts: Partial = {}) { this.state = { query: query, - name: opts.name, + // todo: added default + name: opts.name || '', datasource: opts.datasource, type: 'query', includeAll: true, diff --git a/test/publish.test.js b/test/publish.test.js index fc1a8b8..5860e8c 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -67,6 +67,7 @@ const dashboard = new Dashboard({ test('Publish dashboard - requires dashboard', async () => { await expect(async () => { config.configure(); + // @ts-expect-error intentionally invalid arguments return publish(); }).rejects.toThrow('grafana.publish missing requirement: dashboard'); }); @@ -74,6 +75,7 @@ test('Publish dashboard - requires dashboard', async () => { test('Publish dashboard - invalid state', async () => { await expect(async () => { config.configure(); + // @ts-expect-error intentionally invalid arguments return publish({}); }).rejects.toThrow( 'grafana.Dashboard state is invalid: state.title undefined' @@ -84,6 +86,7 @@ test('Publish dashboard - invalid title', async () => { await expect(async () => { config.configure(); return publish({ + // @ts-expect-error intentionally invalid arguments state: {}, }); }).rejects.toThrow( @@ -98,6 +101,7 @@ test('Publish dashboard - misconfigured url', async () => { url: null, }); return publish({ + // @ts-expect-error incomplete mock state: { title: title, }, @@ -114,6 +118,7 @@ test('Publish dashboard - misconfigured cookie', async () => { url: url, }); return publish({ + // @ts-expect-error incomplete mock state: { title: title, }, @@ -272,6 +277,7 @@ test('Publish dashboard - success w/ custom timeout', async function () { test('Publish dashboard - passes headers', async function () { config.configure({ cookie: cookie, + // @ts-expect-error bad mock headers: headers, url: url, }); diff --git a/test/target.test.js b/test/target.test.js index 408665e..17a41fb 100644 --- a/test/target.test.js +++ b/test/target.test.js @@ -135,6 +135,7 @@ test('Target helper-method - summarize15min', function () { var expected = 'summarize(path.to.metric, "15min")'; var target = new Target(arg).summarize15min().toString(); expect(target).toBe(expected); + // @ts-expect-error todo: useless test as it is always to pass expect(target.hide).toBe(undefined); }); From 7da4d3c6581a6dbb84d2593e39a7776f5d4a6bcd Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Sat, 25 Oct 2025 00:12:08 +0200 Subject: [PATCH 5/7] type improvements --- src/grafana.ts | 64 +++++++++++++++++++++++++----------------- test/dashboard.test.js | 3 -- test/publish.test.js | 2 -- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/grafana.ts b/src/grafana.ts index 9fe8344..497e6ac 100644 --- a/src/grafana.ts +++ b/src/grafana.ts @@ -19,27 +19,36 @@ export interface GrafanaQueryTemplate extends GrafanaSharedProps { export interface GrafanaCustomTemplate extends GrafanaSharedProps { name: string; - type: string; + type?: string; options: any[]; - datasource: null; - refresh: number; - refresh_on_load: boolean; - includeAll: boolean; - allValue: string; - allFormat: string; - query: null | string; - current: object; + datasource?: null | { + type: string; + uid: string; + }; + refresh?: number; + refresh_on_load?: boolean; + includeAll?: boolean; + allValue?: string; + allFormat?: string; + query?: null | string; + current?: object; } export interface GrafanaGraphiteAnnotation extends GrafanaSharedProps { name: string; - datasource: string; - showLine: boolean; - iconColor: string; - lineColor: string; - iconSize: number; - enable: boolean; - target: string; + datasource?: + | null + | { + type: string; + uid: string; + } + | string; + showLine?: boolean; + iconColor?: string; + lineColor?: string; + iconSize?: number; + enable?: boolean; + target?: string; } export interface GrafanaDashboardListPanel extends GrafanaSharedProps { @@ -226,9 +235,9 @@ export interface GrafanaRow extends GrafanaSharedProps { export interface GrafanaExternalLink extends GrafanaSharedProps { title: string; - tooltip: string; + tooltip?: string; url: string; - tags: any[]; + tags?: any[]; icon: string; targetBlank: boolean; type: string; @@ -239,22 +248,25 @@ export interface GrafanaExternalLink extends GrafanaSharedProps { export type GrafanaTemplate = GrafanaQueryTemplate | GrafanaCustomTemplate; export interface GrafanaDashboard extends GrafanaSharedProps { - id: null; + id?: number | null; title: string; - originalTitle: string; + originalTitle?: string; tags: any[]; style: string; timezone: string; editable: boolean; - hideControls: boolean; - sharedCrosshair: boolean; + hideControls?: boolean; + sharedCrosshair?: boolean; refresh: boolean | string; schemaVersion: number; - hideAllLegends: boolean; + hideAllLegends?: boolean; rows: GrafanaRow[]; - annotations: { list: any[]; enable: boolean }; - templating: { list: GrafanaTemplate[]; enable: boolean }; - time: null; + annotations: { list: GrafanaGraphiteAnnotation[]; enable?: boolean }; + templating: { list: GrafanaTemplate[]; enable?: boolean }; + time?: null | { + from: string; + to: string; + }; links: GrafanaExternalLink[]; } diff --git a/test/dashboard.test.js b/test/dashboard.test.js index c0ff8d1..8e36538 100644 --- a/test/dashboard.test.js +++ b/test/dashboard.test.js @@ -38,19 +38,16 @@ test('Dashboard with overriden information', function () { title: 'custom title', tags: ['foo', 'bar'], templating: [ - // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'myvar', options: ['a', 'b'], }, - // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'smoothing', options: ['30min', '10min', '5min', '2min', '1min'], }, ], annotations: [ - // @ts-expect-error todo: this is not correct and will result in errors if to call .generate() { name: 'Deploy Completed', target: 'path.to.metric.with.annotation', diff --git a/test/publish.test.js b/test/publish.test.js index 5860e8c..b9e4dbe 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -57,9 +57,7 @@ const dashboard = new Dashboard({ title: title, tags: tags, refresh: refresh, - // @ts-expect-error todo: figure optional fields templating: [templateconst1, templateconst2], - // @ts-expect-error todo: figure optional fields annotations: [annotation1], links: externalLinks, }); From 0fe6da5afcf95f2fddb9778fbc3c59ac41a2ba18 Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Sat, 25 Oct 2025 00:26:37 +0200 Subject: [PATCH 6/7] add npm run typecheck to CI --- .github/workflows/node.js.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index b8ef9af..673fa66 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -30,3 +30,4 @@ jobs: - run: npm run build --if-present - run: npm test - run: npm run lint + - run: npm run typecheck From ab12c0577dceee6b86a59ca126324aef17dd8a27 Mon Sep 17 00:00:00 2001 From: Bogdan Savluk Date: Sat, 25 Oct 2025 00:31:05 +0200 Subject: [PATCH 7/7] update excludes to ignore files depending on build output --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 73d1874..2a565ca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,5 +39,5 @@ "skipLibCheck": true, "esModuleInterop": true }, - "exclude": ["coverage", "grafana"] + "exclude": ["coverage", "grafana", "index.js", "example.js"] }