@intentius/chant-lexicon-grafana 0.98.0 → 0.100.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 (532) hide show
  1. package/README.md +24 -8
  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/annotations.d.ts +61 -0
  11. package/dist/annotations.d.ts.map +1 -0
  12. package/dist/api/apply.d.ts +160 -0
  13. package/dist/api/apply.d.ts.map +1 -0
  14. package/dist/api/bind.d.ts +32 -0
  15. package/dist/api/bind.d.ts.map +1 -0
  16. package/dist/api/client.d.ts +76 -0
  17. package/dist/api/client.d.ts.map +1 -0
  18. package/dist/api/converge.d.ts +33 -0
  19. package/dist/api/converge.d.ts.map +1 -0
  20. package/dist/api/dashboards.d.ts +102 -0
  21. package/dist/api/dashboards.d.ts.map +1 -0
  22. package/dist/api/datasources.d.ts +26 -0
  23. package/dist/api/datasources.d.ts.map +1 -0
  24. package/dist/api/fake-grafana-writes.d.ts +41 -0
  25. package/dist/api/fake-grafana-writes.d.ts.map +1 -0
  26. package/dist/api/fake-grafana.d.ts +63 -0
  27. package/dist/api/fake-grafana.d.ts.map +1 -0
  28. package/dist/api/folders.d.ts +146 -0
  29. package/dist/api/folders.d.ts.map +1 -0
  30. package/dist/api/library-panels.d.ts +52 -0
  31. package/dist/api/library-panels.d.ts.map +1 -0
  32. package/dist/build.d.ts +55 -6
  33. package/dist/build.d.ts.map +1 -1
  34. package/dist/catalog.d.ts +1 -1
  35. package/dist/catalog.d.ts.map +1 -1
  36. package/dist/codegen/docs.d.ts.map +1 -1
  37. package/dist/codegen/generate.d.ts +7 -1
  38. package/dist/codegen/generate.d.ts.map +1 -1
  39. package/dist/codegen/schema-types.d.ts +3 -3
  40. package/dist/codegen/schema-types.d.ts.map +1 -1
  41. package/dist/composites/agent-dashboard.d.ts.map +1 -1
  42. package/dist/composites/catalog.d.ts.map +1 -1
  43. package/dist/composites/index.d.ts +4 -2
  44. package/dist/composites/index.d.ts.map +1 -1
  45. package/dist/composites/red-dashboard.d.ts +21 -2
  46. package/dist/composites/red-dashboard.d.ts.map +1 -1
  47. package/dist/composites/shared.d.ts +11 -3
  48. package/dist/composites/shared.d.ts.map +1 -1
  49. package/dist/composites/slo-alert-rules.d.ts +92 -0
  50. package/dist/composites/slo-alert-rules.d.ts.map +1 -0
  51. package/dist/config.d.ts +111 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/contact-point-secrets.d.ts +17 -0
  54. package/dist/contact-point-secrets.d.ts.map +1 -0
  55. package/dist/dashboard.d.ts +51 -9
  56. package/dist/dashboard.d.ts.map +1 -1
  57. package/dist/datasource-refs.d.ts +99 -0
  58. package/dist/datasource-refs.d.ts.map +1 -0
  59. package/dist/datasource-settings.d.ts +834 -0
  60. package/dist/datasource-settings.d.ts.map +1 -0
  61. package/dist/datasource.d.ts +82 -11
  62. package/dist/datasource.d.ts.map +1 -1
  63. package/dist/deep-observe-hooks.d.ts +64 -0
  64. package/dist/deep-observe-hooks.d.ts.map +1 -0
  65. package/dist/deep-observe.d.ts +47 -0
  66. package/dist/deep-observe.d.ts.map +1 -0
  67. package/dist/describe-resources.d.ts +50 -0
  68. package/dist/describe-resources.d.ts.map +1 -0
  69. package/dist/detect.d.ts +32 -3
  70. package/dist/detect.d.ts.map +1 -1
  71. package/dist/export-resources.d.ts +38 -0
  72. package/dist/export-resources.d.ts.map +1 -0
  73. package/dist/folder.d.ts +68 -0
  74. package/dist/folder.d.ts.map +1 -0
  75. package/dist/import/alerting.d.ts +40 -0
  76. package/dist/import/alerting.d.ts.map +1 -0
  77. package/dist/import/edits.d.ts +47 -0
  78. package/dist/import/edits.d.ts.map +1 -0
  79. package/dist/import/embedded.d.ts +14 -0
  80. package/dist/import/embedded.d.ts.map +1 -0
  81. package/dist/import/generator.d.ts +60 -0
  82. package/dist/import/generator.d.ts.map +1 -0
  83. package/dist/import/live-export.d.ts +108 -0
  84. package/dist/import/live-export.d.ts.map +1 -0
  85. package/dist/import/mappings.d.ts +89 -0
  86. package/dist/import/mappings.d.ts.map +1 -0
  87. package/dist/import/model.d.ts +105 -0
  88. package/dist/import/model.d.ts.map +1 -0
  89. package/dist/import/normalize-alerting.d.ts +26 -0
  90. package/dist/import/normalize-alerting.d.ts.map +1 -0
  91. package/dist/import/normalize.d.ts +74 -0
  92. package/dist/import/normalize.d.ts.map +1 -0
  93. package/dist/import/parser.d.ts +125 -0
  94. package/dist/import/parser.d.ts.map +1 -0
  95. package/dist/import/report.d.ts +26 -0
  96. package/dist/import/report.d.ts.map +1 -0
  97. package/dist/import/testdata/fixtures.d.ts +41 -0
  98. package/dist/import/testdata/fixtures.d.ts.map +1 -0
  99. package/dist/import/v2.d.ts +73 -0
  100. package/dist/import/v2.d.ts.map +1 -0
  101. package/dist/index.d.ts +31 -12
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/init-templates.d.ts +27 -0
  104. package/dist/init-templates.d.ts.map +1 -0
  105. package/dist/integrity.json +22 -12
  106. package/dist/k8s.d.ts +107 -0
  107. package/dist/k8s.d.ts.map +1 -0
  108. package/dist/lint/audit-catalog.d.ts +2 -1
  109. package/dist/lint/audit-catalog.d.ts.map +1 -1
  110. package/dist/lint/post-synth/graf101.d.ts +2 -2
  111. package/dist/lint/post-synth/graf102.d.ts +1 -1
  112. package/dist/lint/post-synth/graf104.d.ts +2 -2
  113. package/dist/lint/post-synth/graf106.d.ts +2 -2
  114. package/dist/lint/post-synth/graf107.d.ts +1 -1
  115. package/dist/lint/post-synth/graf108.d.ts +8 -0
  116. package/dist/lint/post-synth/graf108.d.ts.map +1 -0
  117. package/dist/lint/post-synth/graf109.d.ts +8 -0
  118. package/dist/lint/post-synth/graf109.d.ts.map +1 -0
  119. package/dist/lint/post-synth/graf110.d.ts +8 -0
  120. package/dist/lint/post-synth/graf110.d.ts.map +1 -0
  121. package/dist/lint/post-synth/graf111.d.ts +8 -0
  122. package/dist/lint/post-synth/graf111.d.ts.map +1 -0
  123. package/dist/lint/post-synth/graf112.d.ts +8 -0
  124. package/dist/lint/post-synth/graf112.d.ts.map +1 -0
  125. package/dist/lint/post-synth/graf113.d.ts +8 -0
  126. package/dist/lint/post-synth/graf113.d.ts.map +1 -0
  127. package/dist/lint/post-synth/graf114.d.ts +8 -0
  128. package/dist/lint/post-synth/graf114.d.ts.map +1 -0
  129. package/dist/lint/post-synth/graf115.d.ts +8 -0
  130. package/dist/lint/post-synth/graf115.d.ts.map +1 -0
  131. package/dist/lint/post-synth/grafana-helpers.d.ts +7 -5
  132. package/dist/lint/post-synth/grafana-helpers.d.ts.map +1 -1
  133. package/dist/lint/post-synth/index.d.ts.map +1 -1
  134. package/dist/lint/rules/literal-secret.d.ts +7 -3
  135. package/dist/lint/rules/literal-secret.d.ts.map +1 -1
  136. package/dist/lsp/hover.d.ts.map +1 -1
  137. package/dist/manifest.json +1 -1
  138. package/dist/members.d.ts +27 -0
  139. package/dist/members.d.ts.map +1 -0
  140. package/dist/meta.json +205 -0
  141. package/dist/okf/index.md +53 -4
  142. package/dist/okf/rules/GRAF002.md +3 -2
  143. package/dist/okf/rules/GRAF101.md +3 -2
  144. package/dist/okf/rules/GRAF102.md +1 -0
  145. package/dist/okf/rules/GRAF104.md +2 -2
  146. package/dist/okf/rules/GRAF106.md +2 -2
  147. package/dist/okf/rules/GRAF108.md +11 -0
  148. package/dist/okf/rules/GRAF109.md +15 -0
  149. package/dist/okf/rules/GRAF110.md +11 -0
  150. package/dist/okf/rules/GRAF111.md +11 -0
  151. package/dist/okf/rules/GRAF112.md +16 -0
  152. package/dist/okf/rules/GRAF113.md +16 -0
  153. package/dist/okf/rules/GRAF114.md +11 -0
  154. package/dist/okf/rules/GRAF115.md +11 -0
  155. package/dist/okf/types/AdhocVariable.md +9 -0
  156. package/dist/okf/types/AlertListPanel.md +9 -0
  157. package/dist/okf/types/AlertQuery.md +9 -0
  158. package/dist/okf/types/AlertRule.md +9 -0
  159. package/dist/okf/types/AlertRuleGroup.md +9 -0
  160. package/dist/okf/types/AzureMonitorQuery.md +9 -0
  161. package/dist/okf/types/BarChartPanel.md +9 -0
  162. package/dist/okf/types/BarGaugePanel.md +9 -0
  163. package/dist/okf/types/BigQueryQuery.md +9 -0
  164. package/dist/okf/types/CanvasPanel.md +9 -0
  165. package/dist/okf/types/ClassicConditionsExpression.md +9 -0
  166. package/dist/okf/types/CloudMonitoringQuery.md +9 -0
  167. package/dist/okf/types/CloudWatchQuery.md +9 -0
  168. package/dist/okf/types/ContactPoint.md +14 -0
  169. package/dist/okf/types/Dashboard.md +2 -1
  170. package/dist/okf/types/Datasource.md +3 -2
  171. package/dist/okf/types/DatasourceProvisioning.md +9 -0
  172. package/dist/okf/types/ElasticsearchQuery.md +9 -0
  173. package/dist/okf/types/ExternalDatasource.md +15 -0
  174. package/dist/okf/types/FlameGraphPanel.md +9 -0
  175. package/dist/okf/types/Folder.md +9 -0
  176. package/dist/okf/types/GeomapPanel.md +9 -0
  177. package/dist/okf/types/GroupByVariable.md +9 -0
  178. package/dist/okf/types/HistogramPanel.md +9 -0
  179. package/dist/okf/types/MSSQLQuery.md +9 -0
  180. package/dist/okf/types/MathExpression.md +9 -0
  181. package/dist/okf/types/MuteTiming.md +13 -0
  182. package/dist/okf/types/MySQLQuery.md +9 -0
  183. package/dist/okf/types/NodeGraphPanel.md +9 -0
  184. package/dist/okf/types/NotificationPolicy.md +9 -0
  185. package/dist/okf/types/NotificationTemplate.md +9 -0
  186. package/dist/okf/types/PieChartPanel.md +9 -0
  187. package/dist/okf/types/PostgresQuery.md +9 -0
  188. package/dist/okf/types/PyroscopeQuery.md +9 -0
  189. package/dist/okf/types/ReduceExpression.md +9 -0
  190. package/dist/okf/types/ResampleExpression.md +9 -0
  191. package/dist/okf/types/SqlExpression.md +9 -0
  192. package/dist/okf/types/StateTimelinePanel.md +9 -0
  193. package/dist/okf/types/StatusHistoryPanel.md +9 -0
  194. package/dist/okf/types/SwitchVariable.md +9 -0
  195. package/dist/okf/types/ThresholdExpression.md +9 -0
  196. package/dist/okf/types/TrendPanel.md +9 -0
  197. package/dist/okf/types/XYChartPanel.md +9 -0
  198. package/dist/op/activities/grafana-apply.d.ts +86 -0
  199. package/dist/op/activities/grafana-apply.d.ts.map +1 -0
  200. package/dist/op/activities/index.d.ts +9 -0
  201. package/dist/op/activities/index.d.ts.map +1 -0
  202. package/dist/op/builders.d.ts +24 -0
  203. package/dist/op/builders.d.ts.map +1 -0
  204. package/dist/ownership.d.ts +78 -0
  205. package/dist/ownership.d.ts.map +1 -0
  206. package/dist/panel-options.d.ts +65 -0
  207. package/dist/panel-options.d.ts.map +1 -0
  208. package/dist/panels.d.ts +46 -9
  209. package/dist/panels.d.ts.map +1 -1
  210. package/dist/pin.d.ts +29 -7
  211. package/dist/pin.d.ts.map +1 -1
  212. package/dist/plugin.d.ts.map +1 -1
  213. package/dist/promql-check.d.ts +51 -0
  214. package/dist/promql-check.d.ts.map +1 -0
  215. package/dist/query-models.d.ts +95 -0
  216. package/dist/query-models.d.ts.map +1 -0
  217. package/dist/query.d.ts +116 -18
  218. package/dist/query.d.ts.map +1 -1
  219. package/dist/rules/graf101.ts +3 -3
  220. package/dist/rules/graf102.ts +1 -1
  221. package/dist/rules/graf104.ts +3 -3
  222. package/dist/rules/graf106.ts +3 -3
  223. package/dist/rules/graf107.ts +1 -1
  224. package/dist/rules/graf108.ts +17 -0
  225. package/dist/rules/graf109.ts +17 -0
  226. package/dist/rules/graf110.ts +17 -0
  227. package/dist/rules/graf111.ts +17 -0
  228. package/dist/rules/graf112.ts +17 -0
  229. package/dist/rules/graf113.ts +17 -0
  230. package/dist/rules/graf114.ts +17 -0
  231. package/dist/rules/graf115.ts +17 -0
  232. package/dist/rules/grafana-helpers.ts +27 -10
  233. package/dist/rules/literal-secret.ts +60 -6
  234. package/dist/schema/azuremonitor.gen.d.ts +354 -0
  235. package/dist/schema/azuremonitor.gen.d.ts.map +1 -0
  236. package/dist/schema/barchart.gen.d.ts +198 -0
  237. package/dist/schema/barchart.gen.d.ts.map +1 -0
  238. package/dist/schema/bargauge.gen.d.ts +97 -0
  239. package/dist/schema/bargauge.gen.d.ts.map +1 -0
  240. package/dist/schema/bigquery.gen.d.ts +93 -0
  241. package/dist/schema/bigquery.gen.d.ts.map +1 -0
  242. package/dist/schema/canvas.gen.d.ts +152 -0
  243. package/dist/schema/canvas.gen.d.ts.map +1 -0
  244. package/dist/schema/cloudwatch.gen.d.ts +394 -0
  245. package/dist/schema/cloudwatch.gen.d.ts.map +1 -0
  246. package/dist/schema/dashboard.gen.d.ts +196 -21
  247. package/dist/schema/dashboard.gen.d.ts.map +1 -1
  248. package/dist/schema/elasticsearch.gen.d.ts +444 -0
  249. package/dist/schema/elasticsearch.gen.d.ts.map +1 -0
  250. package/dist/schema/expr.gen.d.ts +606 -0
  251. package/dist/schema/expr.gen.d.ts.map +1 -0
  252. package/dist/schema/gauge.gen.d.ts.map +1 -1
  253. package/dist/schema/geomap.gen.d.ts +100 -0
  254. package/dist/schema/geomap.gen.d.ts.map +1 -0
  255. package/dist/schema/googlecloudmonitoring.gen.d.ts +312 -0
  256. package/dist/schema/googlecloudmonitoring.gen.d.ts.map +1 -0
  257. package/dist/schema/grafanapyroscope.gen.d.ts +60 -0
  258. package/dist/schema/grafanapyroscope.gen.d.ts.map +1 -0
  259. package/dist/schema/heatmap.gen.d.ts.map +1 -1
  260. package/dist/schema/histogram.gen.d.ts +132 -0
  261. package/dist/schema/histogram.gen.d.ts.map +1 -0
  262. package/dist/schema/index.d.ts +18 -0
  263. package/dist/schema/index.d.ts.map +1 -1
  264. package/dist/schema/logs.gen.d.ts +1 -0
  265. package/dist/schema/logs.gen.d.ts.map +1 -1
  266. package/dist/schema/loki.gen.d.ts.map +1 -1
  267. package/dist/schema/nodegraph.gen.d.ts +49 -0
  268. package/dist/schema/nodegraph.gen.d.ts.map +1 -0
  269. package/dist/schema/piechart.gen.d.ts +127 -0
  270. package/dist/schema/piechart.gen.d.ts.map +1 -0
  271. package/dist/schema/prometheus.gen.d.ts.map +1 -1
  272. package/dist/schema/stat.gen.d.ts.map +1 -1
  273. package/dist/schema/statetimeline.gen.d.ts +124 -0
  274. package/dist/schema/statetimeline.gen.d.ts.map +1 -0
  275. package/dist/schema/statushistory.gen.d.ts +114 -0
  276. package/dist/schema/statushistory.gen.d.ts.map +1 -0
  277. package/dist/schema/table.gen.d.ts +35 -3
  278. package/dist/schema/table.gen.d.ts.map +1 -1
  279. package/dist/schema/tempo.gen.d.ts.map +1 -1
  280. package/dist/schema/text.gen.d.ts.map +1 -1
  281. package/dist/schema/timeseries.gen.d.ts +5 -1
  282. package/dist/schema/timeseries.gen.d.ts.map +1 -1
  283. package/dist/schema/trend.gen.d.ts +180 -0
  284. package/dist/schema/trend.gen.d.ts.map +1 -0
  285. package/dist/schema/xychart.gen.d.ts +145 -0
  286. package/dist/schema/xychart.gen.d.ts.map +1 -0
  287. package/dist/schema-validate.d.ts +39 -4
  288. package/dist/schema-validate.d.ts.map +1 -1
  289. package/dist/serializer.d.ts +11 -3
  290. package/dist/serializer.d.ts.map +1 -1
  291. package/dist/skill-defs.d.ts.map +1 -1
  292. package/dist/skills/chant-grafana-alerting.md +49 -0
  293. package/dist/skills/chant-grafana-operations.md +108 -0
  294. package/dist/skills/chant-grafana-provisioning.md +3 -3
  295. package/dist/skills/chant-grafana.md +15 -8
  296. package/dist/spec/fetch-units-cli.d.ts +3 -0
  297. package/dist/spec/fetch-units-cli.d.ts.map +1 -0
  298. package/dist/spec/overlay.d.ts +43 -0
  299. package/dist/spec/overlay.d.ts.map +1 -0
  300. package/dist/spec/schemas.d.ts +21 -13
  301. package/dist/spec/schemas.d.ts.map +1 -1
  302. package/dist/spec/schemas.gen.d.ts +3 -0
  303. package/dist/spec/schemas.gen.d.ts.map +1 -0
  304. package/dist/spec/units.d.ts +35 -0
  305. package/dist/spec/units.d.ts.map +1 -0
  306. package/dist/spec/units.gen.d.ts +2 -0
  307. package/dist/spec/units.gen.d.ts.map +1 -0
  308. package/dist/transformations.d.ts +459 -0
  309. package/dist/transformations.d.ts.map +1 -0
  310. package/dist/util.d.ts +6 -0
  311. package/dist/util.d.ts.map +1 -1
  312. package/dist/validate-alerting.d.ts +65 -0
  313. package/dist/validate-alerting.d.ts.map +1 -0
  314. package/dist/validate-output.d.ts +62 -9
  315. package/dist/validate-output.d.ts.map +1 -1
  316. package/dist/validate.d.ts.map +1 -1
  317. package/dist/validation.d.ts +14 -0
  318. package/dist/validation.d.ts.map +1 -0
  319. package/dist/variables.d.ts +109 -7
  320. package/dist/variables.d.ts.map +1 -1
  321. package/package.json +12 -4
  322. package/src/actions/actions.test.ts +24 -0
  323. package/src/actions/grafana.ts +40 -0
  324. package/src/actions/index.ts +1 -0
  325. package/src/alerting-build.ts +376 -0
  326. package/src/alerting.e2e.test.ts +212 -0
  327. package/src/alerting.test.ts +272 -0
  328. package/src/alerting.ts +435 -0
  329. package/src/annotations.ts +84 -0
  330. package/src/api/apply.test.ts +256 -0
  331. package/src/api/apply.ts +394 -0
  332. package/src/api/bind.ts +58 -0
  333. package/src/api/client.ts +148 -0
  334. package/src/api/converge.ts +63 -0
  335. package/src/api/dashboards.ts +247 -0
  336. package/src/api/datasources.ts +33 -0
  337. package/src/api/fake-grafana-writes.ts +201 -0
  338. package/src/api/fake-grafana.ts +190 -0
  339. package/src/api/folders.ts +339 -0
  340. package/src/api/library-panels.ts +101 -0
  341. package/src/build.test.ts +351 -10
  342. package/src/build.ts +294 -55
  343. package/src/catalog.ts +104 -2
  344. package/src/codegen/docs.ts +50 -10
  345. package/src/codegen/generate.ts +27 -1
  346. package/src/codegen/schema-types.ts +16 -6
  347. package/src/composites/agent-dashboard.ts +6 -3
  348. package/src/composites/catalog.test.ts +2 -2
  349. package/src/composites/catalog.ts +82 -0
  350. package/src/composites/composites.test.ts +73 -9
  351. package/src/composites/index.ts +4 -2
  352. package/src/composites/queries.e2e.test.ts +374 -0
  353. package/src/composites/red-dashboard.ts +83 -12
  354. package/src/composites/shared.ts +14 -2
  355. package/src/composites/slo-alert-rules.ts +149 -0
  356. package/src/config.test.ts +61 -0
  357. package/src/config.ts +138 -0
  358. package/src/contact-point-secrets.ts +63 -0
  359. package/src/dashboard.ts +68 -9
  360. package/src/datasource-refs.test.ts +56 -0
  361. package/src/datasource-refs.ts +213 -0
  362. package/src/datasource-settings.test.ts +106 -0
  363. package/src/datasource-settings.ts +941 -0
  364. package/src/datasource.ts +123 -11
  365. package/src/deep-observe-hooks.ts +267 -0
  366. package/src/deep-observe.test.ts +311 -0
  367. package/src/deep-observe.ts +187 -0
  368. package/src/describe-resources.test.ts +271 -0
  369. package/src/describe-resources.ts +244 -0
  370. package/src/detect.ts +82 -5
  371. package/src/export-resources.test.ts +129 -0
  372. package/src/export-resources.ts +84 -0
  373. package/src/folder.ts +118 -0
  374. package/src/generated/lexicon-grafana.json +205 -0
  375. package/src/import/alerting-roundtrip.test.ts +161 -0
  376. package/src/import/alerting.ts +500 -0
  377. package/src/import/edits.ts +95 -0
  378. package/src/import/embedded.test.ts +45 -0
  379. package/src/import/embedded.ts +47 -0
  380. package/src/import/generated-types.e2e.test.ts +130 -0
  381. package/src/import/generator.test.ts +210 -0
  382. package/src/import/generator.ts +463 -0
  383. package/src/import/live-export.ts +264 -0
  384. package/src/import/mappings.ts +336 -0
  385. package/src/import/model.ts +117 -0
  386. package/src/import/normalize-alerting.ts +101 -0
  387. package/src/import/normalize.test.ts +117 -0
  388. package/src/import/normalize.ts +393 -0
  389. package/src/import/parser.test.ts +516 -0
  390. package/src/import/parser.ts +1387 -0
  391. package/src/import/report.ts +62 -0
  392. package/src/import/roundtrip.test.ts +563 -0
  393. package/src/import/testdata/fixtures.ts +137 -0
  394. package/src/import/v2.test.ts +292 -0
  395. package/src/import/v2.ts +804 -0
  396. package/src/import.e2e.test.ts +31 -84
  397. package/src/import.test.ts +9 -3
  398. package/src/index.ts +308 -14
  399. package/src/init-templates.test.ts +74 -0
  400. package/src/init-templates.ts +349 -0
  401. package/src/k8s.test.ts +98 -0
  402. package/src/k8s.ts +197 -0
  403. package/src/lint/audit-catalog.ts +68 -3
  404. package/src/lint/core-lint.test.ts +43 -0
  405. package/src/lint/post-synth/graf101.ts +3 -3
  406. package/src/lint/post-synth/graf102.ts +1 -1
  407. package/src/lint/post-synth/graf104.ts +3 -3
  408. package/src/lint/post-synth/graf106.ts +3 -3
  409. package/src/lint/post-synth/graf107.ts +1 -1
  410. package/src/lint/post-synth/graf108.ts +17 -0
  411. package/src/lint/post-synth/graf109.ts +17 -0
  412. package/src/lint/post-synth/graf110.ts +17 -0
  413. package/src/lint/post-synth/graf111.ts +17 -0
  414. package/src/lint/post-synth/graf112.ts +17 -0
  415. package/src/lint/post-synth/graf113.ts +17 -0
  416. package/src/lint/post-synth/graf114.ts +17 -0
  417. package/src/lint/post-synth/graf115.ts +17 -0
  418. package/src/lint/post-synth/grafana-helpers.ts +27 -10
  419. package/src/lint/post-synth/index.ts +16 -0
  420. package/src/lint/post-synth/post-synth.test.ts +333 -12
  421. package/src/lint/rules/literal-secret.ts +60 -6
  422. package/src/lint/rules/rules.test.ts +27 -0
  423. package/src/load-cost.test.ts +35 -0
  424. package/src/lsp/completions.test.ts +5 -0
  425. package/src/lsp/hover.test.ts +7 -0
  426. package/src/lsp/hover.ts +8 -1
  427. package/src/members.ts +68 -0
  428. package/src/observe.e2e.test.ts +255 -0
  429. package/src/op/activities/grafana-apply.e2e.test.ts +184 -0
  430. package/src/op/activities/grafana-apply.test.ts +243 -0
  431. package/src/op/activities/grafana-apply.ts +197 -0
  432. package/src/op/activities/index.ts +8 -0
  433. package/src/op/builders.test.ts +40 -0
  434. package/src/op/builders.ts +34 -0
  435. package/src/ownership.ts +122 -0
  436. package/src/panel-options.ts +66 -0
  437. package/src/panels.test.ts +53 -0
  438. package/src/panels.ts +148 -10
  439. package/src/pin.ts +69 -6
  440. package/src/plugin.test.ts +12 -2
  441. package/src/plugin.ts +75 -0
  442. package/src/promql-check.test.ts +108 -0
  443. package/src/promql-check.ts +193 -0
  444. package/src/query-models.ts +94 -0
  445. package/src/query.test.ts +166 -0
  446. package/src/query.ts +190 -20
  447. package/src/schema/azuremonitor.gen.ts +381 -0
  448. package/src/schema/barchart.gen.ts +221 -0
  449. package/src/schema/bargauge.gen.ts +111 -0
  450. package/src/schema/bigquery.gen.ts +110 -0
  451. package/src/schema/canvas.gen.ts +176 -0
  452. package/src/schema/cloudwatch.gen.ts +423 -0
  453. package/src/schema/dashboard.gen.ts +206 -22
  454. package/src/schema/elasticsearch.gen.ts +508 -0
  455. package/src/schema/expr.gen.ts +618 -0
  456. package/src/schema/gauge.gen.ts +2 -1
  457. package/src/schema/geomap.gen.ts +112 -0
  458. package/src/schema/googlecloudmonitoring.gen.ts +330 -0
  459. package/src/schema/grafanapyroscope.gen.ts +66 -0
  460. package/src/schema/heatmap.gen.ts +2 -1
  461. package/src/schema/histogram.gen.ts +151 -0
  462. package/src/schema/index.ts +18 -0
  463. package/src/schema/logs.gen.ts +3 -1
  464. package/src/schema/loki.gen.ts +2 -1
  465. package/src/schema/nodegraph.gen.ts +58 -0
  466. package/src/schema/piechart.gen.ts +146 -0
  467. package/src/schema/prometheus.gen.ts +2 -1
  468. package/src/schema/stat.gen.ts +2 -1
  469. package/src/schema/statetimeline.gen.ts +143 -0
  470. package/src/schema/statushistory.gen.ts +132 -0
  471. package/src/schema/table.gen.ts +41 -4
  472. package/src/schema/tempo.gen.ts +2 -1
  473. package/src/schema/text.gen.ts +2 -1
  474. package/src/schema/timeseries.gen.ts +7 -2
  475. package/src/schema/trend.gen.ts +208 -0
  476. package/src/schema/xychart.gen.ts +167 -0
  477. package/src/schema-overlay.test.ts +282 -0
  478. package/src/schema-validate.ts +199 -57
  479. package/src/schema.test.ts +4 -2
  480. package/src/serializer.test.ts +13 -1
  481. package/src/serializer.ts +11 -3
  482. package/src/skill-defs.ts +34 -0
  483. package/src/skills/chant-grafana-alerting.md +49 -0
  484. package/src/skills/chant-grafana-operations.md +108 -0
  485. package/src/skills/chant-grafana-provisioning.md +3 -3
  486. package/src/skills/chant-grafana.md +15 -8
  487. package/src/spec/fetch-cli.ts +3 -3
  488. package/src/spec/fetch-units-cli.ts +37 -0
  489. package/src/spec/overlay/canvas.overlay.json +142 -0
  490. package/src/spec/overlay/dashboard.overlay.json +378 -0
  491. package/src/spec/overlay/expr.overlay.json +14 -0
  492. package/src/spec/overlay/geomap.overlay.json +35 -0
  493. package/src/spec/overlay/logs.overlay.json +14 -0
  494. package/src/spec/overlay/nodegraph.overlay.json +31 -0
  495. package/src/spec/overlay/piechart.overlay.json +17 -0
  496. package/src/spec/overlay/table.overlay.json +103 -0
  497. package/src/spec/overlay/timeseries.overlay.json +21 -0
  498. package/src/spec/overlay/trend.overlay.json +17 -0
  499. package/src/spec/overlay/xychart.overlay.json +16 -0
  500. package/src/spec/overlay.ts +105 -0
  501. package/src/spec/schemas/azuremonitor.jsonschema.json +679 -0
  502. package/src/spec/schemas/barchart.jsonschema.json +419 -0
  503. package/src/spec/schemas/bargauge.jsonschema.json +224 -0
  504. package/src/spec/schemas/bigquery.jsonschema.json +290 -0
  505. package/src/spec/schemas/canvas.jsonschema.json +356 -0
  506. package/src/spec/schemas/cloudwatch.jsonschema.json +721 -0
  507. package/src/spec/schemas/dashboardv2.jsonschema.json +3387 -0
  508. package/src/spec/schemas/elasticsearch.jsonschema.json +1695 -0
  509. package/src/spec/schemas/expr.jsonschema.json +987 -0
  510. package/src/spec/schemas/geomap.jsonschema.json +220 -0
  511. package/src/spec/schemas/googlecloudmonitoring.jsonschema.json +488 -0
  512. package/src/spec/schemas/grafanapyroscope.jsonschema.json +93 -0
  513. package/src/spec/schemas/histogram.jsonschema.json +308 -0
  514. package/src/spec/schemas/nodegraph.jsonschema.json +77 -0
  515. package/src/spec/schemas/piechart.jsonschema.json +275 -0
  516. package/src/spec/schemas/statetimeline.jsonschema.json +324 -0
  517. package/src/spec/schemas/statushistory.jsonschema.json +292 -0
  518. package/src/spec/schemas/trend.jsonschema.json +449 -0
  519. package/src/spec/schemas/xychart.jsonschema.json +428 -0
  520. package/src/spec/schemas.gen.ts +40 -0
  521. package/src/spec/schemas.ts +30 -16
  522. package/src/spec/units.gen.ts +281 -0
  523. package/src/spec/units.ts +77 -0
  524. package/src/transformations.test.ts +65 -0
  525. package/src/transformations.ts +574 -0
  526. package/src/util.ts +8 -0
  527. package/src/validate-alerting.test.ts +255 -0
  528. package/src/validate-alerting.ts +430 -0
  529. package/src/validate-output.ts +427 -104
  530. package/src/validate.ts +28 -0
  531. package/src/validation.ts +27 -0
  532. package/src/variables.ts +120 -8
