diff --git a/src/core/config/resolvers/runtime-config.ts b/src/core/config/resolvers/runtime-config.ts index bfdf2acd3e..d927258575 100644 --- a/src/core/config/resolvers/runtime-config.ts +++ b/src/core/config/resolvers/runtime-config.ts @@ -39,15 +39,13 @@ function provideFallbackValues(obj: Record) { } function checkSerializableRuntimeConfig(obj: any, path: string[] = []) { + if (isPrimitiveValue(obj)) { + return; + } + for (const key in obj) { const value = obj[key]; - if ( - value === null || - typeof value === "string" || - value === undefined || - typeof value === "number" || - typeof value === "boolean" - ) { + if (value === null || value === undefined || isPrimitiveValue(value)) { continue; } @@ -67,3 +65,11 @@ function checkSerializableRuntimeConfig(obj: any, path: string[] = []) { } } } + +function isPrimitiveValue(value: any) { + return ( + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" + ); +} diff --git a/test/unit/runtime-config.test.ts b/test/unit/runtime-config.test.ts new file mode 100644 index 0000000000..d37f4d65fb --- /dev/null +++ b/test/unit/runtime-config.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, it, vi } from "vitest"; +import { normalizeRuntimeConfig } from "../../src/core/config/resolvers/runtime-config"; +import type { NitroConfig } from "nitropack/types"; + +const defaultRuntimeConfig = { + textProperty: "value", + numberProperty: 42, + booleanProperty: true, + arrayProperty: ["A", "B", "C"], + objectProperty: { + innerProperty: "value", + }, + mixedArrayProperty: [ + "A", + "B", + { + inner: { + innerProperty: "value", + }, + }, + ], +}; + +const nitroConfig: NitroConfig = { + runtimeConfig: defaultRuntimeConfig, + baseURL: "https://example.com", + experimental: { + envExpansion: false, + }, +}; + +describe("normalizeRuntimeConfig", () => { + it("should not warn on a serializable runtime config", () => { + const warnSpy = vi.spyOn(console, "warn"); + normalizeRuntimeConfig(nitroConfig); + expect(warnSpy).not.toHaveBeenCalled(); + }); + + it("should not warn when primitive prototype is changed", () => { + const warnSpy = vi.spyOn(console, "warn"); + + // https://github.com/nitrojs/nitro/pull/2902 + (String.prototype as any).brokenFunction = () => undefined; + + normalizeRuntimeConfig(nitroConfig); + expect(warnSpy).not.toHaveBeenCalled(); + + delete (String.prototype as any).brokenFunction; + }); + + it("should throw a warning when runtimeConfig is not serializable", () => { + const warnSpy = vi.spyOn(console, "warn"); + normalizeRuntimeConfig({ + ...nitroConfig, + runtimeConfig: { + ...defaultRuntimeConfig, + brokenProperty: new Map(), + }, + }); + expect(warnSpy).toHaveBeenCalled(); + }); +});