diff --git a/package-lock.json b/package-lock.json index 9a65db4..4a09768 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2783,6 +2783,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -3738,6 +3754,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats/node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -5040,22 +5072,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -5463,9 +5479,9 @@ } }, "node_modules/hono": { - "version": "4.12.32", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.32.tgz", - "integrity": "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz", + "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==", "license": "MIT", "engines": { "node": ">=16.9.0" diff --git a/package.json b/package.json index 4ab835a..4c71b5d 100644 --- a/package.json +++ b/package.json @@ -103,5 +103,9 @@ "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "overrides": { + "fast-uri": "^3.1.5", + "hono": "^4.12.34" } } diff --git a/src/logger.ts b/src/logger.ts index b1fb768..309e2ac 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -12,8 +12,13 @@ const LOG_LEVELS = { type LogLevel = keyof typeof LOG_LEVELS; +// DS_LOG_LEVEL is the documented name, but LOG_LEVEL is the conventional one +// and gets set by mistake - production ran silently at "warn" for months +// because the host set LOG_LEVEL=info and nothing read it. Accept both. const currentLogLevel = - LOG_LEVELS[process.env.DS_LOG_LEVEL as LogLevel] ?? LOG_LEVELS.warn; + LOG_LEVELS[process.env.DS_LOG_LEVEL as LogLevel] ?? + LOG_LEVELS[process.env.LOG_LEVEL as LogLevel] ?? + LOG_LEVELS.warn; const logger = { error: (message: string, ...args: unknown[]) => { diff --git a/tests/unit/logger.test.ts b/tests/unit/logger.test.ts index 7918f9a..26d3b9b 100644 --- a/tests/unit/logger.test.ts +++ b/tests/unit/logger.test.ts @@ -25,10 +25,9 @@ describe("logger", () => { const loggerWithErrorLevel = require("../../src/logger.js").default; loggerWithErrorLevel.error("test error", { extra: "data" }); - expect(consoleErrorSpy).toHaveBeenCalledWith( - "[ERROR] test error", - { extra: "data" } - ); + expect(consoleErrorSpy).toHaveBeenCalledWith("[ERROR] test error", { + extra: "data", + }); }); it("should log warn messages when log level is warn", () => { @@ -39,7 +38,7 @@ describe("logger", () => { loggerWithWarnLevel.warn("test warning", "extra"); expect(consoleErrorSpy).toHaveBeenCalledWith( "[WARN] test warning", - "extra" + "extra", ); }); @@ -62,7 +61,7 @@ describe("logger", () => { "[DEBUG] test debug", 1, 2, - 3 + 3, ); }); }); @@ -93,7 +92,7 @@ describe("logger", () => { loggerWithDefaultLevel.warn("should appear"); loggerWithDefaultLevel.info("should not appear"); - + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); expect(consoleErrorSpy).toHaveBeenCalledWith("[WARN] should appear"); }); @@ -106,8 +105,53 @@ describe("logger", () => { loggerWithInvalidLevel.error("should appear"); loggerWithInvalidLevel.warn("should also appear"); loggerWithInvalidLevel.info("should not appear"); - + expect(consoleErrorSpy).toHaveBeenCalledTimes(2); }); }); -}); \ No newline at end of file + + describe("LOG_LEVEL fallback", () => { + // Production ran silently at "warn" for months because the host set + // LOG_LEVEL=info while only DS_LOG_LEVEL was read. Both are accepted now. + const originalLogLevel = process.env.LOG_LEVEL; + + afterEach(() => { + if (originalLogLevel === undefined) { + delete process.env.LOG_LEVEL; + } else { + process.env.LOG_LEVEL = originalLogLevel; + } + }); + + it("honours LOG_LEVEL when DS_LOG_LEVEL is not set", () => { + delete process.env.DS_LOG_LEVEL; + process.env.LOG_LEVEL = "info"; + jest.resetModules(); + const log = require("../../src/logger.js").default; + + log.info("should appear"); + expect(consoleErrorSpy).toHaveBeenCalledWith("[INFO] should appear"); + }); + + it("lets DS_LOG_LEVEL win when both are set", () => { + process.env.DS_LOG_LEVEL = "error"; + process.env.LOG_LEVEL = "debug"; + jest.resetModules(); + const log = require("../../src/logger.js").default; + + log.warn("should not appear"); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + it("still defaults to warn when neither is set", () => { + delete process.env.DS_LOG_LEVEL; + delete process.env.LOG_LEVEL; + jest.resetModules(); + const log = require("../../src/logger.js").default; + + log.warn("should appear"); + log.info("should not appear"); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + }); + }); +});