@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.
Files changed (451) hide show
  1. package/README.md +15 -5
  2. package/dist/actions/grafana.d.ts +24 -0
  3. package/dist/actions/grafana.d.ts.map +1 -0
  4. package/dist/actions/index.d.ts +2 -0
  5. package/dist/actions/index.d.ts.map +1 -0
  6. package/dist/alerting-build.d.ts +128 -0
  7. package/dist/alerting-build.d.ts.map +1 -0
  8. package/dist/alerting.d.ts +273 -0
  9. package/dist/alerting.d.ts.map +1 -0
  10. package/dist/api/apply.d.ts +156 -0
  11. package/dist/api/apply.d.ts.map +1 -0
  12. package/dist/api/bind.d.ts +32 -0
  13. package/dist/api/bind.d.ts.map +1 -0
  14. package/dist/api/client.d.ts +76 -0
  15. package/dist/api/client.d.ts.map +1 -0
  16. package/dist/api/converge.d.ts +33 -0
  17. package/dist/api/converge.d.ts.map +1 -0
  18. package/dist/api/dashboards.d.ts +102 -0
  19. package/dist/api/dashboards.d.ts.map +1 -0
  20. package/dist/api/datasources.d.ts +26 -0
  21. package/dist/api/datasources.d.ts.map +1 -0
  22. package/dist/api/fake-grafana-writes.d.ts +41 -0
  23. package/dist/api/fake-grafana-writes.d.ts.map +1 -0
  24. package/dist/api/fake-grafana.d.ts +61 -0
  25. package/dist/api/fake-grafana.d.ts.map +1 -0
  26. package/dist/api/folders.d.ts +110 -0
  27. package/dist/api/folders.d.ts.map +1 -0
  28. package/dist/api/library-panels.d.ts +52 -0
  29. package/dist/api/library-panels.d.ts.map +1 -0
  30. package/dist/build.d.ts +30 -2
  31. package/dist/build.d.ts.map +1 -1
  32. package/dist/catalog.d.ts +1 -1
  33. package/dist/catalog.d.ts.map +1 -1
  34. package/dist/codegen/docs.d.ts.map +1 -1
  35. package/dist/codegen/schema-types.d.ts +3 -3
  36. package/dist/codegen/schema-types.d.ts.map +1 -1
  37. package/dist/composites/agent-dashboard.d.ts.map +1 -1
  38. package/dist/composites/catalog.d.ts.map +1 -1
  39. package/dist/composites/index.d.ts +4 -2
  40. package/dist/composites/index.d.ts.map +1 -1
  41. package/dist/composites/red-dashboard.d.ts +21 -2
  42. package/dist/composites/red-dashboard.d.ts.map +1 -1
  43. package/dist/composites/shared.d.ts +7 -0
  44. package/dist/composites/shared.d.ts.map +1 -1
  45. package/dist/composites/slo-alert-rules.d.ts +92 -0
  46. package/dist/composites/slo-alert-rules.d.ts.map +1 -0
  47. package/dist/config.d.ts +111 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/contact-point-secrets.d.ts +17 -0
  50. package/dist/contact-point-secrets.d.ts.map +1 -0
  51. package/dist/dashboard.d.ts +16 -2
  52. package/dist/dashboard.d.ts.map +1 -1
  53. package/dist/datasource-refs.d.ts +95 -0
  54. package/dist/datasource-refs.d.ts.map +1 -0
  55. package/dist/datasource.d.ts +29 -0
  56. package/dist/datasource.d.ts.map +1 -1
  57. package/dist/deep-observe-hooks.d.ts +64 -0
  58. package/dist/deep-observe-hooks.d.ts.map +1 -0
  59. package/dist/deep-observe.d.ts +42 -0
  60. package/dist/deep-observe.d.ts.map +1 -0
  61. package/dist/describe-resources.d.ts +49 -0
  62. package/dist/describe-resources.d.ts.map +1 -0
  63. package/dist/detect.d.ts +28 -1
  64. package/dist/detect.d.ts.map +1 -1
  65. package/dist/export-resources.d.ts +38 -0
  66. package/dist/export-resources.d.ts.map +1 -0
  67. package/dist/import/alerting.d.ts +40 -0
  68. package/dist/import/alerting.d.ts.map +1 -0
  69. package/dist/import/edits.d.ts +47 -0
  70. package/dist/import/edits.d.ts.map +1 -0
  71. package/dist/import/embedded.d.ts +14 -0
  72. package/dist/import/embedded.d.ts.map +1 -0
  73. package/dist/import/generator.d.ts +60 -0
  74. package/dist/import/generator.d.ts.map +1 -0
  75. package/dist/import/live-export.d.ts +108 -0
  76. package/dist/import/live-export.d.ts.map +1 -0
  77. package/dist/import/mappings.d.ts +83 -0
  78. package/dist/import/mappings.d.ts.map +1 -0
  79. package/dist/import/model.d.ts +98 -0
  80. package/dist/import/model.d.ts.map +1 -0
  81. package/dist/import/normalize-alerting.d.ts +26 -0
  82. package/dist/import/normalize-alerting.d.ts.map +1 -0
  83. package/dist/import/normalize.d.ts +74 -0
  84. package/dist/import/normalize.d.ts.map +1 -0
  85. package/dist/import/parser.d.ts +110 -0
  86. package/dist/import/parser.d.ts.map +1 -0
  87. package/dist/import/report.d.ts +26 -0
  88. package/dist/import/report.d.ts.map +1 -0
  89. package/dist/import/testdata/fixtures.d.ts +35 -0
  90. package/dist/import/testdata/fixtures.d.ts.map +1 -0
  91. package/dist/import/v2.d.ts +72 -0
  92. package/dist/import/v2.d.ts.map +1 -0
  93. package/dist/index.d.ts +26 -9
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/integrity.json +18 -10
  96. package/dist/k8s.d.ts +107 -0
  97. package/dist/k8s.d.ts.map +1 -0
  98. package/dist/lint/audit-catalog.d.ts +2 -1
  99. package/dist/lint/audit-catalog.d.ts.map +1 -1
  100. package/dist/lint/post-synth/graf101.d.ts +2 -2
  101. package/dist/lint/post-synth/graf102.d.ts +1 -1
  102. package/dist/lint/post-synth/graf107.d.ts +1 -1
  103. package/dist/lint/post-synth/graf108.d.ts +8 -0
  104. package/dist/lint/post-synth/graf108.d.ts.map +1 -0
  105. package/dist/lint/post-synth/graf109.d.ts +8 -0
  106. package/dist/lint/post-synth/graf109.d.ts.map +1 -0
  107. package/dist/lint/post-synth/graf111.d.ts +8 -0
  108. package/dist/lint/post-synth/graf111.d.ts.map +1 -0
  109. package/dist/lint/post-synth/graf112.d.ts +8 -0
  110. package/dist/lint/post-synth/graf112.d.ts.map +1 -0
  111. package/dist/lint/post-synth/graf113.d.ts +8 -0
  112. package/dist/lint/post-synth/graf113.d.ts.map +1 -0
  113. package/dist/lint/post-synth/graf114.d.ts +8 -0
  114. package/dist/lint/post-synth/graf114.d.ts.map +1 -0
  115. package/dist/lint/post-synth/graf115.d.ts +8 -0
  116. package/dist/lint/post-synth/graf115.d.ts.map +1 -0
  117. package/dist/lint/post-synth/grafana-helpers.d.ts +7 -5
  118. package/dist/lint/post-synth/grafana-helpers.d.ts.map +1 -1
  119. package/dist/lint/post-synth/index.d.ts.map +1 -1
  120. package/dist/lint/rules/literal-secret.d.ts +7 -3
  121. package/dist/lint/rules/literal-secret.d.ts.map +1 -1
  122. package/dist/lsp/hover.d.ts.map +1 -1
  123. package/dist/manifest.json +1 -1
  124. package/dist/members.d.ts +27 -0
  125. package/dist/members.d.ts.map +1 -0
  126. package/dist/meta.json +135 -0
  127. package/dist/okf/index.md +36 -2
  128. package/dist/okf/rules/GRAF002.md +3 -2
  129. package/dist/okf/rules/GRAF101.md +3 -2
  130. package/dist/okf/rules/GRAF102.md +1 -0
  131. package/dist/okf/rules/GRAF108.md +11 -0
  132. package/dist/okf/rules/GRAF109.md +15 -0
  133. package/dist/okf/rules/GRAF111.md +11 -0
  134. package/dist/okf/rules/GRAF112.md +16 -0
  135. package/dist/okf/rules/GRAF113.md +16 -0
  136. package/dist/okf/rules/GRAF114.md +11 -0
  137. package/dist/okf/rules/GRAF115.md +11 -0
  138. package/dist/okf/types/AlertListPanel.md +9 -0
  139. package/dist/okf/types/AlertQuery.md +9 -0
  140. package/dist/okf/types/AlertRule.md +9 -0
  141. package/dist/okf/types/AlertRuleGroup.md +9 -0
  142. package/dist/okf/types/BarChartPanel.md +9 -0
  143. package/dist/okf/types/BarGaugePanel.md +9 -0
  144. package/dist/okf/types/CanvasPanel.md +9 -0
  145. package/dist/okf/types/ClassicConditionsExpression.md +9 -0
  146. package/dist/okf/types/ContactPoint.md +14 -0
  147. package/dist/okf/types/Dashboard.md +1 -0
  148. package/dist/okf/types/Datasource.md +3 -2
  149. package/dist/okf/types/ExternalDatasource.md +15 -0
  150. package/dist/okf/types/FlameGraphPanel.md +9 -0
  151. package/dist/okf/types/GeomapPanel.md +9 -0
  152. package/dist/okf/types/HistogramPanel.md +9 -0
  153. package/dist/okf/types/MathExpression.md +9 -0
  154. package/dist/okf/types/MuteTiming.md +13 -0
  155. package/dist/okf/types/NodeGraphPanel.md +9 -0
  156. package/dist/okf/types/NotificationPolicy.md +9 -0
  157. package/dist/okf/types/NotificationTemplate.md +9 -0
  158. package/dist/okf/types/PieChartPanel.md +9 -0
  159. package/dist/okf/types/ReduceExpression.md +9 -0
  160. package/dist/okf/types/ResampleExpression.md +9 -0
  161. package/dist/okf/types/SqlExpression.md +9 -0
  162. package/dist/okf/types/StateTimelinePanel.md +9 -0
  163. package/dist/okf/types/StatusHistoryPanel.md +9 -0
  164. package/dist/okf/types/ThresholdExpression.md +9 -0
  165. package/dist/okf/types/TrendPanel.md +9 -0
  166. package/dist/okf/types/XYChartPanel.md +9 -0
  167. package/dist/op/activities/grafana-apply.d.ts +75 -0
  168. package/dist/op/activities/grafana-apply.d.ts.map +1 -0
  169. package/dist/op/activities/index.d.ts +9 -0
  170. package/dist/op/activities/index.d.ts.map +1 -0
  171. package/dist/op/builders.d.ts +24 -0
  172. package/dist/op/builders.d.ts.map +1 -0
  173. package/dist/ownership.d.ts +67 -0
  174. package/dist/ownership.d.ts.map +1 -0
  175. package/dist/panel-options.d.ts +65 -0
  176. package/dist/panel-options.d.ts.map +1 -0
  177. package/dist/panels.d.ts +46 -9
  178. package/dist/panels.d.ts.map +1 -1
  179. package/dist/pin.d.ts +29 -7
  180. package/dist/pin.d.ts.map +1 -1
  181. package/dist/plugin.d.ts.map +1 -1
  182. package/dist/promql-check.d.ts +51 -0
  183. package/dist/promql-check.d.ts.map +1 -0
  184. package/dist/query.d.ts +9 -8
  185. package/dist/query.d.ts.map +1 -1
  186. package/dist/rules/graf101.ts +3 -3
  187. package/dist/rules/graf102.ts +1 -1
  188. package/dist/rules/graf107.ts +1 -1
  189. package/dist/rules/graf108.ts +17 -0
  190. package/dist/rules/graf109.ts +17 -0
  191. package/dist/rules/graf111.ts +17 -0
  192. package/dist/rules/graf112.ts +17 -0
  193. package/dist/rules/graf113.ts +17 -0
  194. package/dist/rules/graf114.ts +17 -0
  195. package/dist/rules/graf115.ts +17 -0
  196. package/dist/rules/grafana-helpers.ts +15 -8
  197. package/dist/rules/literal-secret.ts +60 -6
  198. package/dist/schema/barchart.gen.d.ts +198 -0
  199. package/dist/schema/barchart.gen.d.ts.map +1 -0
  200. package/dist/schema/bargauge.gen.d.ts +97 -0
  201. package/dist/schema/bargauge.gen.d.ts.map +1 -0
  202. package/dist/schema/canvas.gen.d.ts +152 -0
  203. package/dist/schema/canvas.gen.d.ts.map +1 -0
  204. package/dist/schema/dashboard.gen.d.ts +196 -21
  205. package/dist/schema/dashboard.gen.d.ts.map +1 -1
  206. package/dist/schema/expr.gen.d.ts +606 -0
  207. package/dist/schema/expr.gen.d.ts.map +1 -0
  208. package/dist/schema/gauge.gen.d.ts.map +1 -1
  209. package/dist/schema/geomap.gen.d.ts +100 -0
  210. package/dist/schema/geomap.gen.d.ts.map +1 -0
  211. package/dist/schema/heatmap.gen.d.ts.map +1 -1
  212. package/dist/schema/histogram.gen.d.ts +132 -0
  213. package/dist/schema/histogram.gen.d.ts.map +1 -0
  214. package/dist/schema/index.d.ts +12 -0
  215. package/dist/schema/index.d.ts.map +1 -1
  216. package/dist/schema/logs.gen.d.ts +1 -0
  217. package/dist/schema/logs.gen.d.ts.map +1 -1
  218. package/dist/schema/loki.gen.d.ts.map +1 -1
  219. package/dist/schema/nodegraph.gen.d.ts +49 -0
  220. package/dist/schema/nodegraph.gen.d.ts.map +1 -0
  221. package/dist/schema/piechart.gen.d.ts +127 -0
  222. package/dist/schema/piechart.gen.d.ts.map +1 -0
  223. package/dist/schema/prometheus.gen.d.ts.map +1 -1
  224. package/dist/schema/stat.gen.d.ts.map +1 -1
  225. package/dist/schema/statetimeline.gen.d.ts +124 -0
  226. package/dist/schema/statetimeline.gen.d.ts.map +1 -0
  227. package/dist/schema/statushistory.gen.d.ts +114 -0
  228. package/dist/schema/statushistory.gen.d.ts.map +1 -0
  229. package/dist/schema/table.gen.d.ts +22 -3
  230. package/dist/schema/table.gen.d.ts.map +1 -1
  231. package/dist/schema/tempo.gen.d.ts.map +1 -1
  232. package/dist/schema/text.gen.d.ts.map +1 -1
  233. package/dist/schema/timeseries.gen.d.ts +5 -1
  234. package/dist/schema/timeseries.gen.d.ts.map +1 -1
  235. package/dist/schema/trend.gen.d.ts +180 -0
  236. package/dist/schema/trend.gen.d.ts.map +1 -0
  237. package/dist/schema/xychart.gen.d.ts +145 -0
  238. package/dist/schema/xychart.gen.d.ts.map +1 -0
  239. package/dist/schema-validate.d.ts +30 -4
  240. package/dist/schema-validate.d.ts.map +1 -1
  241. package/dist/serializer.d.ts +11 -3
  242. package/dist/serializer.d.ts.map +1 -1
  243. package/dist/skill-defs.d.ts.map +1 -1
  244. package/dist/skills/chant-grafana-alerting.md +49 -0
  245. package/dist/skills/chant-grafana-provisioning.md +3 -3
  246. package/dist/skills/chant-grafana.md +12 -6
  247. package/dist/spec/fetch-units-cli.d.ts +3 -0
  248. package/dist/spec/fetch-units-cli.d.ts.map +1 -0
  249. package/dist/spec/overlay.d.ts +43 -0
  250. package/dist/spec/overlay.d.ts.map +1 -0
  251. package/dist/spec/schemas.d.ts +13 -7
  252. package/dist/spec/schemas.d.ts.map +1 -1
  253. package/dist/spec/units.d.ts +35 -0
  254. package/dist/spec/units.d.ts.map +1 -0
  255. package/dist/spec/units.gen.d.ts +2 -0
  256. package/dist/spec/units.gen.d.ts.map +1 -0
  257. package/dist/transformations.d.ts +459 -0
  258. package/dist/transformations.d.ts.map +1 -0
  259. package/dist/util.d.ts +6 -0
  260. package/dist/util.d.ts.map +1 -1
  261. package/dist/validate-alerting.d.ts +65 -0
  262. package/dist/validate-alerting.d.ts.map +1 -0
  263. package/dist/validate-output.d.ts +49 -9
  264. package/dist/validate-output.d.ts.map +1 -1
  265. package/dist/validate.d.ts.map +1 -1
  266. package/dist/variables.d.ts +7 -2
  267. package/dist/variables.d.ts.map +1 -1
  268. package/package.json +12 -4
  269. package/src/actions/actions.test.ts +24 -0
  270. package/src/actions/grafana.ts +40 -0
  271. package/src/actions/index.ts +1 -0
  272. package/src/alerting-build.ts +376 -0
  273. package/src/alerting.e2e.test.ts +212 -0
  274. package/src/alerting.test.ts +272 -0
  275. package/src/alerting.ts +435 -0
  276. package/src/api/apply.test.ts +238 -0
  277. package/src/api/apply.ts +384 -0
  278. package/src/api/bind.ts +58 -0
  279. package/src/api/client.ts +148 -0
  280. package/src/api/converge.ts +63 -0
  281. package/src/api/dashboards.ts +247 -0
  282. package/src/api/datasources.ts +33 -0
  283. package/src/api/fake-grafana-writes.ts +201 -0
  284. package/src/api/fake-grafana.ts +186 -0
  285. package/src/api/folders.ts +265 -0
  286. package/src/api/library-panels.ts +101 -0
  287. package/src/build.test.ts +210 -5
  288. package/src/build.ts +180 -43
  289. package/src/catalog.ts +86 -2
  290. package/src/codegen/docs.ts +42 -9
  291. package/src/codegen/schema-types.ts +16 -6
  292. package/src/composites/agent-dashboard.ts +6 -3
  293. package/src/composites/catalog.test.ts +2 -2
  294. package/src/composites/catalog.ts +82 -0
  295. package/src/composites/composites.test.ts +73 -9
  296. package/src/composites/index.ts +4 -2
  297. package/src/composites/queries.e2e.test.ts +374 -0
  298. package/src/composites/red-dashboard.ts +83 -12
  299. package/src/composites/shared.ts +11 -0
  300. package/src/composites/slo-alert-rules.ts +149 -0
  301. package/src/config.test.ts +61 -0
  302. package/src/config.ts +138 -0
  303. package/src/contact-point-secrets.ts +63 -0
  304. package/src/dashboard.ts +16 -2
  305. package/src/datasource-refs.test.ts +56 -0
  306. package/src/datasource-refs.ts +189 -0
  307. package/src/datasource.ts +52 -0
  308. package/src/deep-observe-hooks.ts +252 -0
  309. package/src/deep-observe.test.ts +265 -0
  310. package/src/deep-observe.ts +164 -0
  311. package/src/describe-resources.test.ts +255 -0
  312. package/src/describe-resources.ts +209 -0
  313. package/src/detect.ts +79 -2
  314. package/src/export-resources.test.ts +129 -0
  315. package/src/export-resources.ts +84 -0
  316. package/src/generated/lexicon-grafana.json +135 -0
  317. package/src/import/alerting-roundtrip.test.ts +161 -0
  318. package/src/import/alerting.ts +500 -0
  319. package/src/import/edits.ts +95 -0
  320. package/src/import/embedded.test.ts +45 -0
  321. package/src/import/embedded.ts +47 -0
  322. package/src/import/generated-types.e2e.test.ts +118 -0
  323. package/src/import/generator.test.ts +210 -0
  324. package/src/import/generator.ts +462 -0
  325. package/src/import/live-export.ts +264 -0
  326. package/src/import/mappings.ts +264 -0
  327. package/src/import/model.ts +110 -0
  328. package/src/import/normalize-alerting.ts +101 -0
  329. package/src/import/normalize.test.ts +117 -0
  330. package/src/import/normalize.ts +364 -0
  331. package/src/import/parser.test.ts +440 -0
  332. package/src/import/parser.ts +1236 -0
  333. package/src/import/report.ts +62 -0
  334. package/src/import/roundtrip.test.ts +468 -0
  335. package/src/import/testdata/fixtures.ts +129 -0
  336. package/src/import/v2.test.ts +292 -0
  337. package/src/import/v2.ts +803 -0
  338. package/src/import.e2e.test.ts +31 -84
  339. package/src/import.test.ts +9 -3
  340. package/src/index.ts +190 -5
  341. package/src/k8s.test.ts +98 -0
  342. package/src/k8s.ts +197 -0
  343. package/src/lint/audit-catalog.ts +60 -3
  344. package/src/lint/core-lint.test.ts +43 -0
  345. package/src/lint/post-synth/graf101.ts +3 -3
  346. package/src/lint/post-synth/graf102.ts +1 -1
  347. package/src/lint/post-synth/graf107.ts +1 -1
  348. package/src/lint/post-synth/graf108.ts +17 -0
  349. package/src/lint/post-synth/graf109.ts +17 -0
  350. package/src/lint/post-synth/graf111.ts +17 -0
  351. package/src/lint/post-synth/graf112.ts +17 -0
  352. package/src/lint/post-synth/graf113.ts +17 -0
  353. package/src/lint/post-synth/graf114.ts +17 -0
  354. package/src/lint/post-synth/graf115.ts +17 -0
  355. package/src/lint/post-synth/grafana-helpers.ts +15 -8
  356. package/src/lint/post-synth/index.ts +14 -0
  357. package/src/lint/post-synth/post-synth.test.ts +235 -11
  358. package/src/lint/rules/literal-secret.ts +60 -6
  359. package/src/lint/rules/rules.test.ts +27 -0
  360. package/src/lsp/completions.test.ts +5 -0
  361. package/src/lsp/hover.test.ts +7 -0
  362. package/src/lsp/hover.ts +8 -1
  363. package/src/members.ts +68 -0
  364. package/src/observe.e2e.test.ts +255 -0
  365. package/src/op/activities/grafana-apply.e2e.test.ts +175 -0
  366. package/src/op/activities/grafana-apply.test.ts +229 -0
  367. package/src/op/activities/grafana-apply.ts +171 -0
  368. package/src/op/activities/index.ts +8 -0
  369. package/src/op/builders.test.ts +40 -0
  370. package/src/op/builders.ts +34 -0
  371. package/src/ownership.ts +103 -0
  372. package/src/panel-options.ts +66 -0
  373. package/src/panels.test.ts +51 -0
  374. package/src/panels.ts +148 -10
  375. package/src/pin.ts +57 -6
  376. package/src/plugin.test.ts +5 -2
  377. package/src/plugin.ts +66 -0
  378. package/src/promql-check.test.ts +108 -0
  379. package/src/promql-check.ts +189 -0
  380. package/src/query.ts +13 -8
  381. package/src/schema/barchart.gen.ts +221 -0
  382. package/src/schema/bargauge.gen.ts +111 -0
  383. package/src/schema/canvas.gen.ts +176 -0
  384. package/src/schema/dashboard.gen.ts +206 -22
  385. package/src/schema/expr.gen.ts +618 -0
  386. package/src/schema/gauge.gen.ts +2 -1
  387. package/src/schema/geomap.gen.ts +112 -0
  388. package/src/schema/heatmap.gen.ts +2 -1
  389. package/src/schema/histogram.gen.ts +151 -0
  390. package/src/schema/index.ts +12 -0
  391. package/src/schema/logs.gen.ts +3 -1
  392. package/src/schema/loki.gen.ts +2 -1
  393. package/src/schema/nodegraph.gen.ts +58 -0
  394. package/src/schema/piechart.gen.ts +146 -0
  395. package/src/schema/prometheus.gen.ts +2 -1
  396. package/src/schema/stat.gen.ts +2 -1
  397. package/src/schema/statetimeline.gen.ts +143 -0
  398. package/src/schema/statushistory.gen.ts +132 -0
  399. package/src/schema/table.gen.ts +27 -4
  400. package/src/schema/tempo.gen.ts +2 -1
  401. package/src/schema/text.gen.ts +2 -1
  402. package/src/schema/timeseries.gen.ts +7 -2
  403. package/src/schema/trend.gen.ts +208 -0
  404. package/src/schema/xychart.gen.ts +167 -0
  405. package/src/schema-overlay.test.ts +282 -0
  406. package/src/schema-validate.ts +141 -50
  407. package/src/schema.test.ts +4 -2
  408. package/src/serializer.test.ts +13 -1
  409. package/src/serializer.ts +11 -3
  410. package/src/skill-defs.ts +17 -0
  411. package/src/skills/chant-grafana-alerting.md +49 -0
  412. package/src/skills/chant-grafana-provisioning.md +3 -3
  413. package/src/skills/chant-grafana.md +12 -6
  414. package/src/spec/fetch-cli.ts +3 -3
  415. package/src/spec/fetch-units-cli.ts +37 -0
  416. package/src/spec/overlay/canvas.overlay.json +142 -0
  417. package/src/spec/overlay/dashboard.overlay.json +378 -0
  418. package/src/spec/overlay/expr.overlay.json +14 -0
  419. package/src/spec/overlay/geomap.overlay.json +35 -0
  420. package/src/spec/overlay/logs.overlay.json +14 -0
  421. package/src/spec/overlay/nodegraph.overlay.json +31 -0
  422. package/src/spec/overlay/piechart.overlay.json +17 -0
  423. package/src/spec/overlay/table.overlay.json +84 -0
  424. package/src/spec/overlay/timeseries.overlay.json +21 -0
  425. package/src/spec/overlay/trend.overlay.json +17 -0
  426. package/src/spec/overlay/xychart.overlay.json +16 -0
  427. package/src/spec/overlay.ts +105 -0
  428. package/src/spec/schemas/barchart.jsonschema.json +419 -0
  429. package/src/spec/schemas/bargauge.jsonschema.json +224 -0
  430. package/src/spec/schemas/canvas.jsonschema.json +356 -0
  431. package/src/spec/schemas/dashboardv2.jsonschema.json +3387 -0
  432. package/src/spec/schemas/expr.jsonschema.json +987 -0
  433. package/src/spec/schemas/geomap.jsonschema.json +220 -0
  434. package/src/spec/schemas/histogram.jsonschema.json +308 -0
  435. package/src/spec/schemas/nodegraph.jsonschema.json +77 -0
  436. package/src/spec/schemas/piechart.jsonschema.json +275 -0
  437. package/src/spec/schemas/statetimeline.jsonschema.json +324 -0
  438. package/src/spec/schemas/statushistory.jsonschema.json +292 -0
  439. package/src/spec/schemas/trend.jsonschema.json +449 -0
  440. package/src/spec/schemas/xychart.jsonschema.json +428 -0
  441. package/src/spec/schemas.ts +22 -10
  442. package/src/spec/units.gen.ts +281 -0
  443. package/src/spec/units.ts +77 -0
  444. package/src/transformations.test.ts +65 -0
  445. package/src/transformations.ts +574 -0
  446. package/src/util.ts +8 -0
  447. package/src/validate-alerting.test.ts +255 -0
  448. package/src/validate-alerting.ts +428 -0
  449. package/src/validate-output.ts +332 -101
  450. package/src/validate.ts +14 -0
  451. package/src/variables.ts +7 -2
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Library panels, for the API applier (#2948).
3
+ *
4
+ * A dashboard that uses a library panel holds only a reference to it
5
+ * (`{ libraryPanel: { uid, name } }`); the panel itself lives in Grafana's
6
+ * library, and an exported dashboard carries its model in `__elements`,
7
+ * keyed by uid. The applier writes each element to the library over
8
+ * `/api/library-elements` before the dashboards that reference it, and
9
+ * sends the dashboards without `__elements`, `__inputs` or `__requires`,
10
+ * which are export-only keys Grafana does not store.
11
+ *
12
+ * The library elements API is the same on Grafana 11, 12.4 and 13.2. It has
13
+ * no labels, so a library panel cannot carry chant's marker and is never
14
+ * pruned (the applier reports that as `not-prunable`). An update needs the
15
+ * element's current `version`, which the read supplies.
16
+ */
17
+
18
+ import type { GrafanaClient } from "./client";
19
+ import { send } from "./folders";
20
+ import { converged } from "./converge";
21
+
22
+ type Json = Record<string, unknown>;
23
+
24
+ function isObject(v: unknown): v is Json {
25
+ return typeof v === "object" && v !== null && !Array.isArray(v);
26
+ }
27
+
28
+ /** `kind` of a library panel in the library elements API (2 is a library variable). */
29
+ export const LIBRARY_PANEL_KIND = 1;
30
+
31
+ /** Keys an exported dashboard carries that Grafana does not store. */
32
+ export const EXPORT_ONLY_KEYS: readonly string[] = ["__elements", "__inputs", "__requires"];
33
+
34
+ /** One library panel a build needs. */
35
+ export interface LibraryPanelPlan {
36
+ readonly uid: string;
37
+ readonly name: string;
38
+ readonly model: Json;
39
+ /** The folder it goes in: that of the first dashboard that carries it. Absent for the General folder. */
40
+ readonly folderUid?: string;
41
+ }
42
+
43
+ /**
44
+ * The library panels in a dashboard's `__elements`. An element that is not a
45
+ * panel (a library variable), or that has no uid, name or model, is not
46
+ * something the library panel API can take; it is returned in `skipped`.
47
+ */
48
+ export function libraryPanelsOf(dashboard: Json, folderUid?: string): { panels: LibraryPanelPlan[]; skipped: string[] } {
49
+ const elements = dashboard.__elements;
50
+ const panels: LibraryPanelPlan[] = [];
51
+ const skipped: string[] = [];
52
+ if (!isObject(elements)) return { panels, skipped };
53
+ for (const [key, el] of Object.entries(elements)) {
54
+ if (!isObject(el)) {
55
+ skipped.push(key);
56
+ continue;
57
+ }
58
+ const uid = typeof el.uid === "string" && el.uid !== "" ? el.uid : key;
59
+ const kind = el.kind ?? LIBRARY_PANEL_KIND;
60
+ if (kind !== LIBRARY_PANEL_KIND || typeof el.name !== "string" || !isObject(el.model)) {
61
+ skipped.push(uid);
62
+ continue;
63
+ }
64
+ panels.push({ uid, name: el.name, model: el.model, ...(folderUid ? { folderUid } : {}) });
65
+ }
66
+ return { panels, skipped };
67
+ }
68
+
69
+ /** A dashboard without the export-only keys, as the applier sends it. */
70
+ export function withoutExportKeys(dashboard: Json): Json {
71
+ const out: Json = { ...dashboard };
72
+ for (const k of EXPORT_ONLY_KEYS) delete out[k];
73
+ return out;
74
+ }
75
+
76
+ export function libraryPanelPath(uid: string): string {
77
+ return `/api/library-elements/${encodeURIComponent(uid)}`;
78
+ }
79
+
80
+ /**
81
+ * Create or update one library panel. Unchanged when its name, folder and
82
+ * model already match; nothing is written then.
83
+ */
84
+ export async function ensureLibraryPanel(
85
+ client: GrafanaClient,
86
+ plan: LibraryPanelPlan,
87
+ ): Promise<{ action: "created" | "updated" | "unchanged"; address: string }> {
88
+ const address = libraryPanelPath(plan.uid);
89
+ const live = (await client.get<{ result?: Json }>(address))?.result;
90
+ const body = { name: plan.name, kind: LIBRARY_PANEL_KIND, model: plan.model, folderUid: plan.folderUid ?? "" };
91
+ if (!live) {
92
+ await send(client, "POST", "/api/library-elements", { uid: plan.uid, ...body });
93
+ return { action: "created", address };
94
+ }
95
+ const liveFolder = typeof live.folderUid === "string" ? live.folderUid : "";
96
+ if (live.name === plan.name && liveFolder === (plan.folderUid ?? "") && converged(plan.model, live.model)) {
97
+ return { action: "unchanged", address };
98
+ }
99
+ await send(client, "PATCH", address, { ...body, version: typeof live.version === "number" ? live.version : 1 });
100
+ return { action: "updated", address };
101
+ }
package/src/build.test.ts CHANGED
@@ -11,13 +11,14 @@ import {
11
11
  QueryVariable,
12
12
  TextboxVariable,
13
13
  } from "./variables";
14
- import { panelsJson, renderDashboard, variableModel, dashboardJson, grafanaFiles, type PanelJson } from "./build";
14
+ import { panelsJson, renderDashboard, variableModel, dashboardJson, grafanaFiles, buildGrafana, customVariableOptions, type PanelJson } from "./build";
15
15
 
16
16
  /** The panels array, read as plain panels (the tests below build no rows unless they say so). */
17
17
  function panelsOnly(items: Parameters<typeof panelsJson>[0]): PanelJson[] {
18
18
  return panelsJson(items) as PanelJson[];
19
19
  }
20
20
  import { validateDashboardSchema } from "./schema-validate";
21
+ import { checkGrid } from "./validate-output";
21
22
 
22
23
  const prometheus = new Datasource({ name: "Prometheus", type: "prometheus" });
23
24
  const tempo = new Datasource({ name: "Tempo", type: "tempo" });
@@ -77,6 +78,138 @@ describe("layout", () => {
77
78
  expect((panels[1] as unknown as { panels: unknown[] }).panels).toEqual([]);
78
79
  });
79
80
 
81
+ test("a row with a y keeps that line, even over an empty band or on a line a panel takes (#2992)", () => {
82
+ const panels = panelsJson([
83
+ new StatPanel({ title: "a", gridPos: { x: 0, y: 0, w: 24, h: 4 } }),
84
+ new Row({ title: "late", gridPos: { y: 6 }, panels: [new StatPanel({ title: "b", gridPos: { x: 0, y: 7, w: 24, h: 4 } })] }),
85
+ new Row({ title: "auto", panels: [new StatPanel({ title: "c" })] }),
86
+ new Row({ title: "early", gridPos: { y: 8 } }),
87
+ ]);
88
+ expect(panels.map((p) => [p.title, p.gridPos])).toEqual([
89
+ ["a", { h: 4, w: 24, x: 0, y: 0 }],
90
+ ["late", { h: 1, w: 24, x: 0, y: 6 }],
91
+ ["b", { h: 4, w: 24, x: 0, y: 7 }],
92
+ // An auto-placed row skips the line the "early" row reserved.
93
+ ["auto", { h: 1, w: 24, x: 0, y: 11 }],
94
+ ["c", { h: 4, w: 6, x: 0, y: 12 }],
95
+ ["early", { h: 1, w: 24, x: 0, y: 8 }],
96
+ ]);
97
+ });
98
+
99
+ test("an auto-placed panel flows around an explicit one declared before it (#2941)", () => {
100
+ const panels = panelsJson([
101
+ new TimeSeriesPanel({ title: "a", gridPos: { x: 0, y: 0, w: 12 } }),
102
+ new TimeSeriesPanel({ title: "b", gridPos: { w: 12 } }),
103
+ ]);
104
+ expect(panels.map((p) => p.gridPos)).toEqual([
105
+ { h: 8, w: 12, x: 0, y: 0 },
106
+ { h: 8, w: 12, x: 12, y: 0 },
107
+ ]);
108
+ });
109
+
110
+ test("an explicit panel reserves its cells even when declared after auto-placed ones", () => {
111
+ const panels = panelsJson([
112
+ new StatPanel({ title: "s1" }),
113
+ new StatPanel({ title: "s2" }),
114
+ new StatPanel({ title: "s3" }),
115
+ new StatPanel({ title: "s4" }),
116
+ new StatPanel({ title: "pinned", gridPos: { x: 6, y: 0, w: 6, h: 4 } }),
117
+ new TextPanel({ title: "wide" }),
118
+ ]);
119
+ expect(panels.map((p) => [p.title, p.gridPos])).toEqual([
120
+ ["s1", { h: 4, w: 6, x: 0, y: 0 }],
121
+ ["s2", { h: 4, w: 6, x: 12, y: 0 }],
122
+ ["s3", { h: 4, w: 6, x: 18, y: 0 }],
123
+ ["s4", { h: 4, w: 6, x: 0, y: 4 }],
124
+ ["pinned", { h: 4, w: 6, x: 6, y: 0 }],
125
+ ["wide", { h: 3, w: 24, x: 0, y: 8 }],
126
+ ]);
127
+ });
128
+
129
+ test("a line blocked by an explicit panel is skipped", () => {
130
+ const panels = panelsJson([
131
+ new StatPanel({ title: "band", gridPos: { x: 0, y: 0, w: 24, h: 2 } }),
132
+ new StatPanel({ title: "hole", gridPos: { x: 0, y: 6, w: 6, h: 2 } }),
133
+ new StatPanel({ title: "s1" }),
134
+ new TextPanel({ title: "wide" }),
135
+ ]);
136
+ expect(panels.map((p) => [p.title, p.gridPos])).toEqual([
137
+ ["band", { h: 2, w: 24, x: 0, y: 0 }],
138
+ ["hole", { h: 2, w: 6, x: 0, y: 6 }],
139
+ ["s1", { h: 4, w: 6, x: 0, y: 2 }],
140
+ ["wide", { h: 3, w: 24, x: 0, y: 8 }],
141
+ ]);
142
+ });
143
+
144
+ test("a partial gridPos is honoured: x only keeps its column, y only its line", () => {
145
+ const panels = panelsJson([
146
+ new StatPanel({ title: "right", gridPos: { x: 18 } }),
147
+ new StatPanel({ title: "left", gridPos: { x: 0 } }),
148
+ new StatPanel({ title: "next" }),
149
+ new StatPanel({ title: "low", gridPos: { y: 20, w: 12 } }),
150
+ new StatPanel({ title: "low2", gridPos: { y: 20, w: 12 } }),
151
+ new StatPanel({ title: "low3", gridPos: { y: 20, w: 12 } }),
152
+ ]);
153
+ expect(panels.map((p) => [p.title, p.gridPos])).toEqual([
154
+ ["right", { h: 4, w: 6, x: 18, y: 0 }],
155
+ ["left", { h: 4, w: 6, x: 0, y: 4 }],
156
+ ["next", { h: 4, w: 6, x: 6, y: 4 }],
157
+ ["low", { h: 4, w: 12, x: 0, y: 20 }],
158
+ ["low2", { h: 4, w: 12, x: 12, y: 20 }],
159
+ ["low3", { h: 4, w: 12, x: 0, y: 24 }],
160
+ ]);
161
+ });
162
+
163
+ test("a full-width row header skips lines taken by explicit panels", () => {
164
+ const panels = panelsJson([
165
+ new TimeSeriesPanel({ title: "top" }),
166
+ new Row({
167
+ title: "open",
168
+ panels: [new StatPanel({ title: "pinned", gridPos: { x: 0, y: 8, w: 24, h: 2 } }), new StatPanel({ title: "a" })],
169
+ }),
170
+ new Row({ title: "next" }),
171
+ ]);
172
+ expect(panels.map((p) => [p.type, p.title, p.gridPos])).toEqual([
173
+ ["timeseries", "top", { h: 8, w: 12, x: 0, y: 0 }],
174
+ ["row", "open", { h: 1, w: 24, x: 0, y: 10 }],
175
+ ["stat", "pinned", { h: 2, w: 24, x: 0, y: 8 }],
176
+ ["stat", "a", { h: 4, w: 6, x: 0, y: 11 }],
177
+ ["row", "next", { h: 1, w: 24, x: 0, y: 15 }],
178
+ ]);
179
+ });
180
+
181
+ test("a collapsed row's panels flow around its own explicit panels and don't block the dashboard", () => {
182
+ const panels = panelsJson([
183
+ new Row({
184
+ title: "shut",
185
+ collapsed: true,
186
+ panels: [new StatPanel({ title: "pinned", gridPos: { x: 0, y: 1, w: 6, h: 4 } }), new StatPanel({ title: "a" })],
187
+ }),
188
+ new StatPanel({ title: "after" }),
189
+ ]);
190
+ const shut = panels[0] as unknown as { panels: PanelJson[] };
191
+ expect(shut.panels.map((p) => [p.title, p.gridPos])).toEqual([
192
+ ["pinned", { h: 4, w: 6, x: 0, y: 1 }],
193
+ ["a", { h: 4, w: 6, x: 6, y: 1 }],
194
+ ]);
195
+ expect(panels[1].gridPos).toEqual({ h: 4, w: 6, x: 0, y: 1 });
196
+ });
197
+
198
+ test("a mixed layout built by the dashboard passes GRAF105", () => {
199
+ const dash = new Dashboard({
200
+ title: "Mixed",
201
+ panels: [
202
+ new TimeSeriesPanel({ title: "a", gridPos: { x: 0, y: 0, w: 12 } }),
203
+ new TimeSeriesPanel({ title: "b", gridPos: { w: 12 } }),
204
+ new StatPanel({ title: "c", gridPos: { x: 6 } }),
205
+ new StatPanel({ title: "d", gridPos: { x: 12, y: 8, w: 12, h: 4 } }),
206
+ new StatPanel({ title: "e" }),
207
+ new Row({ title: "r", panels: [new StatPanel({ title: "f", gridPos: { x: 18, y: 12 } }), new StatPanel({ title: "g" })] }),
208
+ ],
209
+ });
210
+ expect(checkGrid({ dashboards: [{ json: JSON.parse(dashboardJson(dash)) }], datasources: [] })).toEqual([]);
211
+ });
212
+
80
213
  test("auto ids skip ids set explicitly", () => {
81
214
  const panels = panelsJson([new StatPanel(), new StatPanel({ id: 1 }), new StatPanel()]);
82
215
  expect(panels.map((p) => p.id)).toEqual([2, 1, 3]);
@@ -102,6 +235,17 @@ describe("datasources and targets", () => {
102
235
  ]);
103
236
  });
104
237
 
238
+ test("a panel declared Mixed stays Mixed, and a query naming no datasource is not sent to Mixed (#2992)", () => {
239
+ const mixed = { type: "datasource", uid: "-- Mixed --" };
240
+ const [bare, panel] = panelsOnly([
241
+ new TextPanel({ datasource: mixed }),
242
+ new StatPanel({ datasource: mixed, targets: [new PromQuery({ expr: "up", datasource: prometheus }), new PromQuery({ expr: "down" })] }),
243
+ ]);
244
+ expect(bare.datasource).toEqual(mixed);
245
+ expect(panel.datasource).toEqual(mixed);
246
+ expect(panel.targets!.map((t) => (t as { datasource?: unknown }).datasource)).toEqual([{ type: "prometheus", uid: "prometheus" }, undefined]);
247
+ });
248
+
105
249
  test("a panel takes its queries' shared datasource, and a row passes its own down", () => {
106
250
  const [shared] = panelsOnly([new StatPanel({ targets: [new PromQuery({ expr: "up", datasource: prometheus })] })]);
107
251
  expect(shared.datasource).toEqual({ type: "prometheus", uid: "prometheus" });
@@ -158,6 +302,51 @@ describe("variables", () => {
158
302
  expect(variableModel(new TextboxVariable({ name: "q" }))).toMatchObject({ type: "textbox", query: "" });
159
303
  });
160
304
 
305
+ test("a custom value in Grafana's `text : value` syntax shows the text and sets the value (#2944)", () => {
306
+ const v = variableModel(new CustomVariable({ name: "env", values: ["Production : prod", "Staging : stg", "dev"] }));
307
+ expect(v).toMatchObject({
308
+ query: "Production : prod,Staging : stg,dev",
309
+ current: { text: "Production", value: "prod" },
310
+ options: [
311
+ { selected: true, text: "Production", value: "prod" },
312
+ { selected: false, text: "Staging", value: "stg" },
313
+ { selected: false, text: "dev", value: "dev" },
314
+ ],
315
+ });
316
+ });
317
+
318
+ test("a custom value's selected option follows current by value, and multi-value current selects several", () => {
319
+ const v = variableModel(
320
+ new CustomVariable({ name: "env", multi: true, values: ["Production : prod", "Staging : stg"], current: { text: ["Staging"], value: ["stg"] } }),
321
+ );
322
+ expect((v as { options: Array<{ selected: boolean }> }).options.map((o) => o.selected)).toEqual([false, true]);
323
+ });
324
+
325
+ test("a comma already escaped as \\, is not escaped again (#2944)", () => {
326
+ const v = variableModel(new CustomVariable({ name: "pair", values: ["a\\,b", "c,d", "Label, with comma : x\\,y"] }));
327
+ expect(v).toMatchObject({
328
+ query: "a\\,b,c\\,d,Label\\, with comma : x\\,y",
329
+ options: [
330
+ { text: "a,b", value: "a,b" },
331
+ { text: "c,d", value: "c,d" },
332
+ { text: "Label, with comma", value: "x,y" },
333
+ ],
334
+ });
335
+ });
336
+
337
+ test("customVariableOptions parses a query the way Grafana does", () => {
338
+ expect(customVariableOptions("a : 1, b,c\\,d , ,x:y, k : v : w")).toEqual([
339
+ { text: "a", value: "1" },
340
+ { text: "b", value: "b" },
341
+ { text: "c,d", value: "c,d" },
342
+ { text: "", value: "" },
343
+ // No spaces around the colon: one plain value.
344
+ { text: "x:y", value: "x:y" },
345
+ // Grafana's first group is greedy: the last ` : ` splits.
346
+ { text: "k : v", value: "w" },
347
+ ]);
348
+ });
349
+
161
350
  test("a dashboard with every variable kind matches the dashboard schema", () => {
162
351
  const dash = new Dashboard({
163
352
  title: "Vars",
@@ -176,16 +365,16 @@ describe("variables", () => {
176
365
 
177
366
  describe("extension points", () => {
178
367
  test("definePanel and defineQuery produce classes that render and lay out like built-ins", () => {
179
- const PieChartPanel = definePanel<{ pieType?: "pie" | "donut" }>()({ type: "piechart", className: "PieChartPanel", defaultSize: { w: 8, h: 8 } });
368
+ const ClockPanel = definePanel<{ mode?: "time" | "countdown" }>()({ type: "grafana-clock-panel", className: "ClockPanel", defaultSize: { w: 8, h: 8 } });
180
369
  const ElasticQuery = defineQuery<{ query: string; refId?: string }>()({ datasourceType: "elasticsearch", className: "ElasticQuery" });
181
370
  const es = new Datasource({ name: "Logs ES", type: "elasticsearch" });
182
371
  const json = renderDashboard(
183
- new Dashboard({ title: "Custom", panels: [new PieChartPanel({ options: { pieType: "donut" }, datasource: es, targets: [new ElasticQuery({ query: "*" })] })] }),
372
+ new Dashboard({ title: "Custom", panels: [new ClockPanel({ options: { mode: "countdown" }, datasource: es, targets: [new ElasticQuery({ query: "*" })] })] }),
184
373
  );
185
374
  expect(json.panels![0]).toMatchObject({
186
- type: "piechart",
375
+ type: "grafana-clock-panel",
187
376
  gridPos: { w: 8, h: 8, x: 0, y: 0 },
188
- options: { pieType: "donut" },
377
+ options: { mode: "countdown" },
189
378
  datasource: { type: "elasticsearch", uid: "logs-es" },
190
379
  targets: [{ refId: "A", query: "*" }],
191
380
  });
@@ -208,3 +397,19 @@ describe("extension points", () => {
208
397
  ]);
209
398
  });
210
399
  });
400
+
401
+ describe("folders (#2944)", () => {
402
+ test("a nested folder is written as nested directories under dashboards/", () => {
403
+ const built = buildGrafana([new Dashboard({ title: "Pods", uid: "pods", folder: "Platform/Kubernetes" })]);
404
+ expect(built.dashboards[0].file).toBe("dashboards/Platform/Kubernetes/pods.json");
405
+ expect(built.index.dashboards[0].folder).toBe("Platform/Kubernetes");
406
+ });
407
+
408
+ test("blank levels, dot-led levels and backslashes can't leave dashboards/", () => {
409
+ const file = (folder: string) => buildGrafana([new Dashboard({ title: "D", uid: "d", folder })]).dashboards[0].file;
410
+ expect(file("/Platform//Kubernetes/")).toBe("dashboards/Platform/Kubernetes/d.json");
411
+ expect(file("../../etc")).toBe("dashboards/etc/d.json");
412
+ expect(file("a\\b")).toBe("dashboards/a-b/d.json");
413
+ expect(file(" / ")).toBe("dashboards/d.json");
414
+ });
415
+ });