From 7963ad8fae1923daafc6d002b828e769e93960fb Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 21 Jan 2026 14:23:22 -0500 Subject: [PATCH 1/4] handle ineligible_guides field in the guides fetch resp --- packages/client/src/clients/guide/client.ts | 9 ++- packages/client/src/clients/guide/types.ts | 12 ++++ .../client/test/clients/guide/guide.test.ts | 72 ++++++++++++++++--- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/packages/client/src/clients/guide/client.ts b/packages/client/src/clients/guide/client.ts index 62528df6..77de9b1a 100644 --- a/packages/client/src/clients/guide/client.ts +++ b/packages/client/src/clients/guide/client.ts @@ -277,6 +277,7 @@ export class KnockGuideClient { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location, @@ -358,7 +359,12 @@ export class KnockGuideClient { >(this.channelId, queryParams); queryStatus = { status: "ok" }; - const { entries, guide_groups: groups, guide_group_display_logs } = data; + const { + entries, + guide_groups: groups, + guide_group_display_logs, + ineligible_guides, + } = data; this.knock.log("[Guide] Loading fetched guides"); this.store.setState((state) => ({ @@ -366,6 +372,7 @@ export class KnockGuideClient { guideGroups: groups?.length > 0 ? groups : [mockDefaultGroup(entries)], guideGroupDisplayLogs: guide_group_display_logs || {}, guides: byKey(entries.map((g) => this.localCopy(g))), + ineligibleGuides: byKey(ineligible_guides), queries: { ...state.queries, [queryKey]: queryStatus }, })); } catch (e) { diff --git a/packages/client/src/clients/guide/types.ts b/packages/client/src/clients/guide/types.ts index 2b5fcd2b..47e5f209 100644 --- a/packages/client/src/clients/guide/types.ts +++ b/packages/client/src/clients/guide/types.ts @@ -65,6 +65,13 @@ export interface GuideGroupData { updated_at: string; } +export type GuideIneligibilityMarker = { + __typename: "GuideIneligibilityMarker"; + key: KnockGuide["key"]; + reason: string; + message: string; +}; + export type GetGuidesQueryParams = { data?: string; tenant?: string; @@ -76,6 +83,7 @@ export type GetGuidesResponse = { entries: GuideData[]; guide_groups: GuideGroupData[]; guide_group_display_logs: Record; + ineligible_guides: GuideIneligibilityMarker[]; }; // @@ -202,6 +210,10 @@ export type StoreState = { guideGroups: GuideGroupData[]; guideGroupDisplayLogs: Record; guides: Record; + ineligibleGuides: Record< + GuideIneligibilityMarker["key"], + GuideIneligibilityMarker + >; previewGuides: Record; queries: Record; location: string | undefined; diff --git a/packages/client/test/clients/guide/guide.test.ts b/packages/client/test/clients/guide/guide.test.ts index 26da6f0f..c04417d6 100644 --- a/packages/client/test/clients/guide/guide.test.ts +++ b/packages/client/test/clients/guide/guide.test.ts @@ -24,6 +24,7 @@ const mockStore = { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -45,6 +46,7 @@ const mockStore = { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -94,6 +96,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -104,6 +107,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -156,6 +160,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -184,6 +189,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: "https://example.com", @@ -200,6 +206,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -593,6 +600,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -623,6 +631,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -654,6 +663,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -689,6 +699,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -744,6 +755,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [unthrottledGuide.key]: unthrottledGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -798,6 +810,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [throttledGuide.key]: throttledGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -858,6 +871,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: { [unthrottledGuide.key]: unthrottledGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1027,6 +1041,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1048,6 +1063,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1068,6 +1084,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1088,6 +1105,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: "https://example.com/dashboard", @@ -1108,6 +1126,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: "https://example.com/settings", @@ -1146,8 +1165,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/dashboard", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1182,8 +1202,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/dashboard", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1218,8 +1239,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/settings", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1253,8 +1275,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/user/settings", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1294,8 +1317,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/admin/settings", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1337,8 +1361,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/dashboard", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1374,8 +1399,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/dashboard", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1411,8 +1437,9 @@ describe("KnockGuideClient", () => { queries: {}, location: "https://example.com/dashboard", counter: 0, + ineligibleGuides: {}, previewGuides: {}, - debug: { forcedGuideKey: null }, + debug: { forcedGuideKey: null, previewSessionId: null }, }; const client = new KnockGuideClient(mockKnock, channelId); @@ -1451,6 +1478,7 @@ describe("KnockGuideClient", () => { [g2.key]: g2, [g3.key]: g3, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: "https://example.com/settings", @@ -1469,6 +1497,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1499,6 +1528,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1577,6 +1607,7 @@ describe("KnockGuideClient", () => { ...mockGuides, [mockGuideFour.key]: mockGuideFour, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1658,6 +1689,7 @@ describe("KnockGuideClient", () => { ], }, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1694,6 +1726,7 @@ describe("KnockGuideClient", () => { ...mockGuides, [mockGuideThree.key]: archivedGuide, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1734,6 +1767,7 @@ describe("KnockGuideClient", () => { ...mockGuides, [mockGuideTwo.key]: undefined as unknown as KnockGuide, }, + ineligibleGuides: {}, previewGuides: { [mockGuideTwo.key]: previewGuide, }, @@ -1774,6 +1808,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: { [mockGuideTwo.key]: previewGuide, }, @@ -1812,6 +1847,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: { [mockGuideTwo.key]: previewGuide, }, @@ -1846,6 +1882,7 @@ describe("KnockGuideClient", () => { default: new Date().toISOString(), }, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1887,6 +1924,7 @@ describe("KnockGuideClient", () => { bypass_global_group_limit: true, }, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -1912,6 +1950,7 @@ describe("KnockGuideClient", () => { default: new Date().toISOString(), // Throttle window started now }, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2025,6 +2064,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2095,6 +2135,7 @@ describe("KnockGuideClient", () => { ], }, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2115,6 +2156,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: {}, + ineligibleGuides: {}, previewGuides: { [mockGuideTwo.key]: mockGuideTwo, }, @@ -2146,6 +2188,7 @@ describe("KnockGuideClient", () => { active: false, }, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2169,6 +2212,7 @@ describe("KnockGuideClient", () => { guideGroups: [mockDefaultGroup], guideGroupDisplayLogs: {}, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2200,6 +2244,7 @@ describe("KnockGuideClient", () => { default: new Date().toISOString(), // Throttle window started now }, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2234,6 +2279,7 @@ describe("KnockGuideClient", () => { ...mockGuides, [mockGuideTwo.key]: mockGuideWithBypass, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2262,6 +2308,7 @@ describe("KnockGuideClient", () => { default: new Date().toISOString(), // Throttle window started now }, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2300,6 +2347,7 @@ describe("KnockGuideClient", () => { default: tenMinutesAgo, }, guides: mockGuides, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2376,6 +2424,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [existingGuide.key]: existingGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2430,6 +2479,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [existingGuide.key]: existingGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2476,6 +2526,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [existingGuide.key]: existingGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2569,6 +2620,7 @@ describe("KnockGuideClient", () => { [mockGuideOne.key]: mockGuideOne, [mockGuideTwo.key]: mockGuideTwo, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2625,6 +2677,7 @@ describe("KnockGuideClient", () => { [mockGuideOne.key]: mockGuideOne, [mockGuideTwo.key]: mockGuideTwo, }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2894,6 +2947,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -2946,6 +3000,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, @@ -3043,6 +3098,7 @@ describe("KnockGuideClient", () => { guideGroups: [], guideGroupDisplayLogs: {}, guides: { [mockGuide.key]: mockGuide }, + ineligibleGuides: {}, previewGuides: {}, queries: {}, location: undefined, From 12805f0f0f02cfb9c37b82191cb69eb78c73ac36 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 2 Feb 2026 16:34:13 -0500 Subject: [PATCH 2/4] always skip ineligible guides in select func --- packages/client/src/clients/guide/client.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/client/src/clients/guide/client.ts b/packages/client/src/clients/guide/client.ts index 77de9b1a..56d25ab8 100644 --- a/packages/client/src/clients/guide/client.ts +++ b/packages/client/src/clients/guide/client.ts @@ -164,6 +164,9 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => { const guide = state.previewGuides[guideKey] || state.guides[guideKey]; if (!guide) continue; + const ineligible = !!state.ineligibleGuides[guide.key]; + if (ineligible) continue; + const affirmed = predicate(guide, { location, filters, From 771ad6671a9fe1ce25aef0de9b0494e07b10e6ae Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 3 Feb 2026 14:09:36 -0500 Subject: [PATCH 3/4] add tests --- .../client/test/clients/guide/guide.test.ts | 124 +++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/packages/client/test/clients/guide/guide.test.ts b/packages/client/test/clients/guide/guide.test.ts index c04417d6..2c43dbf8 100644 --- a/packages/client/test/clients/guide/guide.test.ts +++ b/packages/client/test/clients/guide/guide.test.ts @@ -288,6 +288,61 @@ describe("KnockGuideClient", () => { ); }); + test("stores ineligible_guides from fetch response into the store", async () => { + const mockIneligibleGuides = [ + { + __typename: "GuideIneligibilityMarker" as const, + key: "guide_123", + reason: "marked_as_archived", + message: "User has archived this guide already", + }, + { + __typename: "GuideIneligibilityMarker" as const, + key: "guide_456", + reason: "not_in_target_audience", + message: "User is not a member of the target audience", + }, + ]; + + const mockResponse = { + entries: [ + { + __typename: "Guide", + channel_id: channelId, + id: "guide_789", + key: "active_guide", + type: "test", + semver: "1.0.0", + active: true, + steps: [], + activation_url_rules: [], + activation_url_patterns: [], + bypass_global_group_limit: false, + inserted_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }, + ], + guide_groups: [], + guide_group_display_logs: {}, + ineligible_guides: mockIneligibleGuides, + }; + + vi.mocked(mockKnock.user.getGuides).mockResolvedValueOnce(mockResponse); + + const client = new KnockGuideClient( + mockKnock, + channelId, + defaultTargetParams, + ); + + await client.fetch(); + + expect(client.store.state.ineligibleGuides).toEqual({ + guide_123: mockIneligibleGuides[0], + guide_456: mockIneligibleGuides[1], + }); + }); + test("handles fetch errors", async () => { const mockError = new Error("Network error"); vi.mocked(mockKnock.user.getGuides).mockRejectedValueOnce(mockError); @@ -938,7 +993,7 @@ describe("KnockGuideClient", () => { }); }); - describe("select", () => { + describe("selectGuide", () => { const mockStep = { ref: "step_1", schema_key: "foo", @@ -1972,6 +2027,73 @@ describe("KnockGuideClient", () => { expect(result2).toBeDefined(); expect(result2!.type).toBe("banner"); }); + + test("skips ineligible guides during selection", () => { + const stateWithGuides = { + guideGroups: [mockDefaultGroup], + guideGroupDisplayLogs: {}, + guides: mockGuides, + ineligibleGuides: { + feature_tour: { + __typename: "GuideIneligibilityMarker" as const, + key: "feature_tour", + reason: "target_conditions_not_met", + message: "User does not match the targeting conditions", + }, + }, + previewGuides: {}, + queries: {}, + location: undefined, + counter: 0, + debug: { forcedGuideKey: null, previewSessionId: null }, + }; + + const client = new KnockGuideClient(mockKnock, channelId); + const result = client["_selectGuide"](stateWithGuides); + + // feature_tour is first in display_sequence but is ineligible, + // so it should be skipped and onboarding should be selected next + expect(result!.key).toBe("onboarding"); + }); + + test("skips all ineligible guides and returns undefined when all are ineligible", () => { + const stateWithGuides = { + guideGroups: [mockDefaultGroup], + guideGroupDisplayLogs: {}, + guides: mockGuides, + ineligibleGuides: { + feature_tour: { + __typename: "GuideIneligibilityMarker" as const, + key: "feature_tour", + reason: "marked_as_archived", + message: "User has archived this guide already", + }, + onboarding: { + __typename: "GuideIneligibilityMarker" as const, + key: "onboarding", + reason: "marked_as_archived", + message: "User has archived this guide already", + }, + system_status: { + __typename: "GuideIneligibilityMarker" as const, + key: "system_status", + reason: "marked_as_archived", + message: "User has archived this guide already", + }, + }, + previewGuides: {}, + queries: {}, + location: undefined, + counter: 0, + debug: { forcedGuideKey: null, previewSessionId: null }, + }; + + const client = new KnockGuideClient(mockKnock, channelId); + const result = client["_selectGuide"](stateWithGuides); + + // All guides are ineligible, so should return undefined + expect(result).toBeUndefined(); + }); }); describe("selectGuides", () => { From 2c0551fb513a64ef4d7262cd27a664e577bfaa7d Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 3 Feb 2026 16:03:01 -0500 Subject: [PATCH 4/4] cursor bot feedbacks --- packages/client/src/clients/guide/client.ts | 28 ++++++++++++--------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/client/src/clients/guide/client.ts b/packages/client/src/clients/guide/client.ts index 56d25ab8..a434eaa5 100644 --- a/packages/client/src/clients/guide/client.ts +++ b/packages/client/src/clients/guide/client.ts @@ -164,12 +164,9 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => { const guide = state.previewGuides[guideKey] || state.guides[guideKey]; if (!guide) continue; - const ineligible = !!state.ineligibleGuides[guide.key]; - if (ineligible) continue; - - const affirmed = predicate(guide, { + const affirmed = predicate(guide, filters, { location, - filters, + ineligibleGuides: state.ineligibleGuides, debug: state.debug, }); @@ -182,15 +179,15 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => { return result; }; -type PredicateOpts = { - location?: string | undefined; - filters?: SelectFilterParams | undefined; - debug: DebugState; -}; +type PredicateOpts = Pick< + StoreState, + "location" | "ineligibleGuides" | "debug" +>; const predicate = ( guide: KnockGuide, - { location, filters = {}, debug = {} }: PredicateOpts, + filters: SelectFilterParams, + { location, ineligibleGuides = {}, debug = {} }: PredicateOpts, ) => { if (filters.type && filters.type !== guide.type) { return false; @@ -207,6 +204,11 @@ const predicate = ( return debug.forcedGuideKey === guide.key; } + const ineligible = ineligibleGuides[guide.key]; + if (ineligible) { + return false; + } + if (!guide.active) { return false; } @@ -375,7 +377,7 @@ export class KnockGuideClient { guideGroups: groups?.length > 0 ? groups : [mockDefaultGroup(entries)], guideGroupDisplayLogs: guide_group_display_logs || {}, guides: byKey(entries.map((g) => this.localCopy(g))), - ineligibleGuides: byKey(ineligible_guides), + ineligibleGuides: byKey(ineligible_guides || []), queries: { ...state.queries, [queryKey]: queryStatus }, })); } catch (e) { @@ -476,6 +478,8 @@ export class KnockGuideClient { private handleSocketEvent(payload: GuideSocketEvent) { const { event, data } = payload; + // TODO(KNO-11489): Include an ineligible guide in the socket payload too + // and process it when handling socket events in real time. switch (event) { case "guide.added": return this.addOrReplaceGuide(payload);