Skip to content

Commit 3611cdf

Browse files
committed
chore: move config validation to the actual config
1 parent d8f75db commit 3611cdf

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
@@ -121,7 +121,7 @@ export interface UserConfig extends CliOptions {
121121
notificationTimeoutMs: number;
122122
}
123123

124-
const defaults: UserConfig = {
124+
export const defaultUserConfig: UserConfig = {
125125
apiBaseUrl: "https://cloud.mongodb.com/",
126126
logPath: getLogPath(),
127127
exportsPath: getExportsPath(),
@@ -140,7 +140,7 @@ const defaults: UserConfig = {
140140
};
141141

142142
export const config = setupUserConfig({
143-
defaults,
143+
defaults: defaultUserConfig,
144144
cli: process.argv,
145145
env: process.env,
146146
});
@@ -305,6 +305,35 @@ export function setupUserConfig({
305305
userConfig.connectionString = connectionInfo.connectionString;
306306
}
307307

308+
const transport = userConfig.transport as string;
309+
if (transport !== "http" && transport !== "stdio") {
310+
throw new Error(`Invalid transport: ${transport}`);
311+
}
312+
313+
const telemetry = userConfig.telemetry as string;
314+
if (telemetry !== "enabled" && telemetry !== "disabled") {
315+
throw new Error(`Invalid telemetry: ${telemetry}`);
316+
}
317+
318+
if (userConfig.httpPort < 1 || userConfig.httpPort > 65535) {
319+
throw new Error(`Invalid httpPort: ${userConfig.httpPort}`);
320+
}
321+
322+
if (userConfig.loggers.length === 0) {
323+
throw new Error("No loggers found in config");
324+
}
325+
326+
const loggerTypes = new Set(userConfig.loggers);
327+
if (loggerTypes.size !== userConfig.loggers.length) {
328+
throw new Error("Duplicate loggers found in config");
329+
}
330+
331+
for (const loggerType of userConfig.loggers as string[]) {
332+
if (loggerType !== "mcp" && loggerType !== "disk" && loggerType !== "stderr") {
333+
throw new Error(`Invalid logger: ${loggerType}`);
334+
}
335+
}
336+
308337
return userConfig;
309338
}
310339

src/server.ts

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

190190
private async validateConfig(): Promise<void> {
191-
const transport = this.userConfig.transport as string;
192-
if (transport !== "http" && transport !== "stdio") {
193-
throw new Error(`Invalid transport: ${transport}`);
194-
}
195-
196-
const telemetry = this.userConfig.telemetry as string;
197-
if (telemetry !== "enabled" && telemetry !== "disabled") {
198-
throw new Error(`Invalid telemetry: ${telemetry}`);
199-
}
200-
201-
if (this.userConfig.httpPort < 1 || this.userConfig.httpPort > 65535) {
202-
throw new Error(`Invalid httpPort: ${this.userConfig.httpPort}`);
203-
}
204-
205-
if (this.userConfig.loggers.length === 0) {
206-
throw new Error("No loggers found in config");
207-
}
208-
209-
const loggerTypes = new Set(this.userConfig.loggers);
210-
if (loggerTypes.size !== this.userConfig.loggers.length) {
211-
throw new Error("Duplicate loggers found in config");
212-
}
213-
214-
for (const loggerType of this.userConfig.loggers as string[]) {
215-
if (loggerType !== "mcp" && loggerType !== "disk" && loggerType !== "stderr") {
216-
throw new Error(`Invalid logger: ${loggerType}`);
217-
}
218-
}
219-
220191
if (this.userConfig.connectionString) {
221192
try {
222193
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)