package/src/datasource.ts CHANGED
@@ -10,9 +10,14 @@
10
10
  import { createResource } from "@intentius/chant/runtime";
11
11
  import type { Declarable } from "@intentius/chant/declarable";
12
12
  import { slugUid } from "./util";
13
+ import type { DatasourceJsonData, DatasourceSecureJsonData, TypedDatasourceType } from "./datasource-settings";
13
14
 
14
- /** Datasource plugin types this lexicon types queries for. Any other plugin id is accepted as a string. */
15
- export type KnownDatasourceType = "prometheus" | "tempo" | "loki";
15
+ /**
16
+ * Datasource plugin types this lexicon types queries and settings for
17
+ * (`postgres` is the PostgreSQL plugin's old id). Any other plugin id is
18
+ * accepted as a string.
19
+ */
20
+ export type KnownDatasourceType = TypedDatasourceType;
16
21
 
17
22
  /** How Grafana reaches the datasource: through its backend (`proxy`) or from the browser (`direct`). */
18
23
  export type DatasourceAccess = "proxy" | "direct";
@@ -20,7 +25,7 @@ export type DatasourceAccess = "proxy" | "direct";
20
25
  export interface DatasourceProps<T extends string = string> {
21
26
  /** Display name, unique within the Grafana organisation. */
22
27
  name: string;
23
- /** The datasource plugin id, e.g. `prometheus`, `tempo`, `loki`. */
28
+ /** The datasource plugin id, e.g. `prometheus`, `tempo`, `loki`, `grafana-postgresql-datasource`. */
24
29
  type: T;
25
30
  /** Stable id panels refer to. Defaults to the name as a uid (`Prometheus` becomes `prometheus`). */
26
31
  uid?: string;
@@ -33,17 +38,20 @@ export interface DatasourceProps<T extends string = string> {
33
38
  database?: string;
34
39
  withCredentials?: boolean;
35
40
  /**
36
- * Plugin settings. A declared `Datasource` anywhere in here is written as
37
- * its uid, so `tracesToLogsV2: { datasourceUid: loki }` links Tempo to a
38
- * declared Loki.
41
+ * Plugin settings, typed for the plugins in `DatasourceJsonDataTypes`
42
+ * (`./datasource-settings.ts`) and any object for others. A declared
43
+ * `Datasource` anywhere in here is written as its uid, so
44
+ * `tracesToLogsV2: { datasourceUid: loki }` links Tempo to a declared Loki;
45
+ * a typed field that names a datasource accepts only the plugin types
46
+ * Grafana offers there.
39
47
  */
40
- jsonData?: Record<string, unknown>;
48
+ jsonData?: DatasourceJsonData<T>;
41
49
  /**
42
- * Secrets. Write them as Grafana provisioning expands them
43
- * (`$__env{NAME}`, `$__file{/path}`, `${NAME}`), not as literals: GRAF002
44
- * flags a literal.
50
+ * Secrets, by the keys the plugin reads. Write them as Grafana provisioning
51
+ * expands them (`$__env{NAME}`, `$__file{/path}`, `${NAME}`), not as
52
+ * literals: GRAF002 flags a literal.
45
53
  */
46
- secureJsonData?: Record<string, string>;
54
+ secureJsonData?: DatasourceSecureJsonData<T>;
47
55
  /** Whether users may edit the provisioned datasource in the UI. Defaults to false. */
48
56
  editable?: boolean;
49
57
  orgId?: number;
@@ -83,6 +91,58 @@ export function isDatasourceEntity(value: unknown): value is DatasourceEntity {
83
91
  );
84
92
  }
85
93
 
94
+ export const EXTERNAL_DATASOURCE_TYPE = "Grafana::ExternalDatasource";
95
+
96
+ export interface ExternalDatasourceProps<T extends string = string> {
97
+ /** The datasource plugin id, e.g. `prometheus`. */
98
+ type: T;
99
+ /** The uid the datasource already has in Grafana. */
100
+ uid: string;
101
+ /** Its display name in Grafana, for messages and for a `DatasourceVariable` `regex`. */
102
+ name?: string;
103
+ }
104
+
105
+ export interface ExternalDatasourceEntity<T extends string = string> extends Declarable {
106
+ readonly props: ExternalDatasourceProps<T>;
107
+ /** The plugin id. */
108
+ readonly datasourceType: T;
109
+ /** The uid panels will reference. */
110
+ readonly uid: string;
111
+ }
112
+
113
+ const ExternalBase = createResource(EXTERNAL_DATASOURCE_TYPE, "grafana", {}) as unknown as (this: object, props: Record<string, unknown>) => void;
114
+
115
+ export interface ExternalDatasourceConstructor {
116
+ new <T extends string>(props: ExternalDatasourceProps<T>): ExternalDatasourceEntity<T>;
117
+ }
118
+
119
+ /**
120
+ * A datasource that already exists in Grafana: provisioned by hand, by
121
+ * another build root, or by another tool. It is never written to the
122
+ * provisioning file. Panels, queries and variables use it like a
123
+ * `Datasource`, and GRAF101/GRAF102 check references against it.
124
+ */
125
+ export const ExternalDatasource = function (this: object, props: ExternalDatasourceProps) {
126
+ ExternalBase.call(this, props as unknown as Record<string, unknown>);
127
+ Object.defineProperty(this, "datasourceType", { value: props.type, enumerable: false });
128
+ Object.defineProperty(this, "uid", { value: props.uid, enumerable: false });
129
+ } as unknown as ExternalDatasourceConstructor;
130
+ Object.defineProperty(ExternalDatasource, "name", { value: "ExternalDatasource" });
131
+
132
+ export function isExternalDatasource(value: unknown): value is ExternalDatasourceEntity {
133
+ return (
134
+ typeof value === "object" &&
135
+ value !== null &&
136
+ (value as Declarable).entityType === EXTERNAL_DATASOURCE_TYPE &&
137
+ (value as Declarable).lexicon === "grafana"
138
+ );
139
+ }
140
+
141
+ /** A declared or an external datasource: anything a panel can hold that has a fixed uid. */
142
+ export function isDatasourceDeclaration(value: unknown): value is DatasourceEntity | ExternalDatasourceEntity {
143
+ return isDatasourceEntity(value) || isExternalDatasource(value);
144
+ }
145
+
86
146
  /** A datasource declared somewhere this build can't see, named by its Grafana ref. */
87
147
  export interface DatasourceRef<T extends string = string> {
88
148
  type: T;
@@ -91,3 +151,55 @@ export interface DatasourceRef<T extends string = string> {
91
151
 
92
152
  /** Grafana's own pseudo-datasources, which need no declaration. */
93
153
  export const BUILTIN_DATASOURCE_UIDS: ReadonlySet<string> = new Set(["grafana", "-- Grafana --", "-- Mixed --", "-- Dashboard --"]);
154
+
155
+ export const DATASOURCE_PROVISIONING_TYPE = "Grafana::DatasourceProvisioning";
156
+
157
+ /** A datasource the provisioning file deletes, by its name in an organisation. */
158
+ export interface DeletedDatasource {
159
+ name: string;
160
+ /** Defaults to 1, as in Grafana. */
161
+ orgId?: number;
162
+ }
163
+
164
+ export interface DatasourceProvisioningProps {
165
+ /**
166
+ * Written as the file's `prune`. Grafana marks every datasource this file
167
+ * provisions as prunable, and deletes a prunable datasource once no
168
+ * provisioning file lists it any more, so removing a `Datasource` removes
169
+ * it from Grafana on the next provisioning run. Datasources provisioned
170
+ * without it, or made in the UI or API, are never pruned. Defaults to
171
+ * true; set false to keep a removed datasource in Grafana.
172
+ */
173
+ prune?: boolean;
174
+ /**
175
+ * Written as the file's `deleteDatasources`: Grafana deletes these by name
176
+ * before it provisions the file's datasources. Name one the file also
177
+ * provisions to have Grafana re-create it from the file on every run.
178
+ */
179
+ deleteDatasources?: DeletedDatasource[];
180
+ }
181
+
182
+ export interface DatasourceProvisioningEntity extends Declarable {
183
+ readonly props: DatasourceProvisioningProps;
184
+ }
185
+
186
+ const ProvisioningBase = createResource(DATASOURCE_PROVISIONING_TYPE, "grafana", {}) as unknown as (this: object, props: Record<string, unknown>) => void;
187
+
188
+ /**
189
+ * The settings of the datasource provisioning file itself: `prune` and
190
+ * `deleteDatasources`. Optional: without one the file prunes. Declare at
191
+ * most one per build.
192
+ */
193
+ export const DatasourceProvisioning = function (this: object, props: DatasourceProvisioningProps) {
194
+ ProvisioningBase.call(this, props as unknown as Record<string, unknown>);
195
+ } as unknown as new (props: DatasourceProvisioningProps) => DatasourceProvisioningEntity;
196
+ Object.defineProperty(DatasourceProvisioning, "name", { value: "DatasourceProvisioning" });
197
+
198
+ export function isDatasourceProvisioningEntity(value: unknown): value is DatasourceProvisioningEntity {
199
+ return (
200
+ typeof value === "object" &&
201
+ value !== null &&
202
+ (value as Declarable).entityType === DATASOURCE_PROVISIONING_TYPE &&
203
+ (value as Declarable).lexicon === "grafana"
204
+ );
205
+ }
@@ -0,0 +1,267 @@
1
+ /**
2
+ * grafana deep-observation noise rules (#2946).
3
+ *
4
+ * Plain data on the plugin, because core applies the same rules to the
5
+ * declared tree (a `Dashboard`'s props, panels and queries inlined), which
6
+ * no reader touches. The live tree is the stored dashboard put back into the
7
+ * same vocabulary by the importer (./import/live-export.ts), so what is left
8
+ * to name here is what the translation cannot decide: values the build
9
+ * wrote that the author did not, values Grafana adds or drops on save, and
10
+ * values an author wrote out that are also what happens when they are left
11
+ * out.
12
+ *
13
+ * Measured against Grafana 12.4.11 and 13.2.2 (the e2e in
14
+ * ./observe.e2e.test.ts): read over `/api/dashboards/uid`, a stored dashboard
15
+ * differs from the built one only by the `id` and `version` Grafana adds
16
+ * (../test/e2e/stored-model.ts). Read over `/apis/dashboard.grafana.app`, its
17
+ * spec has no `id` or `version`, but it carries the built-in "Annotations &
18
+ * Alerts" annotation, and empty `options` and `fieldConfig` and every `null`
19
+ * are gone. The rest of this table is the build's own choices: panel ids,
20
+ * grid positions, query refIds, a panel's datasource taken from its queries.
21
+ *
22
+ * Every rule is one of four kinds, and they are in this order below:
23
+ *
24
+ * 1. **Never compared**, on either side: Grafana's bookkeeping.
25
+ * 2. **Empty is absent**, on both sides: `null`, `{}` and `[]` mean the same
26
+ * as leaving a key out, everywhere in a dashboard or datasource. The cost
27
+ * is that values added where the declaration wrote `[]` are reported as
28
+ * unclaimed rather than as drift.
29
+ * 3. **Build-derived**, on the live side where the declaration has nothing:
30
+ * the build filled it in, so it cannot disagree with what was declared.
31
+ * 4. **Default written out**, on the declared side where the live side has
32
+ * nothing: the author wrote the value Grafana assumes, which the
33
+ * translation leaves out.
34
+ *
35
+ * Rules 3 and 4 are gated on `counterpart === "absent"`, so a value the
36
+ * author did declare is always compared, and a change away from it is drift.
37
+ * (That relies on core walking a panel's props when it lists the declared
38
+ * paths, which #2946 fixed in `deepPathSet`.)
39
+ */
40
+
41
+ import type { DeepArrayElement, DeepNode, DeepNormalizationHooks } from "@intentius/chant/deep-observation";
42
+ import { DASHBOARD_TYPE } from "./dashboard";
43
+ import { DATASOURCE_TYPE, EXTERNAL_DATASOURCE_TYPE } from "./datasource";
44
+ import { FOLDER_TYPE } from "./folder";
45
+ import { registeredQueries } from "./query";
46
+ import { DASHBOARD_SCHEMA_VERSION } from "./schema/dashboard.gen";
47
+ import { BOOKKEEPING_KEYS, LINK_DEFAULTS, deepEqual, isBuiltinAnnotation } from "./import/normalize";
48
+ import { DATASOURCE_API_DEFAULTS } from "./import/live-export";
49
+
50
+ type Json = Record<string, unknown>;
51
+
52
+ /** Where a node sits in a dashboard tree, from its index-erased pattern. */
53
+ type Level = "dashboard" | "panel" | "target" | "variable" | "link" | "annotation";
54
+
55
+ const SEGMENT = "([^.\\[\\]]+)";
56
+ const PANEL = "panels\\[\\](?:\\.panels\\[\\])?";
57
+ const LEVELS: ReadonlyArray<[Level, RegExp]> = [
58
+ ["dashboard", new RegExp(`^${SEGMENT}$`)],
59
+ ["panel", new RegExp(`^${PANEL}\\.${SEGMENT}$`)],
60
+ ["target", new RegExp(`^${PANEL}\\.targets\\[\\]\\.${SEGMENT}$`)],
61
+ ["variable", new RegExp(`^variables\\[\\]\\.${SEGMENT}$`)],
62
+ ["link", new RegExp(`^(?:${PANEL}\\.)?links\\[\\]\\.${SEGMENT}$`)],
63
+ ["annotation", new RegExp(`^annotations\\[\\]\\.${SEGMENT}$`)],
64
+ ];
65
+
66
+ function levelOf(pattern: string): { level: Level; key: string } | undefined {
67
+ for (const [level, re] of LEVELS) {
68
+ const m = re.exec(pattern);
69
+ if (m) return { level, key: m[1] };
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ /**
75
+ * Defaults in the props vocabulary: a key an author may write at this value,
76
+ * and the translation leaves out because Grafana assumes it. The dashboard
77
+ * and panel entries mirror `DASHBOARD_DEFAULTS` and `PANEL_DEFAULTS` in
78
+ * ./import/normalize.ts, with `graphTooltip` spelled as `Dashboard` takes it.
79
+ */
80
+ export const PROP_DEFAULTS: Readonly<Record<Level, Readonly<Json>>> = {
81
+ dashboard: {
82
+ editable: true,
83
+ fiscalYearStartMonth: 0,
84
+ graphTooltip: "default",
85
+ links: [],
86
+ tags: [],
87
+ time: { from: "now-6h", to: "now" },
88
+ timepicker: {},
89
+ timezone: "",
90
+ weekStart: "",
91
+ refresh: "",
92
+ liveNow: false,
93
+ description: "",
94
+ schemaVersion: DASHBOARD_SCHEMA_VERSION,
95
+ },
96
+ panel: {
97
+ title: "",
98
+ description: "",
99
+ options: {},
100
+ targets: [],
101
+ transformations: [],
102
+ links: [],
103
+ transparent: false,
104
+ hideTimeOverride: false,
105
+ repeatDirection: "h",
106
+ // A row's.
107
+ collapsed: false,
108
+ panels: [],
109
+ },
110
+ target: {},
111
+ variable: {
112
+ label: "",
113
+ description: "",
114
+ hide: "label",
115
+ skipUrlSync: false,
116
+ multi: false,
117
+ includeAll: false,
118
+ allValue: "",
119
+ regex: "",
120
+ sort: 0,
121
+ refresh: "onLoad",
122
+ auto: false,
123
+ autoCount: 30,
124
+ autoMin: "10s",
125
+ },
126
+ link: LINK_DEFAULTS,
127
+ // Grafana 13.2 drops `hide: false` from an annotation it stores.
128
+ annotation: { hide: false },
129
+ };
130
+
131
+ /** What the build writes into an annotation that leaves them out (annotations.ts `annotationJson`). */
132
+ const ANNOTATION_BUILD_DEFAULTS: Readonly<Json> = { enable: true, iconColor: "red" };
133
+
134
+ /**
135
+ * Keys the build fills in when a declaration leaves them out, by level:
136
+ * the dashboard's uid (from its export name) and schema version, a panel's
137
+ * id, grid position and datasource (from its queries), a query's refId.
138
+ * Grafana keeps what the build wrote, so undeclared, they read back as the
139
+ * build's choice rather than as anybody's edit.
140
+ *
141
+ * `timezone` is here as a value, not a key: chant writes `browser` for a
142
+ * dashboard that names none, where Grafana's own default is `""`.
143
+ */
144
+ export const BUILD_DERIVED: Readonly<Record<Level, ReadonlySet<string>>> = {
145
+ dashboard: new Set(["uid", "schemaVersion"]),
146
+ panel: new Set(["id", "gridPos", "datasource", "pluginVersion"]),
147
+ target: new Set(["refId", "datasource"]),
148
+ // A query variable's selection is whatever the viewer last saved; the build writes one only when it is declared.
149
+ variable: new Set(["current", "datasource"]),
150
+ link: new Set(),
151
+ annotation: new Set(),
152
+ };
153
+
154
+ /** Defaults the build merges into a query from its class (`queryType: "traceql"`, `filters: []`): any key some class defaults, at that value. */
155
+ function queryDefault(key: string, value: unknown): boolean {
156
+ for (const def of registeredQueries()) {
157
+ const defaults = (def as { defaults?: Json }).defaults;
158
+ if (defaults && key in defaults && deepEqual(defaults[key], value)) return true;
159
+ }
160
+ return false;
161
+ }
162
+
163
+ /** `[]` or a plain `{}`. Not a declarable, whose own keys are not enumerable. */
164
+ function isEmptyContainer(value: unknown): boolean {
165
+ if (Array.isArray(value)) return value.length === 0;
166
+ if (typeof value !== "object" || value === null) return false;
167
+ const proto = Object.getPrototypeOf(value) as unknown;
168
+ return (proto === Object.prototype || proto === null) && Object.keys(value).length === 0;
169
+ }
170
+
171
+ function isEmptyFieldConfig(value: unknown): boolean {
172
+ return isEmptyContainer(value) || deepEqual(value, { defaults: {}, overrides: [] });
173
+ }
174
+
175
+ /** Any node at or under a `datasource` key: a reference, whichever form (ref, variable, entity) it takes. */
176
+ function underDatasource(pattern: string): boolean {
177
+ return /(^|\.)datasource(\.|$)/.test(pattern);
178
+ }
179
+
180
+ function isDatasourceType(entityType: string): boolean {
181
+ return entityType === DATASOURCE_TYPE || entityType === EXTERNAL_DATASOURCE_TYPE;
182
+ }
183
+
184
+ function pruneDatasource(node: DeepNode): boolean {
185
+ // 1. The organisation is where it lives, not a property of it; the version is Grafana's save counter.
186
+ if (node.pattern === "orgId" || node.pattern === "version") return true;
187
+ // 2.
188
+ if (node.value === null || isEmptyContainer(node.value)) return true;
189
+ if (node.counterpart !== "absent") return false;
190
+ if (node.side === "live") {
191
+ // 3. The uid comes from the name when not declared; `editable` is `!readOnly`, true for one created in the UI or API.
192
+ return node.pattern === "uid" || node.pattern === "editable";
193
+ }
194
+ // 4.
195
+ if (node.pattern === "editable") return node.value === false;
196
+ return node.pattern in DATASOURCE_API_DEFAULTS && deepEqual(DATASOURCE_API_DEFAULTS[node.pattern], node.value);
197
+ }
198
+
199
+ function pruneDashboard(node: DeepNode): boolean {
200
+ const at = levelOf(node.pattern);
201
+
202
+ // 1. Bookkeeping and Grafana's own additions, whatever either side says.
203
+ if (at?.level === "dashboard" && BOOKKEEPING_KEYS.includes(at.key)) return true;
204
+ if (/^annotations(\.list)?\[\]$/.test(node.pattern) && isBuiltinAnnotation(node.value)) return true;
205
+ if (at?.level === "panel" && (at.key === "options" || at.key === "fieldConfig") && isEmptyFieldConfig(node.value)) return true;
206
+
207
+ // 2. Empty is absent, on both sides whatever the other has. Grafana drops
208
+ // every `null` when it stores a dashboard through /apis, and an empty list
209
+ // or object means what leaving the key out means. Not gated on the
210
+ // counterpart, which is matched by pattern: a threshold's first step has
211
+ // `value: null` where the others have a number, and one panel's
212
+ // `overrides: []` sits beside another's list of overrides.
213
+ if (node.value === null || isEmptyContainer(node.value)) return true;
214
+ if (node.counterpart !== "absent") return false;
215
+
216
+ if (node.side === "live") {
217
+ // 3. Build-derived.
218
+ if (underDatasource(node.pattern)) return true;
219
+ if (/^panels\[\](?:\.panels\[\])?\.gridPos\./.test(node.pattern)) return true;
220
+ if (!at) return false;
221
+ if (BUILD_DERIVED[at.level].has(at.key)) return true;
222
+ if (at.level === "dashboard" && at.key === "timezone" && node.value === "browser") return true;
223
+ if (at.level === "target" && queryDefault(at.key, node.value)) return true;
224
+ if (at.level === "link" && at.key in LINK_DEFAULTS && deepEqual(LINK_DEFAULTS[at.key], node.value)) return true;
225
+ if (at.level === "annotation" && at.key in ANNOTATION_BUILD_DEFAULTS && deepEqual(ANNOTATION_BUILD_DEFAULTS[at.key], node.value)) return true;
226
+ return false;
227
+ }
228
+
229
+ // 4. A default written out.
230
+ if (!at) return false;
231
+ const defaults = PROP_DEFAULTS[at.level];
232
+ return at.key in defaults && deepEqual(defaults[at.key], node.value);
233
+ }
234
+
235
+ /** A folder's uid comes from its path when it is not declared. */
236
+ function pruneFolder(node: DeepNode): boolean {
237
+ return node.side === "live" && node.counterpart === "absent" && node.pattern === "uid";
238
+ }
239
+
240
+ export const grafanaDeepNormalizationHooks: DeepNormalizationHooks = {
241
+ prune(node: DeepNode): boolean {
242
+ if (node.entityType === DASHBOARD_TYPE) return pruneDashboard(node);
243
+ if (node.entityType === FOLDER_TYPE) return pruneFolder(node);
244
+ if (isDatasourceType(node.entityType)) return pruneDatasource(node);
245
+ return false;
246
+ },
247
+
248
+ /**
249
+ * A datasource's secrets are compared by key, never by value: Grafana
250
+ * returns only which ones are set, the reader writes those as
251
+ * `[REDACTED]`, and the declared values (`$__env{...}` references, or
252
+ * worse) are masked the same way.
253
+ */
254
+ mask(node: DeepNode): boolean {
255
+ return isDatasourceType(node.entityType) && /^secureJsonData\./.test(node.pattern);
256
+ },
257
+
258
+ /**
259
+ * Dashboard tags are a set. Nothing else is reordered: panel order is
260
+ * layout order, and variable and link order is the order Grafana shows
261
+ * them in.
262
+ */
263
+ orderKey(element: DeepArrayElement): string | undefined {
264
+ if (element.entityType === DASHBOARD_TYPE && element.pattern === "tags" && typeof element.element === "string") return element.element;
265
+ return undefined;
266
+ },
267
+ };