Skip to content

Commit dbd633e

Browse files
committed
chore: move config validation to the actual config
1 parent c95bf72 commit dbd633e

File tree

3 files changed

+66
-68
lines changed

3 files changed

+66
-68
lines changed

src/common/config.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export interface UserConfig extends CliOptions {
118118
notificationTimeoutMs: number;
119119
}
120120

121-
const defaults: UserConfig = {
121+
export const defaultUserConfig: UserConfig = {
122122
apiBaseUrl: "https://cloud.mongodb.com/",
123123
logPath: getLogPath(),
124124
disabledTools: [],
@@ -134,7 +134,7 @@ const defaults: UserConfig = {
134134
};
135135

136136
export const config = setupUserConfig({
137-
defaults,
137+
defaults: defaultUserConfig,
138138
cli: process.argv,
139139
env: process.env,
140140
});
@@ -295,6 +295,35 @@ export function setupUserConfig({
295295
userConfig.connectionString = connectionInfo.connectionString;
296296
}
297297

298+
const transport = userConfig.transport as string;
299+
if (transport !== "http" && transport !== "stdio") {
300+
throw new Error(`Invalid transport: ${transport}`);
301+
}
302+
303+
const telemetry = userConfig.telemetry as string;
304+
if (telemetry !== "enabled" && telemetry !== "disabled") {
305+
throw new Error(`Invalid telemetry: ${telemetry}`);
306+
}
307+
308+
if (userConfig.httpPort < 1 || userConfig.httpPort > 65535) {
309+
throw new Error(`Invalid httpPort: ${userConfig.httpPort}`);
310+
}
311+
312+
if (userConfig.loggers.length === 0) {
313+
throw new Error("No loggers found in config");
314+
}
315+
316+
const loggerTypes = new Set(userConfig.loggers);
317+
if (loggerTypes.size !== userConfig.loggers.length) {
318+
throw new Error("Duplicate loggers found in config");
319+
}
320+
321+
for (const loggerType of userConfig.loggers as string[]) {
322+
if (loggerType !== "mcp" && loggerType !== "disk" && loggerType !== "stderr") {
323+
throw new Error(`Invalid logger: ${loggerType}`);
324+
}
325+
}
326+
298327
return userConfig;
299328
}
300329

src/server.ts

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -154,35 +154,6 @@ export class Server {
154154
}
155155

156156
private async validateConfig(): Promise<void> {
157-
const transport = this.userConfig.transport as string;
158-
if (transport !== "http" && transport !== "stdio") {
159-
throw new Error(`Invalid transport: ${transport}`);
160-
}
161-
162-
const telemetry = this.userConfig.telemetry as string;
163-
if (telemetry !== "enabled" && telemetry !== "disabled") {
164-
throw new Error(`Invalid telemetry: ${telemetry}`);
165-
}
166-
167-
if (this.userConfig.httpPort < 1 || this.userConfig.httpPort > 65535) {
168-
throw new Error(`Invalid httpPort: ${this.userConfig.httpPort}`);
169-
}
170-
171-
if (this.userConfig.loggers.length === 0) {
172-
throw new Error("No loggers found in config");
173-
}
174-
175-
const loggerTypes = new Set(this.userConfig.loggers);
176-
if (loggerTypes.size !== this.userConfig.loggers.length) {
177-
throw new Error("Duplicate loggers found in config");
178-
}
179-
180-
for (const loggerType of this.userConfig.loggers as string[]) {
181-
if (loggerType !== "mcp" && loggerType !== "disk" && loggerType !== "stderr") {
182-
throw new Error(`Invalid logger: ${loggerType}`);
183-
}
184-
}
185-
186157
if (this.userConfig.connectionString) {
187158
try {
188159
await this.session.connectToMongoDB({

tests/unit/common/config.test.ts

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
11
import { describe, it, expect } from "vitest";
2-
import { setupUserConfig, UserConfig } from "../../../src/common/config.js";
2+
import { setupUserConfig, UserConfig, defaultUserConfig } from "../../../src/common/config.js";
33

44
describe("config", () => {
55
describe("env var parsing", () => {
66
describe("string cases", () => {
7-
const testCases = {
8-
MDB_MCP_API_BASE_URL: "apiBaseUrl",
9-
MDB_MCP_API_CLIENT_ID: "apiClientId",
10-
MDB_MCP_API_CLIENT_SECRET: "apiClientSecret",
11-
MDB_MCP_TELEMETRY: "telemetry",
12-
MDB_MCP_LOG_PATH: "logPath",
13-
MDB_MCP_CONNECTION_STRING: "connectionString",
14-
MDB_MCP_READ_ONLY: "readOnly",
15-
MDB_MCP_INDEX_CHECK: "indexCheck",
16-
MDB_MCP_TRANSPORT: "transport",
17-
MDB_MCP_HTTP_PORT: "httpPort",
18-
MDB_MCP_HTTP_HOST: "httpHost",
19-
MDB_MCP_IDLE_TIMEOUT_MS: "idleTimeoutMs",
20-
MDB_MCP_NOTIFICATION_TIMEOUT_MS: "notificationTimeoutMs",
21-
} as const;
22-
23-
for (const [envVar, config] of Object.entries(testCases)) {
24-
it(`should map ${envVar} to ${config}`, () => {
25-
const randomValue = "value=" + Math.random();
7+
const testCases = [
8+
{ envVar: "MDB_MCP_API_BASE_URL", property: "apiBaseUrl", value: "http://test.com" },
9+
{ envVar: "MDB_MCP_API_CLIENT_ID", property: "apiClientId", value: "ClientIdLol" },
10+
{ envVar: "MDB_MCP_API_CLIENT_SECRET", property: "apiClientSecret", value: "SuperClientSecret" },
11+
{ envVar: "MDB_MCP_TELEMETRY", property: "telemetry", value: "enabled" },
12+
{ envVar: "MDB_MCP_LOG_PATH", property: "logPath", value: "/var/log" },
13+
{ envVar: "MDB_MCP_CONNECTION_STRING", property: "connectionString", value: "mongodb://localhost" },
14+
{ envVar: "MDB_MCP_READ_ONLY", property: "readOnly", value: true },
15+
{ envVar: "MDB_MCP_INDEX_CHECK", property: "indexCheck", value: true },
16+
{ envVar: "MDB_MCP_TRANSPORT", property: "transport", value: "http" },
17+
{ envVar: "MDB_MCP_HTTP_PORT", property: "httpPort", value: 8080 },
18+
{ envVar: "MDB_MCP_HTTP_HOST", property: "httpHost", value: "localhost" },
19+
{ envVar: "MDB_MCP_IDLE_TIMEOUT_MS", property: "idleTimeoutMs", value: 5000 },
20+
{ envVar: "MDB_MCP_NOTIFICATION_TIMEOUT_MS", property: "notificationTimeoutMs", value: 5000 },
21+
] as const;
2622

23+
for (const { envVar, property, value } of testCases) {
24+
it(`should map ${envVar} to ${property} with value "${value}"`, () => {
2725
const actual = setupUserConfig({
2826
cli: [],
2927
env: {
30-
[envVar]: randomValue,
28+
[envVar]: String(value),
3129
},
32-
defaults: {},
30+
defaults: defaultUserConfig,
3331
});
3432

35-
expect(actual[config]).toBe(randomValue);
33+
expect(actual[property]).toBe(value);
3634
});
3735
}
3836
});
@@ -45,17 +43,15 @@ describe("config", () => {
4543

4644
for (const [envVar, config] of Object.entries(testCases)) {
4745
it(`should map ${envVar} to ${config}`, () => {
48-
const randomValue = "value=" + Math.random();
49-
5046
const actual = setupUserConfig({
5147
cli: [],
5248
env: {
53-
[envVar]: randomValue,
49+
[envVar]: "disk,mcp",
5450
},
55-
defaults: {},
51+
defaults: defaultUserConfig,
5652
});
5753

58-
expect(actual[config]).toEqual([randomValue]);
54+
expect(actual[config]).toEqual(["disk", "mcp"]);
5955
});
6056
}
6157
});
@@ -101,8 +97,8 @@ describe("config", () => {
10197
expected: { notificationTimeoutMs: "42" },
10298
},
10399
{
104-
cli: ["--telemetry", "obviously"],
105-
expected: { telemetry: "obviously" },
100+
cli: ["--telemetry", "enabled"],
101+
expected: { telemetry: "enabled" },
106102
},
107103
{
108104
cli: ["--transport", "stdio"],
@@ -223,7 +219,7 @@ describe("config", () => {
223219
const actual = setupUserConfig({
224220
cli: ["myself", "--", ...cli],
225221
env: {},
226-
defaults: {},
222+
defaults: defaultUserConfig,
227223
});
228224

229225
for (const [key, value] of Object.entries(expected)) {
@@ -322,7 +318,7 @@ describe("config", () => {
322318
const actual = setupUserConfig({
323319
cli: ["myself", "--", ...cli],
324320
env: {},
325-
defaults: {},
321+
defaults: defaultUserConfig,
326322
});
327323

328324
for (const [key, value] of Object.entries(expected)) {
@@ -339,8 +335,8 @@ describe("config", () => {
339335
expected: { disabledTools: ["some", "tool"] },
340336
},
341337
{
342-
cli: ["--loggers", "canada,file"],
343-
expected: { loggers: ["canada", "file"] },
338+
cli: ["--loggers", "disk,mcp"],
339+
expected: { loggers: ["disk", "mcp"] },
344340
},
345341
] as { cli: string[]; expected: Partial<UserConfig> }[];
346342

@@ -349,7 +345,7 @@ describe("config", () => {
349345
const actual = setupUserConfig({
350346
cli: ["myself", "--", ...cli],
351347
env: {},
352-
defaults: {},
348+
defaults: defaultUserConfig,
353349
});
354350

355351
for (const [key, value] of Object.entries(expected)) {
@@ -365,7 +361,7 @@ describe("config", () => {
365361
const actual = setupUserConfig({
366362
cli: ["myself", "--", "--connectionString", "mongodb://localhost"],
367363
env: { MDB_MCP_CONNECTION_STRING: "mongodb://crazyhost" },
368-
defaults: {},
364+
defaults: defaultUserConfig,
369365
});
370366

371367
expect(actual.connectionString).toBe("mongodb://localhost");
@@ -376,6 +372,7 @@ describe("config", () => {
376372
cli: ["myself", "--", "--connectionString", "mongodb://localhost"],
377373
env: {},
378374
defaults: {
375+
...defaultUserConfig,
379376
connectionString: "mongodb://crazyhost",
380377
},
381378
});
@@ -388,6 +385,7 @@ describe("config", () => {
388385
cli: [],
389386
env: { MDB_MCP_CONNECTION_STRING: "mongodb://localhost" },
390387
defaults: {
388+
...defaultUserConfig,
391389
connectionString: "mongodb://crazyhost",
392390
},
393391
});
@@ -401,7 +399,7 @@ describe("config", () => {
401399
const actual = setupUserConfig({
402400
cli: ["myself", "--", "mongodb://localhost", "--connectionString", "toRemove"],
403401
env: {},
404-
defaults: {},
402+
defaults: defaultUserConfig,
405403
});
406404

407405
// the shell specifies directConnection=true and serverSelectionTimeoutMS=2000 by default

0 commit comments

Comments
 (0)