@thotischner/observability-mcp 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/loader.d.ts +1 -0
- package/dist/config/loader.js +19 -1
- package/dist/config/loader.test.js +28 -0
- package/package.json +1 -1
package/dist/config/loader.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ import type { Config, GeneralSettings, HealthThresholds } from "../types.js";
|
|
|
2
2
|
export declare const DEFAULT_SETTINGS: GeneralSettings;
|
|
3
3
|
export declare const DEFAULT_HEALTH_THRESHOLDS: HealthThresholds;
|
|
4
4
|
export declare function substituteEnv(raw: string): string;
|
|
5
|
+
export declare function substituteEnvInTree<T>(node: T): T;
|
|
5
6
|
export declare function loadConfig(): Config;
|
|
6
7
|
export declare function saveConfig(config: Config): void;
|
package/dist/config/loader.js
CHANGED
|
@@ -34,10 +34,28 @@ export function substituteEnv(raw) {
|
|
|
34
34
|
return "";
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
+
// Walk the parsed YAML tree and substitute ${VAR} only inside string values.
|
|
38
|
+
// Comments don't survive yaml.load(), so this side-steps the bug where the
|
|
39
|
+
// regex previously fired on `${...}` written in #-prefixed YAML comments.
|
|
40
|
+
export function substituteEnvInTree(node) {
|
|
41
|
+
if (typeof node === "string")
|
|
42
|
+
return substituteEnv(node);
|
|
43
|
+
if (Array.isArray(node))
|
|
44
|
+
return node.map((v) => substituteEnvInTree(v));
|
|
45
|
+
if (node && typeof node === "object") {
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const [k, v] of Object.entries(node)) {
|
|
48
|
+
out[k] = substituteEnvInTree(v);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
return node;
|
|
53
|
+
}
|
|
37
54
|
export function loadConfig() {
|
|
38
55
|
try {
|
|
39
56
|
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
40
|
-
const
|
|
57
|
+
const parsedRaw = yaml.load(raw);
|
|
58
|
+
const parsed = substituteEnvInTree(parsedRaw || {});
|
|
41
59
|
return {
|
|
42
60
|
sources: parsed?.sources || [],
|
|
43
61
|
settings: { ...DEFAULT_SETTINGS, ...parsed?.settings },
|
|
@@ -167,6 +167,34 @@ sources:
|
|
|
167
167
|
delete process.env.A;
|
|
168
168
|
delete process.env.B;
|
|
169
169
|
});
|
|
170
|
+
it("does not substitute or warn for ${VAR} inside YAML comments (#17)", async () => {
|
|
171
|
+
delete process.env.VAR;
|
|
172
|
+
const configPath = join(TMP_DIR, "comments.yaml");
|
|
173
|
+
writeFileSync(configPath, `
|
|
174
|
+
# Note: \${VAR}-style substitution is resolved at runtime from .env.
|
|
175
|
+
# Another mention of \${SHOULD_NOT_WARN} in prose.
|
|
176
|
+
sources:
|
|
177
|
+
- name: example
|
|
178
|
+
type: prometheus
|
|
179
|
+
url: http://localhost:9090
|
|
180
|
+
enabled: true
|
|
181
|
+
`);
|
|
182
|
+
process.env.CONFIG_PATH = configPath;
|
|
183
|
+
const warnings = [];
|
|
184
|
+
const origWarn = console.warn;
|
|
185
|
+
console.warn = (msg) => warnings.push(msg);
|
|
186
|
+
try {
|
|
187
|
+
const mod = await import("./loader.js?" + Date.now());
|
|
188
|
+
const config = mod.loadConfig();
|
|
189
|
+
assert.equal(config.sources.length, 1);
|
|
190
|
+
assert.equal(config.sources[0].url, "http://localhost:9090");
|
|
191
|
+
const hits = warnings.filter((w) => w.includes("VAR") || w.includes("SHOULD_NOT_WARN"));
|
|
192
|
+
assert.equal(hits.length, 0, `expected no warnings for comment placeholders, got: ${hits.join("; ")}`);
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
console.warn = origWarn;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
170
198
|
it("substitutes inside loaded YAML config", async () => {
|
|
171
199
|
process.env.GRAFANA_USER = "12345";
|
|
172
200
|
process.env.GRAFANA_TOKEN = "secret-token";
|
package/package.json
CHANGED