@intentius/chant-lexicon-grafana 0.97.0 → 0.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -5
- package/dist/actions/grafana.d.ts +24 -0
- package/dist/actions/grafana.d.ts.map +1 -0
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/alerting-build.d.ts +128 -0
- package/dist/alerting-build.d.ts.map +1 -0
- package/dist/alerting.d.ts +273 -0
- package/dist/alerting.d.ts.map +1 -0
- package/dist/api/apply.d.ts +156 -0
- package/dist/api/apply.d.ts.map +1 -0
- package/dist/api/bind.d.ts +32 -0
- package/dist/api/bind.d.ts.map +1 -0
- package/dist/api/client.d.ts +76 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/converge.d.ts +33 -0
- package/dist/api/converge.d.ts.map +1 -0
- package/dist/api/dashboards.d.ts +102 -0
- package/dist/api/dashboards.d.ts.map +1 -0
- package/dist/api/datasources.d.ts +26 -0
- package/dist/api/datasources.d.ts.map +1 -0
- package/dist/api/fake-grafana-writes.d.ts +41 -0
- package/dist/api/fake-grafana-writes.d.ts.map +1 -0
- package/dist/api/fake-grafana.d.ts +61 -0
- package/dist/api/fake-grafana.d.ts.map +1 -0
- package/dist/api/folders.d.ts +110 -0
- package/dist/api/folders.d.ts.map +1 -0
- package/dist/api/library-panels.d.ts +52 -0
- package/dist/api/library-panels.d.ts.map +1 -0
- package/dist/build.d.ts +30 -2
- package/dist/build.d.ts.map +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/schema-types.d.ts +3 -3
- package/dist/codegen/schema-types.d.ts.map +1 -1
- package/dist/composites/agent-dashboard.d.ts.map +1 -1
- package/dist/composites/catalog.d.ts.map +1 -1
- package/dist/composites/index.d.ts +4 -2
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/red-dashboard.d.ts +21 -2
- package/dist/composites/red-dashboard.d.ts.map +1 -1
- package/dist/composites/shared.d.ts +7 -0
- package/dist/composites/shared.d.ts.map +1 -1
- package/dist/composites/slo-alert-rules.d.ts +92 -0
- package/dist/composites/slo-alert-rules.d.ts.map +1 -0
- package/dist/config.d.ts +111 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/contact-point-secrets.d.ts +17 -0
- package/dist/contact-point-secrets.d.ts.map +1 -0
- package/dist/dashboard.d.ts +16 -2
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/datasource-refs.d.ts +95 -0
- package/dist/datasource-refs.d.ts.map +1 -0
- package/dist/datasource.d.ts +29 -0
- package/dist/datasource.d.ts.map +1 -1
- package/dist/deep-observe-hooks.d.ts +64 -0
- package/dist/deep-observe-hooks.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +42 -0
- package/dist/deep-observe.d.ts.map +1 -0
- package/dist/describe-resources.d.ts +49 -0
- package/dist/describe-resources.d.ts.map +1 -0
- package/dist/detect.d.ts +28 -1
- package/dist/detect.d.ts.map +1 -1
- package/dist/export-resources.d.ts +38 -0
- package/dist/export-resources.d.ts.map +1 -0
- package/dist/import/alerting.d.ts +40 -0
- package/dist/import/alerting.d.ts.map +1 -0
- package/dist/import/edits.d.ts +47 -0
- package/dist/import/edits.d.ts.map +1 -0
- package/dist/import/embedded.d.ts +14 -0
- package/dist/import/embedded.d.ts.map +1 -0
- package/dist/import/generator.d.ts +60 -0
- package/dist/import/generator.d.ts.map +1 -0
- package/dist/import/live-export.d.ts +108 -0
- package/dist/import/live-export.d.ts.map +1 -0
- package/dist/import/mappings.d.ts +83 -0
- package/dist/import/mappings.d.ts.map +1 -0
- package/dist/import/model.d.ts +98 -0
- package/dist/import/model.d.ts.map +1 -0
- package/dist/import/normalize-alerting.d.ts +26 -0
- package/dist/import/normalize-alerting.d.ts.map +1 -0
- package/dist/import/normalize.d.ts +74 -0
- package/dist/import/normalize.d.ts.map +1 -0
- package/dist/import/parser.d.ts +110 -0
- package/dist/import/parser.d.ts.map +1 -0
- package/dist/import/report.d.ts +26 -0
- package/dist/import/report.d.ts.map +1 -0
- package/dist/import/testdata/fixtures.d.ts +35 -0
- package/dist/import/testdata/fixtures.d.ts.map +1 -0
- package/dist/import/v2.d.ts +72 -0
- package/dist/import/v2.d.ts.map +1 -0
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +18 -10
- package/dist/k8s.d.ts +107 -0
- package/dist/k8s.d.ts.map +1 -0
- package/dist/lint/audit-catalog.d.ts +2 -1
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/graf101.d.ts +2 -2
- package/dist/lint/post-synth/graf102.d.ts +1 -1
- package/dist/lint/post-synth/graf107.d.ts +1 -1
- package/dist/lint/post-synth/graf108.d.ts +8 -0
- package/dist/lint/post-synth/graf108.d.ts.map +1 -0
- package/dist/lint/post-synth/graf109.d.ts +8 -0
- package/dist/lint/post-synth/graf109.d.ts.map +1 -0
- package/dist/lint/post-synth/graf111.d.ts +8 -0
- package/dist/lint/post-synth/graf111.d.ts.map +1 -0
- package/dist/lint/post-synth/graf112.d.ts +8 -0
- package/dist/lint/post-synth/graf112.d.ts.map +1 -0
- package/dist/lint/post-synth/graf113.d.ts +8 -0
- package/dist/lint/post-synth/graf113.d.ts.map +1 -0
- package/dist/lint/post-synth/graf114.d.ts +8 -0
- package/dist/lint/post-synth/graf114.d.ts.map +1 -0
- package/dist/lint/post-synth/graf115.d.ts +8 -0
- package/dist/lint/post-synth/graf115.d.ts.map +1 -0
- package/dist/lint/post-synth/grafana-helpers.d.ts +7 -5
- package/dist/lint/post-synth/grafana-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/rules/literal-secret.d.ts +7 -3
- package/dist/lint/rules/literal-secret.d.ts.map +1 -1
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/members.d.ts +27 -0
- package/dist/members.d.ts.map +1 -0
- package/dist/meta.json +135 -0
- package/dist/okf/index.md +36 -2
- package/dist/okf/rules/GRAF002.md +3 -2
- package/dist/okf/rules/GRAF101.md +3 -2
- package/dist/okf/rules/GRAF102.md +1 -0
- package/dist/okf/rules/GRAF108.md +11 -0
- package/dist/okf/rules/GRAF109.md +15 -0
- package/dist/okf/rules/GRAF111.md +11 -0
- package/dist/okf/rules/GRAF112.md +16 -0
- package/dist/okf/rules/GRAF113.md +16 -0
- package/dist/okf/rules/GRAF114.md +11 -0
- package/dist/okf/rules/GRAF115.md +11 -0
- package/dist/okf/types/AlertListPanel.md +9 -0
- package/dist/okf/types/AlertQuery.md +9 -0
- package/dist/okf/types/AlertRule.md +9 -0
- package/dist/okf/types/AlertRuleGroup.md +9 -0
- package/dist/okf/types/BarChartPanel.md +9 -0
- package/dist/okf/types/BarGaugePanel.md +9 -0
- package/dist/okf/types/CanvasPanel.md +9 -0
- package/dist/okf/types/ClassicConditionsExpression.md +9 -0
- package/dist/okf/types/ContactPoint.md +14 -0
- package/dist/okf/types/Dashboard.md +1 -0
- package/dist/okf/types/Datasource.md +3 -2
- package/dist/okf/types/ExternalDatasource.md +15 -0
- package/dist/okf/types/FlameGraphPanel.md +9 -0
- package/dist/okf/types/GeomapPanel.md +9 -0
- package/dist/okf/types/HistogramPanel.md +9 -0
- package/dist/okf/types/MathExpression.md +9 -0
- package/dist/okf/types/MuteTiming.md +13 -0
- package/dist/okf/types/NodeGraphPanel.md +9 -0
- package/dist/okf/types/NotificationPolicy.md +9 -0
- package/dist/okf/types/NotificationTemplate.md +9 -0
- package/dist/okf/types/PieChartPanel.md +9 -0
- package/dist/okf/types/ReduceExpression.md +9 -0
- package/dist/okf/types/ResampleExpression.md +9 -0
- package/dist/okf/types/SqlExpression.md +9 -0
- package/dist/okf/types/StateTimelinePanel.md +9 -0
- package/dist/okf/types/StatusHistoryPanel.md +9 -0
- package/dist/okf/types/ThresholdExpression.md +9 -0
- package/dist/okf/types/TrendPanel.md +9 -0
- package/dist/okf/types/XYChartPanel.md +9 -0
- package/dist/op/activities/grafana-apply.d.ts +75 -0
- package/dist/op/activities/grafana-apply.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +9 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/builders.d.ts +24 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/ownership.d.ts +67 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/panel-options.d.ts +65 -0
- package/dist/panel-options.d.ts.map +1 -0
- package/dist/panels.d.ts +46 -9
- package/dist/panels.d.ts.map +1 -1
- package/dist/pin.d.ts +29 -7
- package/dist/pin.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/promql-check.d.ts +51 -0
- package/dist/promql-check.d.ts.map +1 -0
- package/dist/query.d.ts +9 -8
- package/dist/query.d.ts.map +1 -1
- package/dist/rules/graf101.ts +3 -3
- package/dist/rules/graf102.ts +1 -1
- package/dist/rules/graf107.ts +1 -1
- package/dist/rules/graf108.ts +17 -0
- package/dist/rules/graf109.ts +17 -0
- package/dist/rules/graf111.ts +17 -0
- package/dist/rules/graf112.ts +17 -0
- package/dist/rules/graf113.ts +17 -0
- package/dist/rules/graf114.ts +17 -0
- package/dist/rules/graf115.ts +17 -0
- package/dist/rules/grafana-helpers.ts +15 -8
- package/dist/rules/literal-secret.ts +60 -6
- package/dist/schema/barchart.gen.d.ts +198 -0
- package/dist/schema/barchart.gen.d.ts.map +1 -0
- package/dist/schema/bargauge.gen.d.ts +97 -0
- package/dist/schema/bargauge.gen.d.ts.map +1 -0
- package/dist/schema/canvas.gen.d.ts +152 -0
- package/dist/schema/canvas.gen.d.ts.map +1 -0
- package/dist/schema/dashboard.gen.d.ts +196 -21
- package/dist/schema/dashboard.gen.d.ts.map +1 -1
- package/dist/schema/expr.gen.d.ts +606 -0
- package/dist/schema/expr.gen.d.ts.map +1 -0
- package/dist/schema/gauge.gen.d.ts.map +1 -1
- package/dist/schema/geomap.gen.d.ts +100 -0
- package/dist/schema/geomap.gen.d.ts.map +1 -0
- package/dist/schema/heatmap.gen.d.ts.map +1 -1
- package/dist/schema/histogram.gen.d.ts +132 -0
- package/dist/schema/histogram.gen.d.ts.map +1 -0
- package/dist/schema/index.d.ts +12 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/logs.gen.d.ts +1 -0
- package/dist/schema/logs.gen.d.ts.map +1 -1
- package/dist/schema/loki.gen.d.ts.map +1 -1
- package/dist/schema/nodegraph.gen.d.ts +49 -0
- package/dist/schema/nodegraph.gen.d.ts.map +1 -0
- package/dist/schema/piechart.gen.d.ts +127 -0
- package/dist/schema/piechart.gen.d.ts.map +1 -0
- package/dist/schema/prometheus.gen.d.ts.map +1 -1
- package/dist/schema/stat.gen.d.ts.map +1 -1
- package/dist/schema/statetimeline.gen.d.ts +124 -0
- package/dist/schema/statetimeline.gen.d.ts.map +1 -0
- package/dist/schema/statushistory.gen.d.ts +114 -0
- package/dist/schema/statushistory.gen.d.ts.map +1 -0
- package/dist/schema/table.gen.d.ts +22 -3
- package/dist/schema/table.gen.d.ts.map +1 -1
- package/dist/schema/tempo.gen.d.ts.map +1 -1
- package/dist/schema/text.gen.d.ts.map +1 -1
- package/dist/schema/timeseries.gen.d.ts +5 -1
- package/dist/schema/timeseries.gen.d.ts.map +1 -1
- package/dist/schema/trend.gen.d.ts +180 -0
- package/dist/schema/trend.gen.d.ts.map +1 -0
- package/dist/schema/xychart.gen.d.ts +145 -0
- package/dist/schema/xychart.gen.d.ts.map +1 -0
- package/dist/schema-validate.d.ts +30 -4
- package/dist/schema-validate.d.ts.map +1 -1
- package/dist/serializer.d.ts +11 -3
- package/dist/serializer.d.ts.map +1 -1
- package/dist/skill-defs.d.ts.map +1 -1
- package/dist/skills/chant-grafana-alerting.md +49 -0
- package/dist/skills/chant-grafana-provisioning.md +3 -3
- package/dist/skills/chant-grafana.md +12 -6
- package/dist/spec/fetch-units-cli.d.ts +3 -0
- package/dist/spec/fetch-units-cli.d.ts.map +1 -0
- package/dist/spec/overlay.d.ts +43 -0
- package/dist/spec/overlay.d.ts.map +1 -0
- package/dist/spec/schemas.d.ts +13 -7
- package/dist/spec/schemas.d.ts.map +1 -1
- package/dist/spec/units.d.ts +35 -0
- package/dist/spec/units.d.ts.map +1 -0
- package/dist/spec/units.gen.d.ts +2 -0
- package/dist/spec/units.gen.d.ts.map +1 -0
- package/dist/transformations.d.ts +459 -0
- package/dist/transformations.d.ts.map +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/validate-alerting.d.ts +65 -0
- package/dist/validate-alerting.d.ts.map +1 -0
- package/dist/validate-output.d.ts +49 -9
- package/dist/validate-output.d.ts.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/variables.d.ts +7 -2
- package/dist/variables.d.ts.map +1 -1
- package/package.json +12 -4
- package/src/actions/actions.test.ts +24 -0
- package/src/actions/grafana.ts +40 -0
- package/src/actions/index.ts +1 -0
- package/src/alerting-build.ts +376 -0
- package/src/alerting.e2e.test.ts +212 -0
- package/src/alerting.test.ts +272 -0
- package/src/alerting.ts +435 -0
- package/src/api/apply.test.ts +238 -0
- package/src/api/apply.ts +384 -0
- package/src/api/bind.ts +58 -0
- package/src/api/client.ts +148 -0
- package/src/api/converge.ts +63 -0
- package/src/api/dashboards.ts +247 -0
- package/src/api/datasources.ts +33 -0
- package/src/api/fake-grafana-writes.ts +201 -0
- package/src/api/fake-grafana.ts +186 -0
- package/src/api/folders.ts +265 -0
- package/src/api/library-panels.ts +101 -0
- package/src/build.test.ts +210 -5
- package/src/build.ts +180 -43
- package/src/catalog.ts +86 -2
- package/src/codegen/docs.ts +42 -9
- package/src/codegen/schema-types.ts +16 -6
- package/src/composites/agent-dashboard.ts +6 -3
- package/src/composites/catalog.test.ts +2 -2
- package/src/composites/catalog.ts +82 -0
- package/src/composites/composites.test.ts +73 -9
- package/src/composites/index.ts +4 -2
- package/src/composites/queries.e2e.test.ts +374 -0
- package/src/composites/red-dashboard.ts +83 -12
- package/src/composites/shared.ts +11 -0
- package/src/composites/slo-alert-rules.ts +149 -0
- package/src/config.test.ts +61 -0
- package/src/config.ts +138 -0
- package/src/contact-point-secrets.ts +63 -0
- package/src/dashboard.ts +16 -2
- package/src/datasource-refs.test.ts +56 -0
- package/src/datasource-refs.ts +189 -0
- package/src/datasource.ts +52 -0
- package/src/deep-observe-hooks.ts +252 -0
- package/src/deep-observe.test.ts +265 -0
- package/src/deep-observe.ts +164 -0
- package/src/describe-resources.test.ts +255 -0
- package/src/describe-resources.ts +209 -0
- package/src/detect.ts +79 -2
- package/src/export-resources.test.ts +129 -0
- package/src/export-resources.ts +84 -0
- package/src/generated/lexicon-grafana.json +135 -0
- package/src/import/alerting-roundtrip.test.ts +161 -0
- package/src/import/alerting.ts +500 -0
- package/src/import/edits.ts +95 -0
- package/src/import/embedded.test.ts +45 -0
- package/src/import/embedded.ts +47 -0
- package/src/import/generated-types.e2e.test.ts +118 -0
- package/src/import/generator.test.ts +210 -0
- package/src/import/generator.ts +462 -0
- package/src/import/live-export.ts +264 -0
- package/src/import/mappings.ts +264 -0
- package/src/import/model.ts +110 -0
- package/src/import/normalize-alerting.ts +101 -0
- package/src/import/normalize.test.ts +117 -0
- package/src/import/normalize.ts +364 -0
- package/src/import/parser.test.ts +440 -0
- package/src/import/parser.ts +1236 -0
- package/src/import/report.ts +62 -0
- package/src/import/roundtrip.test.ts +468 -0
- package/src/import/testdata/fixtures.ts +129 -0
- package/src/import/v2.test.ts +292 -0
- package/src/import/v2.ts +803 -0
- package/src/import.e2e.test.ts +31 -84
- package/src/import.test.ts +9 -3
- package/src/index.ts +190 -5
- package/src/k8s.test.ts +98 -0
- package/src/k8s.ts +197 -0
- package/src/lint/audit-catalog.ts +60 -3
- package/src/lint/core-lint.test.ts +43 -0
- package/src/lint/post-synth/graf101.ts +3 -3
- package/src/lint/post-synth/graf102.ts +1 -1
- package/src/lint/post-synth/graf107.ts +1 -1
- package/src/lint/post-synth/graf108.ts +17 -0
- package/src/lint/post-synth/graf109.ts +17 -0
- package/src/lint/post-synth/graf111.ts +17 -0
- package/src/lint/post-synth/graf112.ts +17 -0
- package/src/lint/post-synth/graf113.ts +17 -0
- package/src/lint/post-synth/graf114.ts +17 -0
- package/src/lint/post-synth/graf115.ts +17 -0
- package/src/lint/post-synth/grafana-helpers.ts +15 -8
- package/src/lint/post-synth/index.ts +14 -0
- package/src/lint/post-synth/post-synth.test.ts +235 -11
- package/src/lint/rules/literal-secret.ts +60 -6
- package/src/lint/rules/rules.test.ts +27 -0
- package/src/lsp/completions.test.ts +5 -0
- package/src/lsp/hover.test.ts +7 -0
- package/src/lsp/hover.ts +8 -1
- package/src/members.ts +68 -0
- package/src/observe.e2e.test.ts +255 -0
- package/src/op/activities/grafana-apply.e2e.test.ts +175 -0
- package/src/op/activities/grafana-apply.test.ts +229 -0
- package/src/op/activities/grafana-apply.ts +171 -0
- package/src/op/activities/index.ts +8 -0
- package/src/op/builders.test.ts +40 -0
- package/src/op/builders.ts +34 -0
- package/src/ownership.ts +103 -0
- package/src/panel-options.ts +66 -0
- package/src/panels.test.ts +51 -0
- package/src/panels.ts +148 -10
- package/src/pin.ts +57 -6
- package/src/plugin.test.ts +5 -2
- package/src/plugin.ts +66 -0
- package/src/promql-check.test.ts +108 -0
- package/src/promql-check.ts +189 -0
- package/src/query.ts +13 -8
- package/src/schema/barchart.gen.ts +221 -0
- package/src/schema/bargauge.gen.ts +111 -0
- package/src/schema/canvas.gen.ts +176 -0
- package/src/schema/dashboard.gen.ts +206 -22
- package/src/schema/expr.gen.ts +618 -0
- package/src/schema/gauge.gen.ts +2 -1
- package/src/schema/geomap.gen.ts +112 -0
- package/src/schema/heatmap.gen.ts +2 -1
- package/src/schema/histogram.gen.ts +151 -0
- package/src/schema/index.ts +12 -0
- package/src/schema/logs.gen.ts +3 -1
- package/src/schema/loki.gen.ts +2 -1
- package/src/schema/nodegraph.gen.ts +58 -0
- package/src/schema/piechart.gen.ts +146 -0
- package/src/schema/prometheus.gen.ts +2 -1
- package/src/schema/stat.gen.ts +2 -1
- package/src/schema/statetimeline.gen.ts +143 -0
- package/src/schema/statushistory.gen.ts +132 -0
- package/src/schema/table.gen.ts +27 -4
- package/src/schema/tempo.gen.ts +2 -1
- package/src/schema/text.gen.ts +2 -1
- package/src/schema/timeseries.gen.ts +7 -2
- package/src/schema/trend.gen.ts +208 -0
- package/src/schema/xychart.gen.ts +167 -0
- package/src/schema-overlay.test.ts +282 -0
- package/src/schema-validate.ts +141 -50
- package/src/schema.test.ts +4 -2
- package/src/serializer.test.ts +13 -1
- package/src/serializer.ts +11 -3
- package/src/skill-defs.ts +17 -0
- package/src/skills/chant-grafana-alerting.md +49 -0
- package/src/skills/chant-grafana-provisioning.md +3 -3
- package/src/skills/chant-grafana.md +12 -6
- package/src/spec/fetch-cli.ts +3 -3
- package/src/spec/fetch-units-cli.ts +37 -0
- package/src/spec/overlay/canvas.overlay.json +142 -0
- package/src/spec/overlay/dashboard.overlay.json +378 -0
- package/src/spec/overlay/expr.overlay.json +14 -0
- package/src/spec/overlay/geomap.overlay.json +35 -0
- package/src/spec/overlay/logs.overlay.json +14 -0
- package/src/spec/overlay/nodegraph.overlay.json +31 -0
- package/src/spec/overlay/piechart.overlay.json +17 -0
- package/src/spec/overlay/table.overlay.json +84 -0
- package/src/spec/overlay/timeseries.overlay.json +21 -0
- package/src/spec/overlay/trend.overlay.json +17 -0
- package/src/spec/overlay/xychart.overlay.json +16 -0
- package/src/spec/overlay.ts +105 -0
- package/src/spec/schemas/barchart.jsonschema.json +419 -0
- package/src/spec/schemas/bargauge.jsonschema.json +224 -0
- package/src/spec/schemas/canvas.jsonschema.json +356 -0
- package/src/spec/schemas/dashboardv2.jsonschema.json +3387 -0
- package/src/spec/schemas/expr.jsonschema.json +987 -0
- package/src/spec/schemas/geomap.jsonschema.json +220 -0
- package/src/spec/schemas/histogram.jsonschema.json +308 -0
- package/src/spec/schemas/nodegraph.jsonschema.json +77 -0
- package/src/spec/schemas/piechart.jsonschema.json +275 -0
- package/src/spec/schemas/statetimeline.jsonschema.json +324 -0
- package/src/spec/schemas/statushistory.jsonschema.json +292 -0
- package/src/spec/schemas/trend.jsonschema.json +449 -0
- package/src/spec/schemas/xychart.jsonschema.json +428 -0
- package/src/spec/schemas.ts +22 -10
- package/src/spec/units.gen.ts +281 -0
- package/src/spec/units.ts +77 -0
- package/src/transformations.test.ts +65 -0
- package/src/transformations.ts +574 -0
- package/src/util.ts +8 -0
- package/src/validate-alerting.test.ts +255 -0
- package/src/validate-alerting.ts +428 -0
- package/src/validate-output.ts +332 -101
- package/src/validate.ts +14 -0
- package/src/variables.ts +7 -2
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TemplateIR` -> TypeScript, for `chant import`.
|
|
3
|
+
*
|
|
4
|
+
* The parser has already decided what every declaration is (./model.ts);
|
|
5
|
+
* this module decides only how the plan is written, the way the lexicon's
|
|
6
|
+
* examples are written:
|
|
7
|
+
*
|
|
8
|
+
* - one constant per declaration, named from its title (`CPU Busy` becomes
|
|
9
|
+
* `cpuBusy`; a panel's queries take its name and their refId, `cpuBusyA`);
|
|
10
|
+
* - a nested value lifted into a named const typed by the class's props
|
|
11
|
+
* (`const cpuBusyOptions: PropsOf<typeof GaugePanel>["options"] = …`),
|
|
12
|
+
* which is what COR001 asks;
|
|
13
|
+
* - at most eight declarables per module (COR009): a module group with
|
|
14
|
+
* more is split into `<file>-1.ts`, `<file>-2.ts`, …, keeping a panel with
|
|
15
|
+
* its queries;
|
|
16
|
+
* - an `export { … }` list at the end of each module (COR004), naming what
|
|
17
|
+
* another module imports, and the dashboard;
|
|
18
|
+
* - classes the plan declares (`definePanel`, `defineQuery`) in their own
|
|
19
|
+
* module, imported where they are used.
|
|
20
|
+
*
|
|
21
|
+
* A dashboard's modules go in a directory of their own (`plan.directory`),
|
|
22
|
+
* so importing a second dashboard into the same project does not collide
|
|
23
|
+
* with the first.
|
|
24
|
+
*
|
|
25
|
+
* Extension points:
|
|
26
|
+
*
|
|
27
|
+
* - `generatePlan(plan)` is the entry point for anything that builds a
|
|
28
|
+
* plan without the parser (live export, #2946).
|
|
29
|
+
* - `DECLARABLES_PER_FILE` is COR009's limit.
|
|
30
|
+
* - Everything Grafana-specific lives in the parser's tables
|
|
31
|
+
* (./mappings.ts); a new class needs no change here.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { GeneratedFile, TypeScriptGenerator } from "@intentius/chant/import/generator";
|
|
35
|
+
import type { TemplateIR } from "@intentius/chant/import/parser";
|
|
36
|
+
import { isCallValue, isDeclRef, type CustomClass, type Declaration, type Plan } from "./model";
|
|
37
|
+
import { DASHBOARD_RESOURCE_TYPE, PROVISIONING_RESOURCE_TYPE, type PlanResourceProperties } from "./parser";
|
|
38
|
+
|
|
39
|
+
const PACKAGE = "@intentius/chant-lexicon-grafana";
|
|
40
|
+
|
|
41
|
+
/** COR009's default: at most this many declarables per file. */
|
|
42
|
+
export const DECLARABLES_PER_FILE = 8;
|
|
43
|
+
|
|
44
|
+
const MAX_LINE = 100;
|
|
45
|
+
|
|
46
|
+
const RESERVED = new Set(
|
|
47
|
+
(
|
|
48
|
+
"break case catch class const continue debugger default delete do else enum export extends false finally for " +
|
|
49
|
+
"function if import in instanceof new null return super switch this throw true try typeof var void while with " +
|
|
50
|
+
"yield let static implements interface package private protected public await arguments eval undefined NaN Infinity"
|
|
51
|
+
).split(" "),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
55
|
+
|
|
56
|
+
function words(text: string): string[] {
|
|
57
|
+
return text.split(/[^A-Za-z0-9]+/).filter((w) => w !== "");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** camelCase of a text, at most six words; an all-caps word (`DS_PROMETHEUS`) is taken as a word, not an acronym per letter. */
|
|
61
|
+
function camel(text: string): string {
|
|
62
|
+
return words(text)
|
|
63
|
+
.slice(0, 6)
|
|
64
|
+
.map((w) => (w.length > 1 && w === w.toUpperCase() && /[A-Z]/.test(w) ? w.charAt(0) + w.slice(1).toLowerCase() : w))
|
|
65
|
+
.map((w, i) => (i === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)))
|
|
66
|
+
.join("");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function pascal(text: string): string {
|
|
70
|
+
return words(text)
|
|
71
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
72
|
+
.join("");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ── TypeScript literals ──────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
/** An expression written as is: a reference to a declared variable. */
|
|
78
|
+
class Code {
|
|
79
|
+
constructor(readonly code: string) {}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** A call to a package function, its arguments laid out like any other value. */
|
|
83
|
+
class Call {
|
|
84
|
+
constructor(
|
|
85
|
+
readonly fn: string,
|
|
86
|
+
readonly args: readonly unknown[],
|
|
87
|
+
) {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function propertyKey(k: string): string {
|
|
91
|
+
return IDENT.test(k) ? k : JSON.stringify(k);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A string literal: double-quoted, single-quoted when that saves escaping
|
|
96
|
+
* `"` (PromQL label matchers read better), or a template literal when the
|
|
97
|
+
* string spans lines.
|
|
98
|
+
*/
|
|
99
|
+
function stringLiteral(s: string): string {
|
|
100
|
+
if (s.includes("\n") && !s.includes("\r")) return `\`${s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\``;
|
|
101
|
+
const double = JSON.stringify(s);
|
|
102
|
+
if (!s.includes('"') || s.includes("'")) return double;
|
|
103
|
+
return `'${double.slice(1, -1).replace(/\\"/g, '"')}'`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function scalarLiteral(v: unknown): string {
|
|
107
|
+
if (v instanceof Code) return v.code;
|
|
108
|
+
if (v === null) return "null";
|
|
109
|
+
if (typeof v === "string") return stringLiteral(v);
|
|
110
|
+
if (typeof v === "number") {
|
|
111
|
+
if (Number.isNaN(v)) return "NaN";
|
|
112
|
+
if (!Number.isFinite(v)) return v > 0 ? "Infinity" : "-Infinity";
|
|
113
|
+
return Object.is(v, -0) ? "-0" : String(v);
|
|
114
|
+
}
|
|
115
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
116
|
+
return JSON.stringify(String(v));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isPlain(v: unknown): v is Record<string, unknown> {
|
|
120
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Code) && !(v instanceof Call);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function inline(v: unknown): string {
|
|
124
|
+
if (v instanceof Call) return `${v.fn}(${v.args.map(inline).join(", ")})`;
|
|
125
|
+
if (Array.isArray(v)) return `[${v.map(inline).join(", ")}]`;
|
|
126
|
+
if (isPlain(v)) {
|
|
127
|
+
const items = Object.entries(v)
|
|
128
|
+
.filter(([, x]) => x !== undefined)
|
|
129
|
+
.map(([k, x]) => `${propertyKey(k)}: ${inline(x)}`);
|
|
130
|
+
return items.length === 0 ? "{}" : `{ ${items.join(", ")} }`;
|
|
131
|
+
}
|
|
132
|
+
return scalarLiteral(v);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** A value as a TypeScript expression, starting at column `col`, indented by `indent` spaces. */
|
|
136
|
+
export function tsLiteral(v: unknown, indent: number, col = indent): string {
|
|
137
|
+
const one = inline(v);
|
|
138
|
+
if (!one.includes("\n") && col + one.length + 2 <= MAX_LINE) return one;
|
|
139
|
+
const pad = " ".repeat(indent + 2);
|
|
140
|
+
const close = " ".repeat(indent);
|
|
141
|
+
if (v instanceof Call && v.args.length > 0) {
|
|
142
|
+
// Leading arguments that fit stay on the call's line; the last is laid out from there.
|
|
143
|
+
const head = `${v.fn}(${v.args.slice(0, -1).map((a) => `${inline(a)}, `).join("")}`;
|
|
144
|
+
return `${head}${tsLiteral(v.args[v.args.length - 1], indent, col + head.length)})`;
|
|
145
|
+
}
|
|
146
|
+
if (Array.isArray(v)) {
|
|
147
|
+
if (v.length === 0) return "[]";
|
|
148
|
+
return `[\n${v.map((x) => `${pad}${tsLiteral(x, indent + 2)},`).join("\n")}\n${close}]`;
|
|
149
|
+
}
|
|
150
|
+
if (isPlain(v)) {
|
|
151
|
+
const lines: string[] = [];
|
|
152
|
+
for (const [k, x] of Object.entries(v)) {
|
|
153
|
+
if (x === undefined) continue;
|
|
154
|
+
const key = `${pad}${propertyKey(k)}: `;
|
|
155
|
+
lines.push(`${key}${tsLiteral(x, indent + 2, key.length)},`);
|
|
156
|
+
}
|
|
157
|
+
return lines.length === 0 ? "{}" : `{\n${lines.join("\n")}\n${close}}`;
|
|
158
|
+
}
|
|
159
|
+
return scalarLiteral(v);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** True for a value COR001 wants in a named const rather than inline in a constructor. */
|
|
163
|
+
function needsHoist(v: unknown): boolean {
|
|
164
|
+
if (Array.isArray(v)) return v.some((x) => (typeof x === "object" && x !== null && !(x instanceof Code)) || Array.isArray(x));
|
|
165
|
+
if (v instanceof Call) return true;
|
|
166
|
+
return isPlain(v);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ── modules ──────────────────────────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
/** One generated module: what it imports, declares and exports. */
|
|
172
|
+
class Module {
|
|
173
|
+
readonly values = new Set<string>();
|
|
174
|
+
readonly types = new Set<string>();
|
|
175
|
+
readonly local = new Map<Module, Set<string>>();
|
|
176
|
+
readonly body: string[] = [];
|
|
177
|
+
readonly exports = new Set<string>();
|
|
178
|
+
/** Names declared here, in order, so the export list follows the file. */
|
|
179
|
+
readonly declared: string[] = [];
|
|
180
|
+
declarables = 0;
|
|
181
|
+
constructor(
|
|
182
|
+
readonly path: string,
|
|
183
|
+
readonly summary: string,
|
|
184
|
+
) {}
|
|
185
|
+
|
|
186
|
+
block(lines: string[]): void {
|
|
187
|
+
if (this.body.length > 0) this.body.push("");
|
|
188
|
+
this.body.push(...lines);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
render(): string {
|
|
192
|
+
const byName = (a: string, b: string) => a.localeCompare(b, "en", { sensitivity: "base" });
|
|
193
|
+
const names = [...this.values, ...[...this.types].filter((t) => !this.values.has(t)).map((t) => `type ${t}`)].sort((a, b) =>
|
|
194
|
+
byName(a.replace(/^type /, ""), b.replace(/^type /, "")),
|
|
195
|
+
);
|
|
196
|
+
const lines = [`/** ${this.summary} */`];
|
|
197
|
+
if (names.length > 0) {
|
|
198
|
+
const one = `import { ${names.join(", ")} } from "${PACKAGE}";`;
|
|
199
|
+
lines.push(one.length <= MAX_LINE ? one : `import {\n${names.map((n) => ` ${n},`).join("\n")}\n} from "${PACKAGE}";`);
|
|
200
|
+
}
|
|
201
|
+
const dir = this.path.includes("/") ? this.path.slice(0, this.path.lastIndexOf("/") + 1) : "";
|
|
202
|
+
const specs = [...this.local].map(([m, set]) => [`./${m.path.slice(dir.length).replace(/\.ts$/, "")}`, set] as const);
|
|
203
|
+
for (const [spec, set] of specs.sort(([a], [b]) => byName(a, b))) {
|
|
204
|
+
const one = `import { ${[...set].sort(byName).join(", ")} } from "${spec}";`;
|
|
205
|
+
lines.push(one.length <= MAX_LINE ? one : `import {\n${[...set].sort(byName).map((n) => ` ${n},`).join("\n")}\n} from "${spec}";`);
|
|
206
|
+
}
|
|
207
|
+
lines.push("", ...this.body);
|
|
208
|
+
if (this.exports.size > 0) {
|
|
209
|
+
const names = this.declared.filter((n) => this.exports.has(n));
|
|
210
|
+
const one = `export { ${names.join(", ")} };`;
|
|
211
|
+
lines.push("", one.length <= MAX_LINE ? one : `export {\n${names.map((e) => ` ${e},`).join("\n")}\n};`);
|
|
212
|
+
}
|
|
213
|
+
return `${lines.join("\n")}\n`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ── naming ───────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
class Names {
|
|
220
|
+
private readonly taken = new Set<string>();
|
|
221
|
+
|
|
222
|
+
constructor(reserved: Iterable<string>) {
|
|
223
|
+
for (const r of reserved) this.taken.add(r);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
take(base: string, fallback: string): string {
|
|
227
|
+
let b = camel(base);
|
|
228
|
+
if (b === "" || /^[0-9]/.test(b)) b = camel(`${fallback} ${base}`);
|
|
229
|
+
if (b === "" || /^[0-9]/.test(b)) b = camel(fallback);
|
|
230
|
+
let out = b;
|
|
231
|
+
for (let n = 2; this.taken.has(out) || RESERVED.has(out); n++) out = `${b}${n}`;
|
|
232
|
+
this.taken.add(out);
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function assignNames(plan: Plan): Map<string, string> {
|
|
238
|
+
const names = new Map<string, string>();
|
|
239
|
+
const classNames = plan.customClasses.map((c) => c.className);
|
|
240
|
+
const namer = new Names(["PropsOf", "DatasourceRef", "definePanel", "defineQuery", ...classNames]);
|
|
241
|
+
for (const d of plan.declarations) {
|
|
242
|
+
if (typeof d.name === "string") names.set(d.id, namer.take(d.name, d.kind === "value" ? "datasource" : d.id.split(":")[0]));
|
|
243
|
+
}
|
|
244
|
+
for (const d of plan.declarations) {
|
|
245
|
+
if (typeof d.name === "string") continue;
|
|
246
|
+
const base = names.get(d.name.of) ?? d.name.of;
|
|
247
|
+
names.set(d.id, namer.take(`${base} ${d.name.suffix}`, "query"));
|
|
248
|
+
}
|
|
249
|
+
return names;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ── layout ───────────────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
/** Which file each declaration goes to: module groups split at `DECLARABLES_PER_FILE`, by unit. */
|
|
255
|
+
function layout(plan: Plan): { modules: Module[]; home: Map<string, Module> } {
|
|
256
|
+
const modules: Module[] = [];
|
|
257
|
+
const home = new Map<string, Module>();
|
|
258
|
+
const prefix = plan.directory === "" ? "" : `${plan.directory}/`;
|
|
259
|
+
|
|
260
|
+
if (plan.customClasses.length > 0) {
|
|
261
|
+
const spec = plan.modules.find((m) => m.key === "plugins");
|
|
262
|
+
const mod = new Module(`${prefix}${spec?.file ?? "plugins"}.ts`, spec?.summary ?? "Classes for plugins chant has no class for");
|
|
263
|
+
modules.push(mod);
|
|
264
|
+
for (const c of plan.customClasses) home.set(c.id, mod);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
for (const spec of plan.modules) {
|
|
268
|
+
if (spec.key === "plugins") continue;
|
|
269
|
+
const decls = plan.declarations.filter((d) => d.module === spec.key);
|
|
270
|
+
if (decls.length === 0) continue;
|
|
271
|
+
// Units in declaration order, each with its declarable count.
|
|
272
|
+
const units: Array<{ decls: Declaration[]; count: number }> = [];
|
|
273
|
+
const byUnit = new Map<string, { decls: Declaration[]; count: number }>();
|
|
274
|
+
for (const d of decls) {
|
|
275
|
+
const key = d.unit ?? d.id;
|
|
276
|
+
let u = byUnit.get(key);
|
|
277
|
+
if (!u) {
|
|
278
|
+
u = { decls: [], count: 0 };
|
|
279
|
+
byUnit.set(key, u);
|
|
280
|
+
units.push(u);
|
|
281
|
+
}
|
|
282
|
+
u.decls.push(d);
|
|
283
|
+
if (d.kind === "new") u.count++;
|
|
284
|
+
}
|
|
285
|
+
const total = units.reduce((n, u) => n + u.count, 0);
|
|
286
|
+
const chunks: Declaration[][] = [];
|
|
287
|
+
if (total <= DECLARABLES_PER_FILE) chunks.push(decls);
|
|
288
|
+
else {
|
|
289
|
+
let current: Declaration[] = [];
|
|
290
|
+
let count = 0;
|
|
291
|
+
const flush = () => {
|
|
292
|
+
if (current.length > 0) chunks.push(current);
|
|
293
|
+
current = [];
|
|
294
|
+
count = 0;
|
|
295
|
+
};
|
|
296
|
+
for (const u of units) {
|
|
297
|
+
if (count + u.count > DECLARABLES_PER_FILE) flush();
|
|
298
|
+
if (u.count > DECLARABLES_PER_FILE) {
|
|
299
|
+
// A panel with more queries than fit: split the unit itself.
|
|
300
|
+
for (const d of u.decls) {
|
|
301
|
+
if (d.kind === "new" && count + 1 > DECLARABLES_PER_FILE) flush();
|
|
302
|
+
current.push(d);
|
|
303
|
+
if (d.kind === "new") count++;
|
|
304
|
+
}
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
current.push(...u.decls);
|
|
308
|
+
count += u.count;
|
|
309
|
+
}
|
|
310
|
+
flush();
|
|
311
|
+
}
|
|
312
|
+
chunks.forEach((chunk, i) => {
|
|
313
|
+
const file = chunks.length === 1 ? spec.file : `${spec.file}-${i + 1}`;
|
|
314
|
+
const mod = new Module(`${prefix}${file}.ts`, chunks.length === 1 ? spec.summary : `${spec.summary} (${i + 1} of ${chunks.length})`);
|
|
315
|
+
modules.push(mod);
|
|
316
|
+
for (const d of chunk) home.set(d.id, mod);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return { modules, home };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// ── generation ───────────────────────────────────────────────────────
|
|
323
|
+
|
|
324
|
+
/** The TypeScript for one plan: its modules, in the order they should be read. */
|
|
325
|
+
export function generatePlan(plan: Plan): GeneratedFile[] {
|
|
326
|
+
return generatePlanModules(plan).files;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* The TypeScript for one plan, and where each declaration the plan exports
|
|
331
|
+
* is declared: its module's path and variable (#2962: a ConfigMap holding
|
|
332
|
+
* the dashboard refers to it).
|
|
333
|
+
*/
|
|
334
|
+
export function generatePlanModules(plan: Plan): {
|
|
335
|
+
files: GeneratedFile[];
|
|
336
|
+
exported: Map<string, { path: string; name: string }>;
|
|
337
|
+
} {
|
|
338
|
+
const names = assignNames(plan);
|
|
339
|
+
const { modules, home } = layout(plan);
|
|
340
|
+
const byId = new Map(plan.declarations.map((d) => [d.id, d]));
|
|
341
|
+
const classes = new Map(plan.customClasses.map((c) => [c.id, c]));
|
|
342
|
+
|
|
343
|
+
const hoisted = new Set<string>([...names.values(), ...plan.customClasses.map((c) => c.className)]);
|
|
344
|
+
const constName = (base: string) => {
|
|
345
|
+
let out = base;
|
|
346
|
+
for (let n = 2; hoisted.has(out) || RESERVED.has(out); n++) out = `${base}${n}`;
|
|
347
|
+
hoisted.add(out);
|
|
348
|
+
return out;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/** A reference from `mod` to a declaration or custom class, importing it when it lives elsewhere. */
|
|
352
|
+
const refer = (mod: Module, id: string, name: string): Code => {
|
|
353
|
+
const from = home.get(id);
|
|
354
|
+
if (from && from !== mod) {
|
|
355
|
+
const set = mod.local.get(from) ?? new Set<string>();
|
|
356
|
+
set.add(name);
|
|
357
|
+
mod.local.set(from, set);
|
|
358
|
+
from.exports.add(name);
|
|
359
|
+
}
|
|
360
|
+
return new Code(name);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/** Replace declaration references in a value with the variables they name. */
|
|
364
|
+
const resolve = (mod: Module, v: unknown): unknown => {
|
|
365
|
+
if (isDeclRef(v)) {
|
|
366
|
+
const target = byId.get(v.$decl);
|
|
367
|
+
if (!target) throw new Error(`grafana import: the plan refers to "${v.$decl}", which it does not declare`);
|
|
368
|
+
return refer(mod, v.$decl, names.get(v.$decl)!);
|
|
369
|
+
}
|
|
370
|
+
if (isCallValue(v)) {
|
|
371
|
+
mod.values.add(v.$call);
|
|
372
|
+
return new Call(v.$call, v.args.map((x) => resolve(mod, x)));
|
|
373
|
+
}
|
|
374
|
+
if (Array.isArray(v)) return v.map((x) => resolve(mod, x));
|
|
375
|
+
if (isPlain(v)) return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, resolve(mod, x)]));
|
|
376
|
+
return v;
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// Custom classes.
|
|
380
|
+
for (const c of plan.customClasses) {
|
|
381
|
+
const mod = home.get(c.id)!;
|
|
382
|
+
mod.values.add(c.factory);
|
|
383
|
+
const head = `const ${c.className} = ${c.factory}()(`;
|
|
384
|
+
mod.block([...c.comment, `${head}${tsLiteral(c.definition, 0, head.length)});`]);
|
|
385
|
+
mod.declared.push(c.className);
|
|
386
|
+
mod.exports.add(c.className);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
for (const d of plan.declarations) {
|
|
390
|
+
const mod = home.get(d.id)!;
|
|
391
|
+
const name = names.get(d.id)!;
|
|
392
|
+
const lines: string[] = [...(d.comment ?? [])];
|
|
393
|
+
if (d.kind === "value") {
|
|
394
|
+
for (const t of d.type?.imports ?? []) mod.types.add(t);
|
|
395
|
+
const head = `const ${name}${d.type ? `: ${d.type.text}` : ""} = `;
|
|
396
|
+
lines.push(`${head}${tsLiteral(resolve(mod, d.value), 0, head.length)};`);
|
|
397
|
+
} else {
|
|
398
|
+
const className = d.className!;
|
|
399
|
+
let classRef: string;
|
|
400
|
+
if (d.customClass) {
|
|
401
|
+
const c = classes.get(d.customClass) as CustomClass;
|
|
402
|
+
classRef = refer(mod, c.id, c.className).code;
|
|
403
|
+
} else {
|
|
404
|
+
mod.values.add(className);
|
|
405
|
+
classRef = className;
|
|
406
|
+
}
|
|
407
|
+
mod.declarables++;
|
|
408
|
+
const entries: Array<[string, string]> = [];
|
|
409
|
+
for (const [key, raw] of Object.entries(d.props ?? {})) {
|
|
410
|
+
if (raw === undefined) continue;
|
|
411
|
+
const value = resolve(mod, raw);
|
|
412
|
+
if (!needsHoist(value)) {
|
|
413
|
+
entries.push([key, tsLiteral(value, 2, 4 + key.length)]);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
mod.types.add("PropsOf");
|
|
417
|
+
const cn = constName(`${name}${pascal(key) || "Value"}`);
|
|
418
|
+
const head = `const ${cn}: PropsOf<typeof ${classRef}>[${JSON.stringify(key)}] = `;
|
|
419
|
+
lines.push(`${head}${tsLiteral(value, 0, head.length)};`);
|
|
420
|
+
entries.push([key, cn]);
|
|
421
|
+
}
|
|
422
|
+
const head = `const ${name} = new ${classRef}(`;
|
|
423
|
+
const prop = ([k, v]: [string, string]) => (k === v && IDENT.test(k) ? k : `${propertyKey(k)}: ${v}`);
|
|
424
|
+
const one = `{ ${entries.map(prop).join(", ")} }`;
|
|
425
|
+
const args =
|
|
426
|
+
entries.length === 0
|
|
427
|
+
? "{}"
|
|
428
|
+
: !one.includes("\n") && head.length + one.length + 2 <= MAX_LINE
|
|
429
|
+
? one
|
|
430
|
+
: `{\n${entries.map((e) => ` ${prop(e)},`).join("\n")}\n}`;
|
|
431
|
+
lines.push(`${head}${args});`);
|
|
432
|
+
}
|
|
433
|
+
mod.block(lines);
|
|
434
|
+
mod.declared.push(name);
|
|
435
|
+
if (plan.exports.includes(d.id)) mod.exports.add(name);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const exported = new Map<string, { path: string; name: string }>();
|
|
439
|
+
for (const id of plan.exports) {
|
|
440
|
+
const mod = home.get(id);
|
|
441
|
+
const name = names.get(id);
|
|
442
|
+
if (mod && name) exported.set(id, { path: mod.path, name });
|
|
443
|
+
}
|
|
444
|
+
return { files: modules.map((m) => ({ path: m.path, content: m.render() })), exported };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** The Grafana TypeScript generator `chant import` runs. */
|
|
448
|
+
export class GrafanaGenerator implements TypeScriptGenerator {
|
|
449
|
+
/** Core writes exactly the files returned: a dashboard's modules refer to each other and live in its own directory. */
|
|
450
|
+
readonly ownsLayout = true;
|
|
451
|
+
|
|
452
|
+
generate(ir: TemplateIR): GeneratedFile[] {
|
|
453
|
+
const files: GeneratedFile[] = [];
|
|
454
|
+
for (const r of ir.resources) {
|
|
455
|
+
if (r.type !== DASHBOARD_RESOURCE_TYPE && r.type !== PROVISIONING_RESOURCE_TYPE) continue;
|
|
456
|
+
const { plan } = r.properties as unknown as PlanResourceProperties;
|
|
457
|
+
files.push(...generatePlan(plan));
|
|
458
|
+
}
|
|
459
|
+
// Nothing to write for a v2 or pre-5.0 dashboard: the import warnings say why.
|
|
460
|
+
return files;
|
|
461
|
+
}
|
|
462
|
+
}
|