diff --git a/packages/core/src/eventFilterMatches.ts b/packages/core/src/eventFilterMatches.ts index 86a78aef750..222d09746cb 100644 --- a/packages/core/src/eventFilterMatches.ts +++ b/packages/core/src/eventFilterMatches.ts @@ -5,16 +5,10 @@ import type { EventFilter } from "./schemas/eventFilter.js"; // If the values of the array are objects, then we are doing content filtering // An example would be [{ $endsWith: ".png" }, { $startsWith: "images/" } ] export function eventFilterMatches(payload: any, filter: EventFilter): boolean { - if (payload === undefined || payload === null) { - if (Object.entries(filter).length === 0) { - return true; - } else { - return false; - } - } + const safePayload = payload ?? {}; for (const [patternKey, patternValue] of Object.entries(filter)) { - const payloadValue = payload[patternKey]; + const payloadValue = safePayload[patternKey]; if (Array.isArray(patternValue)) { if (patternValue.length === 0) { diff --git a/packages/core/test/eventFilterMatches.test.ts b/packages/core/test/eventFilterMatches.test.ts index 4df17fa235a..a658822d93e 100644 --- a/packages/core/test/eventFilterMatches.test.ts +++ b/packages/core/test/eventFilterMatches.test.ts @@ -209,6 +209,20 @@ describe("eventFilterMatches", () => { expect(eventFilterMatches(payload, filter)).toBe(true); }); + it("should return true for nested $exists: false when parent key is missing or null", () => { + const filter: EventFilter = { + user: { + email: [{ $exists: false }], + }, + }; + + expect(eventFilterMatches({}, filter)).toBe(true); + expect(eventFilterMatches({ user: null }, filter)).toBe(true); + expect(eventFilterMatches({ user: {} }, filter)).toBe(true); + expect(eventFilterMatches({ user: { email: undefined } }, filter)).toBe(true); + expect(eventFilterMatches({ user: { email: "user@example.com" } }, filter)).toBe(false); + }); + it("should return true when payload does match numeric condition", () => { const payload = { name: "John",