@intentius/chant-lexicon-grafana 0.124.30 → 0.124.32

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 (166) hide show
  1. package/dist/actions/grafana.js +36 -0
  2. package/dist/actions/index.js +1 -0
  3. package/dist/alerting-build.js +262 -0
  4. package/dist/alerting.js +125 -0
  5. package/dist/annotations.js +47 -0
  6. package/dist/api/apply.js +320 -0
  7. package/dist/api/bind.js +44 -0
  8. package/dist/api/client.js +113 -0
  9. package/dist/api/converge.js +61 -0
  10. package/dist/api/dashboards.js +210 -0
  11. package/dist/api/datasources.js +24 -0
  12. package/dist/api/fake-grafana-writes.js +185 -0
  13. package/dist/api/fake-grafana.js +161 -0
  14. package/dist/api/folders.js +290 -0
  15. package/dist/api/library-panels.js +82 -0
  16. package/dist/build.js +767 -0
  17. package/dist/catalog.js +198 -0
  18. package/dist/codegen/docs-cli.js +3 -0
  19. package/dist/codegen/docs.js +130 -0
  20. package/dist/codegen/generate-cli.js +7 -0
  21. package/dist/codegen/generate.js +97 -0
  22. package/dist/codegen/package.js +28 -0
  23. package/dist/codegen/schema-types.js +159 -0
  24. package/dist/composites/agent-dashboard.js +460 -0
  25. package/dist/composites/catalog.js +306 -0
  26. package/dist/composites/index.js +8 -0
  27. package/dist/composites/red-dashboard.js +135 -0
  28. package/dist/composites/shared.js +74 -0
  29. package/dist/composites/slo-alert-rules.js +96 -0
  30. package/dist/composites/slo-dashboard.js +153 -0
  31. package/dist/config.js +110 -0
  32. package/dist/contact-point-check.js +61 -0
  33. package/dist/contact-point-secrets.js +32 -0
  34. package/dist/contact-point-settings.gen.js +421 -0
  35. package/dist/dashboard.js +60 -0
  36. package/dist/datasource-refs.js +170 -0
  37. package/dist/datasource-settings.js +57 -0
  38. package/dist/datasource.js +68 -0
  39. package/dist/deep-observe-hooks.js +266 -0
  40. package/dist/deep-observe.js +171 -0
  41. package/dist/describe-resources.js +249 -0
  42. package/dist/detect.js +119 -0
  43. package/dist/export-resources.js +73 -0
  44. package/dist/folder.js +86 -0
  45. package/dist/import/alerting.js +514 -0
  46. package/dist/import/edits.js +90 -0
  47. package/dist/import/embedded.js +60 -0
  48. package/dist/import/generator.js +656 -0
  49. package/dist/import/live-export.js +246 -0
  50. package/dist/import/mappings.js +317 -0
  51. package/dist/import/model.js +23 -0
  52. package/dist/import/normalize-alerting.js +106 -0
  53. package/dist/import/normalize.js +426 -0
  54. package/dist/import/operator.js +252 -0
  55. package/dist/import/parser.js +1480 -0
  56. package/dist/import/report.js +58 -0
  57. package/dist/import/testdata/fixtures.js +122 -0
  58. package/dist/import/v2.js +814 -0
  59. package/dist/index.js +59 -0
  60. package/dist/init-templates.js +305 -0
  61. package/dist/integrity.json +2 -2
  62. package/dist/k8s.js +548 -0
  63. package/dist/library-panel.js +83 -0
  64. package/dist/lint/audit-catalog.js +40 -0
  65. package/dist/lint/audit-lineage.js +9 -0
  66. package/dist/lint/post-synth/graf101.js +13 -0
  67. package/dist/lint/post-synth/graf102.js +13 -0
  68. package/dist/lint/post-synth/graf103.js +13 -0
  69. package/dist/lint/post-synth/graf104.js +13 -0
  70. package/dist/lint/post-synth/graf105.js +13 -0
  71. package/dist/lint/post-synth/graf106.js +13 -0
  72. package/dist/lint/post-synth/graf107.js +13 -0
  73. package/dist/lint/post-synth/graf108.js +13 -0
  74. package/dist/lint/post-synth/graf109.js +13 -0
  75. package/dist/lint/post-synth/graf110.js +13 -0
  76. package/dist/lint/post-synth/graf111.js +13 -0
  77. package/dist/lint/post-synth/graf112.js +13 -0
  78. package/dist/lint/post-synth/graf113.js +13 -0
  79. package/dist/lint/post-synth/graf114.js +13 -0
  80. package/dist/lint/post-synth/graf115.js +13 -0
  81. package/dist/lint/post-synth/graf116.js +13 -0
  82. package/dist/lint/post-synth/graf117.js +13 -0
  83. package/dist/lint/post-synth/graf118.js +37 -0
  84. package/dist/lint/post-synth/grafana-helpers.js +89 -0
  85. package/dist/lint/post-synth/index.js +38 -0
  86. package/dist/lint/rules/grafana-ast.js +70 -0
  87. package/dist/lint/rules/index.js +6 -0
  88. package/dist/lint/rules/literal-secret.js +109 -0
  89. package/dist/lint/rules/uid-syntax.js +53 -0
  90. package/dist/lsp/completions.js +11 -0
  91. package/dist/lsp/hover.js +29 -0
  92. package/dist/manifest.json +1 -1
  93. package/dist/op/activities/grafana-apply.js +147 -0
  94. package/dist/op/activities/index.js +7 -0
  95. package/dist/op/builders.js +19 -0
  96. package/dist/ownership.js +102 -0
  97. package/dist/package-cli.js +14 -0
  98. package/dist/panel-options.js +12 -0
  99. package/dist/panels.js +296 -0
  100. package/dist/pin.js +113 -0
  101. package/dist/plugin.js +172 -0
  102. package/dist/promql-check.js +176 -0
  103. package/dist/query-models.js +13 -0
  104. package/dist/query-syntax.js +129 -0
  105. package/dist/query.js +227 -0
  106. package/dist/schema/annotationslist.gen.js +5 -0
  107. package/dist/schema/azuremonitor.gen.js +5 -0
  108. package/dist/schema/barchart.gen.js +5 -0
  109. package/dist/schema/bargauge.gen.js +5 -0
  110. package/dist/schema/bigquery.gen.js +5 -0
  111. package/dist/schema/candlestick.gen.js +5 -0
  112. package/dist/schema/canvas.gen.js +5 -0
  113. package/dist/schema/cloudwatch.gen.js +5 -0
  114. package/dist/schema/dashboard.gen.js +6 -0
  115. package/dist/schema/dashboardlist.gen.js +5 -0
  116. package/dist/schema/datagrid.gen.js +5 -0
  117. package/dist/schema/elasticsearch.gen.js +5 -0
  118. package/dist/schema/expr.gen.js +5 -0
  119. package/dist/schema/gauge.gen.js +5 -0
  120. package/dist/schema/geomap.gen.js +5 -0
  121. package/dist/schema/googlecloudmonitoring.gen.js +5 -0
  122. package/dist/schema/grafanapyroscope.gen.js +5 -0
  123. package/dist/schema/heatmap.gen.js +5 -0
  124. package/dist/schema/histogram.gen.js +5 -0
  125. package/dist/schema/index.js +40 -0
  126. package/dist/schema/logs.gen.js +5 -0
  127. package/dist/schema/loki.gen.js +5 -0
  128. package/dist/schema/news.gen.js +5 -0
  129. package/dist/schema/nodegraph.gen.js +5 -0
  130. package/dist/schema/piechart.gen.js +5 -0
  131. package/dist/schema/prometheus.gen.js +5 -0
  132. package/dist/schema/stat.gen.js +5 -0
  133. package/dist/schema/statetimeline.gen.js +5 -0
  134. package/dist/schema/statushistory.gen.js +5 -0
  135. package/dist/schema/table.gen.js +5 -0
  136. package/dist/schema/tempo.gen.js +5 -0
  137. package/dist/schema/text.gen.js +5 -0
  138. package/dist/schema/timeseries.gen.js +5 -0
  139. package/dist/schema/trend.gen.js +5 -0
  140. package/dist/schema/xychart.gen.js +5 -0
  141. package/dist/schema-validate.js +265 -0
  142. package/dist/serializer.js +40 -0
  143. package/dist/skill-defs.js +60 -0
  144. package/dist/spec/fetch-cli.js +26 -0
  145. package/dist/spec/fetch-notifiers-cli.js +53 -0
  146. package/dist/spec/fetch-units-cli.js +40 -0
  147. package/dist/spec/notifiers.js +126 -0
  148. package/dist/spec/overlay.js +92 -0
  149. package/dist/spec/schemas.gen.js +42 -0
  150. package/dist/spec/schemas.js +62 -0
  151. package/dist/spec/units.gen.js +280 -0
  152. package/dist/spec/units.js +72 -0
  153. package/dist/transformations.js +127 -0
  154. package/dist/util.js +34 -0
  155. package/dist/validate-alerting.js +444 -0
  156. package/dist/validate-cli.js +7 -0
  157. package/dist/validate-output.js +635 -0
  158. package/dist/validate.js +122 -0
  159. package/dist/validation.js +13 -0
  160. package/dist/variables.js +70 -0
  161. package/package.json +10 -10
  162. package/src/codegen/package.ts +2 -2
  163. package/src/spec/fetch-notifiers-cli.ts +2 -2
  164. package/src/spec/fetch-units-cli.ts +2 -2
  165. package/src/spec/overlay.ts +2 -2
  166. package/src/spec/schemas.ts +2 -2
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Validate the grafana lexicon's own artifacts: the vendored schemas match
3
+ * their pinned digests, the committed schema types match what generate would
4
+ * write, every required class is in the registry, and every built-in panel
5
+ * renders to a dashboard the pinned schema accepts.
6
+ */
7
+ import { readFileSync } from "fs";
8
+ import { dirname, join } from "path";
9
+ import { fileURLToPath } from "url";
10
+ import { BUILTIN_CATALOG, lexiconRegistry } from "./catalog.js";
11
+ import { digestMismatches } from "./spec/schemas.js";
12
+ import { schemaModules } from "./codegen/generate.js";
13
+ import * as panels from "./panels.js";
14
+ import { Dashboard } from "./dashboard.js";
15
+ import { renderDashboard } from "./build.js";
16
+ import { validateDashboardSchema } from "./schema-validate.js";
17
+ /** Every entity class the package must keep exporting. */
18
+ export const REQUIRED_NAMES = [
19
+ "Dashboard",
20
+ "Datasource",
21
+ "ExternalDatasource",
22
+ "DashboardProvider",
23
+ "DatasourceProvisioning",
24
+ "Folder",
25
+ "LibraryPanel",
26
+ "LibraryPanelRef",
27
+ "Row",
28
+ "TimeSeriesPanel",
29
+ "StatPanel",
30
+ "GaugePanel",
31
+ "TablePanel",
32
+ "LogsPanel",
33
+ "TracesPanel",
34
+ "HeatmapPanel",
35
+ "TextPanel",
36
+ "BarChartPanel",
37
+ "BarGaugePanel",
38
+ "PieChartPanel",
39
+ "StateTimelinePanel",
40
+ "StatusHistoryPanel",
41
+ "HistogramPanel",
42
+ "NodeGraphPanel",
43
+ "XYChartPanel",
44
+ "TrendPanel",
45
+ "CanvasPanel",
46
+ "GeomapPanel",
47
+ "CandlestickPanel",
48
+ "AnnotationsListPanel",
49
+ "DashboardListPanel",
50
+ "NewsPanel",
51
+ "DataGridPanel",
52
+ "FlameGraphPanel",
53
+ "AlertListPanel",
54
+ "PromQuery",
55
+ "TempoQuery",
56
+ "LokiQuery",
57
+ "ElasticsearchQuery",
58
+ "CloudWatchQuery",
59
+ "AzureMonitorQuery",
60
+ "CloudMonitoringQuery",
61
+ "BigQueryQuery",
62
+ "PyroscopeQuery",
63
+ "OpenSearchQuery",
64
+ "PostgresQuery",
65
+ "MySQLQuery",
66
+ "MSSQLQuery",
67
+ "QueryVariable",
68
+ "CustomVariable",
69
+ "IntervalVariable",
70
+ "DatasourceVariable",
71
+ "ConstantVariable",
72
+ "TextboxVariable",
73
+ "AdhocVariable",
74
+ "GroupByVariable",
75
+ "SwitchVariable",
76
+ ];
77
+ const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
78
+ export async function validate() {
79
+ const checks = [];
80
+ const registry = lexiconRegistry();
81
+ const missing = REQUIRED_NAMES.filter((n) => !(n in registry));
82
+ checks.push(missing.length === 0
83
+ ? { name: "required-names", ok: true }
84
+ : { name: "required-names", ok: false, error: `Missing required names: ${missing.join(", ")}` });
85
+ const bad = digestMismatches();
86
+ checks.push(bad.length === 0
87
+ ? { name: "schemas-match-pin", ok: true }
88
+ : { name: "schemas-match-pin", ok: false, error: `Vendored schemas differ from GRAFANA_SCHEMA_PIN: ${bad.map((b) => b.name).join(", ")}` });
89
+ const stale = Object.entries(schemaModules())
90
+ .filter(([rel, source]) => {
91
+ try {
92
+ return readFileSync(join(pkgDir, rel), "utf-8") !== source;
93
+ }
94
+ catch {
95
+ return true;
96
+ }
97
+ })
98
+ .map(([rel]) => rel);
99
+ checks.push(stale.length === 0
100
+ ? { name: "schema-types-in-sync", ok: true }
101
+ : { name: "schema-types-in-sync", ok: false, error: `Run npm run generate: stale ${stale.join(", ")}` });
102
+ const classes = Object.entries(panels).filter((e) => typeof e[1] === "function" && "definition" in e[1]);
103
+ const broken = [];
104
+ for (const [name, Cls] of classes) {
105
+ try {
106
+ const json = renderDashboard(new Dashboard({ title: name, uid: "validate", panels: [new Cls({ title: name })] }));
107
+ const problems = validateDashboardSchema(json);
108
+ if (problems.length > 0)
109
+ broken.push(`${name} (${problems[0].path}: ${problems[0].message})`);
110
+ }
111
+ catch (err) {
112
+ broken.push(`${name} (${err instanceof Error ? err.message : String(err)})`);
113
+ }
114
+ }
115
+ checks.push(broken.length === 0
116
+ ? { name: "panels-match-schema", ok: true }
117
+ : { name: "panels-match-schema", ok: false, error: `Panels whose dashboard fails the schema: ${broken.join(", ")}` });
118
+ checks.push(BUILTIN_CATALOG.length === Object.keys(registry).length
119
+ ? { name: "catalog-matches-registry", ok: true }
120
+ : { name: "catalog-matches-registry", ok: false, error: "catalog and registry disagree" });
121
+ return { success: checks.every((c) => c.ok), checks };
122
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@intentius/chant-lexicon-grafana/validation`: the GRAF101-GRAF117 checks
3
+ * as plain functions over built Grafana output, and the schema validation
4
+ * behind GRAF107, for code that checks dashboards without a build.
5
+ *
6
+ * These are not on the package root, so importing the lexicon to declare
7
+ * dashboards does not load them. `chant build` and `chant lint` run the same
8
+ * checks through the plugin's post-synth checks. ajv is loaded the first time
9
+ * a schema is checked, and the schemas come from a generated module rather
10
+ * than files, so this works bundled.
11
+ */
12
+ export { validateGrafanaOutput, issuesFor, knownDatasourcesOf, } from "./validate-output.js";
13
+ export { validateDashboardSchema, validateExpressionSchema, schemaValidationUnavailable, } from "./schema-validate.js";
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Dashboard variables (Grafana's "templating"): query, custom, interval,
3
+ * datasource, constant, textbox, ad hoc filters, group by and switch.
4
+ *
5
+ * A variable is declared on its own and listed in a dashboard's
6
+ * `variables`. Queries reference it as `$name` or `${name}` in their
7
+ * expression; GRAF103 checks every such reference names a declared
8
+ * variable. A `DatasourceVariable` can stand in for a datasource on a panel
9
+ * or query, and the reference becomes `${name}`.
10
+ */
11
+ import { createProperty } from "@intentius/chant/runtime";
12
+ /** The kinds Grafana can repeat a panel or row over: the ones that hold a list of values (`MultiValueVariable` in @grafana/scenes). */
13
+ export const MULTI_VALUE_KINDS = new Set(["query", "custom", "datasource", "groupby"]);
14
+ export const VARIABLE_TYPE_PREFIX = "Grafana::Variable::";
15
+ function variableClass(kind, className) {
16
+ const Base = createProperty(`${VARIABLE_TYPE_PREFIX}${kind}`, "grafana");
17
+ const Cls = function (props) {
18
+ Base.call(this, props);
19
+ Object.defineProperty(this, "variableKind", { value: kind, enumerable: false });
20
+ Object.defineProperty(this, "variableName", { value: props.name, enumerable: false });
21
+ if (kind === "datasource") {
22
+ Object.defineProperty(this, "pluginType", { value: props.pluginType, enumerable: false });
23
+ }
24
+ };
25
+ Object.defineProperty(Cls, "name", { value: className });
26
+ return Cls;
27
+ }
28
+ /** A variable whose values come from a datasource query. */
29
+ export const QueryVariable = variableClass("query", "QueryVariable");
30
+ /** A variable with a fixed list of values. */
31
+ export const CustomVariable = variableClass("custom", "CustomVariable");
32
+ /** A time interval to choose, used as `$name` in range selectors. */
33
+ export const IntervalVariable = variableClass("interval", "IntervalVariable");
34
+ /** A choice of datasource of one plugin type. Usable wherever a datasource is. */
35
+ export const DatasourceVariable = variableClass("datasource", "DatasourceVariable");
36
+ /** A hidden, fixed value. */
37
+ export const ConstantVariable = variableClass("constant", "ConstantVariable");
38
+ /** A free-text box. */
39
+ export const TextboxVariable = variableClass("textbox", "TextboxVariable");
40
+ /**
41
+ * Ad hoc filters: `key operator value` filters Grafana adds to every query
42
+ * sent to the variable's datasource (Prometheus, Loki, Elasticsearch,
43
+ * InfluxDB and others whose plugin supports them). Referenced by no query.
44
+ */
45
+ export const AdhocVariable = variableClass("adhoc", "AdhocVariable");
46
+ /**
47
+ * Group by: a choice of label keys Grafana adds as a grouping to every query
48
+ * sent to the variable's datasource. In Grafana 12.4 and 13.x it is
49
+ * experimental: with the `groupByVariable` feature toggle off, Grafana
50
+ * drops it when the dashboard loads.
51
+ */
52
+ export const GroupByVariable = variableClass("groupby", "GroupByVariable");
53
+ /** An on/off switch, `$name` being `enabledValue` or `disabledValue`. New in Grafana 12.3. */
54
+ export const SwitchVariable = variableClass("switch", "SwitchVariable");
55
+ export function isVariableEntity(value) {
56
+ return (typeof value === "object" &&
57
+ value !== null &&
58
+ value.lexicon === "grafana" &&
59
+ typeof value.entityType === "string" &&
60
+ value.entityType.startsWith(VARIABLE_TYPE_PREFIX));
61
+ }
62
+ export function isDatasourceVariable(value) {
63
+ return isVariableEntity(value) && value.variableKind === "datasource";
64
+ }
65
+ /** Variable names Grafana defines itself; queries may use them without declaring anything. */
66
+ export function isBuiltinVariable(name) {
67
+ return name.startsWith("__") || name === "timeFilter" || name === "interval" || name === "interval_ms";
68
+ }
69
+ /** A valid variable name: what `$name` can match. */
70
+ export const VARIABLE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-grafana",
3
- "version": "0.124.30",
3
+ "version": "0.124.32",
4
4
  "description": "Grafana lexicon for chant — typed dashboards, panels, queries and datasources, serialized to dashboard JSON and Grafana provisioning files",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -36,22 +36,22 @@
36
36
  ".": {
37
37
  "development": "./src/index.ts",
38
38
  "types": "./dist/index.d.ts",
39
- "default": "./src/index.ts"
39
+ "default": "./dist/index.js"
40
40
  },
41
41
  "./*": {
42
42
  "development": "./src/*.ts",
43
43
  "types": "./dist/*.d.ts",
44
- "default": "./src/*.ts"
44
+ "default": "./dist/*.js"
45
45
  },
46
46
  "./op/activities": {
47
47
  "development": "./src/op/activities/index.ts",
48
48
  "types": "./dist/op/activities/index.d.ts",
49
- "default": "./src/op/activities/index.ts"
49
+ "default": "./dist/op/activities/index.js"
50
50
  },
51
51
  "./lint/post-synth": {
52
52
  "development": "./src/lint/post-synth/index.ts",
53
53
  "types": "./dist/lint/post-synth/index.d.ts",
54
- "default": "./src/lint/post-synth/index.ts"
54
+ "default": "./dist/lint/post-synth/index.js"
55
55
  },
56
56
  "./manifest": "./dist/manifest.json",
57
57
  "./meta": "./dist/meta.json",
@@ -63,14 +63,14 @@
63
63
  "validate": "tsx src/validate-cli.ts",
64
64
  "docs": "tsx src/codegen/docs-cli.ts",
65
65
  "prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
66
- "build": "../../scripts/tsc7.sh -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete"
66
+ "build": "../../scripts/tsc7.sh -p tsconfig.build.json --sourceMap false && tsc-alias -p tsconfig.build.json"
67
67
  },
68
68
  "dependencies": {
69
69
  "@grafana/lezer-logql": "0.4.2",
70
70
  "@grafana/lezer-traceql": "1.0.3",
71
- "@intentius/chant-lexicon-k8s": "^0.124.30",
72
- "@intentius/chant-lexicon-otel": "^0.124.30",
73
- "@intentius/chant-lexicon-prometheus": "^0.124.30",
71
+ "@intentius/chant-lexicon-k8s": "^0.124.32",
72
+ "@intentius/chant-lexicon-otel": "^0.124.32",
73
+ "@intentius/chant-lexicon-prometheus": "^0.124.32",
74
74
  "@lezer/lr": "^1.4.10",
75
75
  "ajv": "^8.20.0",
76
76
  "js-yaml": "^4.3.1"
@@ -83,7 +83,7 @@
83
83
  "zod": "^4.3.6"
84
84
  },
85
85
  "peerDependencies": {
86
- "@intentius/chant": "^0.124.30",
86
+ "@intentius/chant": "^0.124.32",
87
87
  "zod": "^4.3.6"
88
88
  }
89
89
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { readFileSync } from "fs";
6
6
  import { join, dirname } from "path";
7
- import { fileURLToPath } from "url";
7
+ import { moduleSourceDir } from "@intentius/chant/module-source";
8
8
  import {
9
9
  packagePipeline,
10
10
  collectSkills,
@@ -17,7 +17,7 @@ import { grafanaSkills } from "../skill-defs";
17
17
  export type { PackageOptions, PackageResult };
18
18
 
19
19
  // src/codegen/package.ts -> src/
20
- const srcDir = dirname(dirname(fileURLToPath(import.meta.url)));
20
+ const srcDir = dirname(moduleSourceDir(import.meta.url));
21
21
 
22
22
  export async function packageLexicon(opts: PackageOptions = {}): Promise<PackageResult> {
23
23
  const pkgJson = JSON.parse(readFileSync(join(srcDir, "..", "package.json"), "utf-8"));
@@ -15,7 +15,7 @@
15
15
  import { execFileSync } from "child_process";
16
16
  import { writeFileSync } from "fs";
17
17
  import { dirname, join } from "path";
18
- import { fileURLToPath } from "url";
18
+ import { moduleSourceDir } from "@intentius/chant/module-source";
19
19
  import { GRAFANA_NOTIFIERS_SOURCE, renderNotifiers, type NotifierResponse } from "./notifiers";
20
20
 
21
21
  /** curl, not fetch: the response is read from a Grafana the caller runs, and the egress catalogue lists only the commands that reach a remote host. */
@@ -50,6 +50,6 @@ async function viaDocker(): Promise<NotifierResponse[]> {
50
50
  }
51
51
 
52
52
  const notifiers = process.argv[2] ? readFrom(process.argv[2].replace(/\/$/, "")) : await viaDocker();
53
- const out = join(dirname(fileURLToPath(import.meta.url)), "..", "contact-point-settings.gen.ts");
53
+ const out = join(moduleSourceDir(import.meta.url), "..", "contact-point-settings.gen.ts");
54
54
  writeFileSync(out, renderNotifiers(notifiers));
55
55
  console.log(`wrote ${out} (${notifiers.length} integrations)`);
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { writeFileSync } from "fs";
10
10
  import { dirname, join } from "path";
11
- import { fileURLToPath } from "url";
11
+ import { moduleSourceDir } from "@intentius/chant/module-source";
12
12
  import { sha256 } from "./schemas";
13
13
  import { GRAFANA_UNITS_SOURCE, LEGACY_UNIT_ALIASES } from "./units";
14
14
 
@@ -33,5 +33,5 @@ export const GRAFANA_UNIT_IDS: readonly string[] = [
33
33
  ${ids.map((id) => ` ${JSON.stringify(id)},`).join("\n")}
34
34
  ];
35
35
  `;
36
- writeFileSync(join(dirname(fileURLToPath(import.meta.url)), "units.gen.ts"), out);
36
+ writeFileSync(join(moduleSourceDir(import.meta.url), "units.gen.ts"), out);
37
37
  console.error(`${ids.length} unit ids from ${repo}@${ref} written to src/spec/units.gen.ts`);
@@ -19,7 +19,7 @@
19
19
 
20
20
  import { existsSync, readFileSync } from "fs";
21
21
  import { dirname, join } from "path";
22
- import { fileURLToPath } from "url";
22
+ import { moduleSourceDir } from "@intentius/chant/module-source";
23
23
  import type { SchemaName } from "../pin";
24
24
 
25
25
  export interface OverlayPatch {
@@ -42,7 +42,7 @@ export interface SchemaOverlay {
42
42
  }
43
43
 
44
44
  export function overlayDir(): string {
45
- return join(dirname(fileURLToPath(import.meta.url)), "overlay");
45
+ return join(moduleSourceDir(import.meta.url), "overlay");
46
46
  }
47
47
 
48
48
  export function overlayPath(name: SchemaName): string {
@@ -13,13 +13,13 @@
13
13
  import { createHash } from "crypto";
14
14
  import { readFileSync } from "fs";
15
15
  import { dirname, join } from "path";
16
- import { fileURLToPath } from "url";
16
+ import { moduleSourceDir } from "@intentius/chant/module-source";
17
17
  import { GRAFANA_SCHEMA_PIN, VENDORED_SCHEMA_NAMES, type SchemaName, type VendoredSchemaName } from "../pin";
18
18
  import { applyOverlay, loadOverlay } from "./overlay";
19
19
 
20
20
  /** Where the vendored files live: beside this module, under `src/`. */
21
21
  export function schemasDir(): string {
22
- return join(dirname(fileURLToPath(import.meta.url)), "schemas");
22
+ return join(moduleSourceDir(import.meta.url), "schemas");
23
23
  }
24
24
 
25
25
  export function schemaPath(name: VendoredSchemaName): string {