@knocklabs/client 0.14.4 → 0.14.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/clients/feed/feed.js +1 -1
  3. package/dist/cjs/clients/feed/feed.js.map +1 -1
  4. package/dist/cjs/clients/feed/index.js +1 -1
  5. package/dist/cjs/clients/feed/index.js.map +1 -1
  6. package/dist/cjs/clients/feed/socket-manager.js +2 -0
  7. package/dist/cjs/clients/feed/socket-manager.js.map +1 -0
  8. package/dist/cjs/clients/guide/client.js +1 -1
  9. package/dist/cjs/clients/guide/client.js.map +1 -1
  10. package/dist/esm/clients/feed/feed.mjs +117 -102
  11. package/dist/esm/clients/feed/feed.mjs.map +1 -1
  12. package/dist/esm/clients/feed/index.mjs +31 -15
  13. package/dist/esm/clients/feed/index.mjs.map +1 -1
  14. package/dist/esm/clients/feed/socket-manager.mjs +81 -0
  15. package/dist/esm/clients/feed/socket-manager.mjs.map +1 -0
  16. package/dist/esm/clients/guide/client.mjs +123 -65
  17. package/dist/esm/clients/guide/client.mjs.map +1 -1
  18. package/dist/types/clients/feed/feed.d.ts +11 -6
  19. package/dist/types/clients/feed/feed.d.ts.map +1 -1
  20. package/dist/types/clients/feed/index.d.ts +2 -0
  21. package/dist/types/clients/feed/index.d.ts.map +1 -1
  22. package/dist/types/clients/feed/socket-manager.d.ts +31 -0
  23. package/dist/types/clients/feed/socket-manager.d.ts.map +1 -0
  24. package/dist/types/clients/feed/types.d.ts +4 -3
  25. package/dist/types/clients/feed/types.d.ts.map +1 -1
  26. package/dist/types/clients/guide/client.d.ts +22 -1
  27. package/dist/types/clients/guide/client.d.ts.map +1 -1
  28. package/package.json +5 -3
  29. package/src/clients/feed/feed.ts +51 -41
  30. package/src/clients/feed/index.ts +27 -3
  31. package/src/clients/feed/socket-manager.ts +185 -0
  32. package/src/clients/feed/types.ts +5 -3
  33. package/src/clients/guide/client.ts +146 -2
@@ -2,25 +2,28 @@ import { GenericData } from '@knocklabs/types';
2
2
  import { StoreApi } from 'zustand';
3
3
  import { default as Knock } from '../../knock';
4
4
  import { FeedClientOptions, FetchFeedOptions } from './interfaces';
5
+ import { FeedSocketManager, SocketEventPayload } from './socket-manager';
5
6
  import { BindableFeedEvent, FeedEventCallback, FeedItemOrItems, FeedRealTimeCallback, FeedStoreState } from './types';
6
7
  declare class Feed {
7
8
  readonly knock: Knock;
8
9
  readonly feedId: string;
10
+ readonly defaultOptions: FeedClientOptions;
11
+ readonly referenceId: string;
12
+ unsubscribeFromSocketEvents: (() => void) | undefined;
13
+ private socketManager;
9
14
  private userFeedId;
10
- private channel?;
11
15
  private broadcaster;
12
- private defaultOptions;
13
16
  private broadcastChannel;
14
17
  private disconnectTimer;
15
18
  private hasSubscribedToRealTimeUpdates;
16
19
  private visibilityChangeHandler;
17
20
  private visibilityChangeListenerConnected;
18
21
  store: StoreApi<FeedStoreState>;
19
- constructor(knock: Knock, feedId: string, options: FeedClientOptions);
22
+ constructor(knock: Knock, feedId: string, options: FeedClientOptions, socketManager: FeedSocketManager | undefined);
20
23
  /**
21
24
  * Used to reinitialize a current feed instance, which is useful when reauthenticating users
22
25
  */
23
- reinitialize(): void;
26
+ reinitialize(socketManager?: FeedSocketManager): void;
24
27
  /**
25
28
  * Cleans up a feed instance by destroying the store and disconnecting
26
29
  * an open socket connection.
@@ -48,6 +51,7 @@ declare class Feed {
48
51
  data: any;
49
52
  } | undefined>;
50
53
  fetchNextPage(options?: FetchFeedOptions): Promise<void>;
54
+ get socketChannelTopic(): string;
51
55
  private broadcast;
52
56
  private onNewMessageReceived;
53
57
  private buildUserFeedId;
@@ -57,12 +61,13 @@ declare class Feed {
57
61
  private setupBroadcastChannel;
58
62
  private broadcastOverChannel;
59
63
  private initializeRealtimeConnection;
64
+ handleSocketEvent(payload: SocketEventPayload): Promise<void>;
60
65
  /**
61
66
  * Listen for changes to document visibility and automatically disconnect
62
67
  * or reconnect the socket after a delay
63
68
  */
64
- private setupAutoSocketManager;
65
- private teardownAutoSocketManager;
69
+ private setUpVisibilityListeners;
70
+ private tearDownVisibilityListeners;
66
71
  private emitEvent;
67
72
  private handleVisibilityChange;
68
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/feed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,KAAK,MAAM,aAAa,CAAC;AAOhC,OAAO,EACL,iBAAiB,EAIjB,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EAEjB,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACf,MAAM,SAAS,CAAC;AAUjB,cAAM,IAAI;IAeN,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAfzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,cAAc,CAAoB;IAC1C,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,8BAA8B,CAAkB;IACxD,OAAO,CAAC,uBAAuB,CAAwB;IACvD,OAAO,CAAC,iCAAiC,CAAkB;IAGpD,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAG5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,iBAAiB;IAyB5B;;OAEG;IACH,YAAY;IAWZ;;;OAGG;IACH,QAAQ;IAoBR,2EAA2E;IAC3E,OAAO;IAWP,gBAAgB;IA2BhB,EAAE,CACA,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,iBAAiB,GAAG,oBAAoB;IAKpD,GAAG,CACD,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,iBAAiB,GAAG,oBAAoB;IAKpD,QAAQ;IAIF,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA0Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA0Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,gBAAgB,CACpB,WAAW,EAAE,eAAe,EAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAwB7B,cAAc,CAAC,WAAW,EAAE,eAAe;IAuE3C,iBAAiB;IA2BjB,qBAAqB;IA0CrB,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAS7C,KAAK,CAAC,OAAO,GAAE,gBAAqB;;;;IA0FpC,aAAa,CAAC,OAAO,GAAE,gBAAqB;IAgBlD,OAAO,CAAC,SAAS;YAQH,oBAAoB;IAalC,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iCAAiC;YAiD3B,gBAAgB;YAsBhB,oBAAoB;IA2BlC,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,4BAA4B;IA0BpC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,sBAAsB;CA2B/B;AAED,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/feed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,KAAK,MAAM,aAAa,CAAC;AAOhC,OAAO,EACL,iBAAiB,EAIjB,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EAEjB,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACf,MAAM,SAAS,CAAC;AAYjB,cAAM,IAAI;IAiBN,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAjBzB,SAAgB,cAAc,EAAE,iBAAiB,CAAC;IAClD,SAAgB,WAAW,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAa;IACzE,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,8BAA8B,CAAkB;IACxD,OAAO,CAAC,uBAAuB,CAAwB;IACvD,OAAO,CAAC,iCAAiC,CAAkB;IAGpD,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAG5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,iBAAiB,EAC1B,aAAa,EAAE,iBAAiB,GAAG,SAAS;IA2B9C;;OAEG;IACH,YAAY,CAAC,aAAa,CAAC,EAAE,iBAAiB;IAa9C;;;OAGG;IACH,QAAQ;IAiBR,2EAA2E;IAC3E,OAAO;IAWP,gBAAgB;IAiBhB,EAAE,CACA,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,iBAAiB,GAAG,oBAAoB;IAKpD,GAAG,CACD,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,iBAAiB,GAAG,oBAAoB;IAKpD,QAAQ;IAIF,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA0Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA0Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,gBAAgB,CACpB,WAAW,EAAE,eAAe,EAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAwB7B,cAAc,CAAC,WAAW,EAAE,eAAe;IAuE3C,iBAAiB;IA2BjB,qBAAqB;IA0CrB,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAS7C,KAAK,CAAC,OAAO,GAAE,gBAAqB;;;;IA0FpC,aAAa,CAAC,OAAO,GAAE,gBAAqB;IAgBlD,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,OAAO,CAAC,SAAS;YAQH,oBAAoB;IAiBlC,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iCAAiC;YAiD3B,gBAAgB;YAsBhB,oBAAoB;IA2BlC,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,4BAA4B;IAe9B,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;IAYnD;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,sBAAsB;CA2B/B;AAED,eAAe,IAAI,CAAC"}
@@ -4,11 +4,13 @@ import { FeedClientOptions } from './interfaces';
4
4
  declare class FeedClient {
5
5
  private instance;
6
6
  private feedInstances;
7
+ private socketManager;
7
8
  constructor(instance: Knock);
8
9
  initialize(feedChannelId: string, options?: FeedClientOptions): Feed;
9
10
  removeInstance(feed: Feed): void;
10
11
  teardownInstances(): void;
11
12
  reinitializeInstances(): void;
13
+ private initSocketManager;
12
14
  }
13
15
  export { Feed };
14
16
  export default FeedClient;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,cAAM,UAAU;IACd,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,aAAa,CAAc;gBAEvB,QAAQ,EAAE,KAAK;IAI3B,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAOjE,cAAc,CAAC,IAAI,EAAE,IAAI;IAIzB,iBAAiB;IAMjB,qBAAqB;CAKtB;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAChB,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,cAAM,UAAU;IACd,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,aAAa,CAAgC;gBAEzC,QAAQ,EAAE,KAAK;IAI3B,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAajE,cAAc,CAAC,IAAI,EAAE,IAAI;IAIzB,iBAAiB;IAMjB,qBAAqB;IAerB,OAAO,CAAC,iBAAiB;CAM1B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAChB,eAAe,UAAU,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { Socket } from 'phoenix';
2
+ import { default as Feed } from './feed';
3
+ import { FeedMetadata } from './interfaces';
4
+ export declare const SocketEventType: {
5
+ readonly NewMessage: "new-message";
6
+ };
7
+ type ClientReferenceId = string;
8
+ type NewMessageEventPayload = {
9
+ event: typeof SocketEventType.NewMessage;
10
+ /**
11
+ * @deprecated Top-level feed metadata. Exists for legacy reasons.
12
+ */
13
+ metadata: FeedMetadata;
14
+ /** Feed metadata, keyed by client reference id. */
15
+ data: Record<ClientReferenceId, {
16
+ metadata: FeedMetadata;
17
+ }>;
18
+ };
19
+ export type SocketEventPayload = NewMessageEventPayload;
20
+ export declare class FeedSocketManager {
21
+ readonly socket: Socket;
22
+ private channels;
23
+ private params;
24
+ private inbox;
25
+ constructor(socket: Socket);
26
+ join(feed: Feed): () => void;
27
+ leave(feed: Feed): void;
28
+ private setInbox;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=socket-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-manager.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/socket-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1B,OAAO,KAAK,EAAqB,YAAY,EAAE,MAAM,cAAc,CAAC;AAEpE,eAAO,MAAM,eAAe;;CAElB,CAAC;AAUX,KAAK,iBAAiB,GAAG,MAAM,CAAC;AAEhC,KAAK,sBAAsB,GAAG;IAC5B,KAAK,EAAE,OAAO,eAAe,CAAC,UAAU,CAAC;IACzC;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC,iBAAiB,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAaxD,qBAAa,iBAAiB;IAuChB,QAAQ,CAAC,MAAM,EAAE,MAAM;IApCnC,OAAO,CAAC,QAAQ,CAAgC;IAwBhD,OAAO,CAAC,MAAM,CAGZ;IAIF,OAAO,CAAC,KAAK,CAGX;gBAEmB,MAAM,EAAE,MAAM;IAMnC,IAAI,CAAC,IAAI,EAAE,IAAI;IAwDf,KAAK,CAAC,IAAI,EAAE,IAAI;IA4BhB,OAAO,CAAC,QAAQ;CAYjB"}
@@ -1,6 +1,7 @@
1
1
  import { GenericData, PageInfo } from '@knocklabs/types';
2
2
  import { NetworkStatus } from '../../networkStatus';
3
3
  import { FeedItem, FeedMetadata, FeedResponse } from './interfaces';
4
+ import { SocketEventPayload, SocketEventType } from './socket-manager';
4
5
  export type StoreFeedResultOptions = {
5
6
  shouldSetPage?: boolean;
6
7
  shouldAppend?: boolean;
@@ -17,9 +18,9 @@ export interface FeedStoreState {
17
18
  setItemAttrs: (itemIds: string[], attrs: object) => void;
18
19
  resetStore: (metadata?: FeedMetadata) => void;
19
20
  }
20
- export interface FeedMessagesReceivedPayload {
21
- metadata: FeedMetadata;
22
- }
21
+ export type FeedMessagesReceivedPayload = Extract<SocketEventPayload, {
22
+ event: typeof SocketEventType.NewMessage;
23
+ }>;
23
24
  export type FeedRealTimeEvent = "messages.new";
24
25
  export type FeedEvent = FeedRealTimeEvent | "items.received.page" | "items.received.realtime" | "items.archived" | "items.unarchived" | "items.seen" | "items.unseen" | "items.read" | "items.unread" | "items.all_archived" | "items.all_read" | "items.all_seen";
25
26
  export type BindableFeedEvent = FeedEvent | "items.received.*" | "items.*";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC3E,WAAW,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,gBAAgB,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;IACzD,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,YAAY,CAAC;CACxB;AAQD,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAE/C,MAAM,MAAM,SAAS,GACjB,iBAAiB,GACjB,qBAAqB,GACrB,yBAAyB,GACzB,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,cAAc,GACd,oBAAoB,GACpB,gBAAgB,GAChB,gBAAgB,CAAC;AAGrB,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAE3E,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,WAAW;IAC/C,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEvE,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC3E,WAAW,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,gBAAgB,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;IACzD,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,MAAM,2BAA2B,GAAG,OAAO,CAC/C,kBAAkB,EAClB;IAAE,KAAK,EAAE,OAAO,eAAe,CAAC,UAAU,CAAA;CAAE,CAC7C,CAAC;AAQF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAE/C,MAAM,MAAM,SAAS,GACjB,iBAAiB,GACjB,qBAAqB,GACrB,yBAAyB,GACzB,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,cAAc,GACd,oBAAoB,GACpB,gBAAgB,GAChB,gBAAgB,CAAC;AAGrB,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAE3E,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,WAAW;IAC/C,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { GenericData } from '@knocklabs/types';
2
2
  import { Store } from '@tanstack/store';
3
+ import { URLPattern } from 'urlpattern-polyfill';
3
4
  import { default as Knock } from '../../knock';
4
5
  export declare const guidesApiRootPath: (userId: string | undefined | null) => string;
5
6
  interface StepMessageState {
@@ -18,6 +19,10 @@ interface GuideStepData {
18
19
  message: StepMessageState;
19
20
  content: any;
20
21
  }
22
+ interface GuideActivationLocationRuleData {
23
+ directive: "allow" | "block";
24
+ pathname: string;
25
+ }
21
26
  interface GuideData {
22
27
  __typename: "Guide";
23
28
  channel_id: string;
@@ -27,6 +32,7 @@ interface GuideData {
27
32
  type: string;
28
33
  semver: string;
29
34
  steps: GuideStepData[];
35
+ activation_location_rules: GuideActivationLocationRuleData[];
30
36
  inserted_at: string;
31
37
  updated_at: string;
32
38
  }
@@ -37,8 +43,12 @@ export interface KnockGuideStep extends GuideStepData {
37
43
  }) => void;
38
44
  markAsArchived: () => void;
39
45
  }
46
+ interface KnockGuideActivationLocationRule extends GuideActivationLocationRuleData {
47
+ pattern: URLPattern;
48
+ }
40
49
  export interface KnockGuide extends GuideData {
41
50
  steps: KnockGuideStep[];
51
+ activation_location_rules: KnockGuideActivationLocationRule[];
42
52
  }
43
53
  type GetGuidesQueryParams = {
44
54
  data?: string;
@@ -60,6 +70,7 @@ type QueryStatus = {
60
70
  type StoreState = {
61
71
  guides: KnockGuide[];
62
72
  queries: Record<QueryKey, QueryStatus>;
73
+ location: string | undefined;
63
74
  };
64
75
  type QueryFilterParams = Pick<GetGuidesQueryParams, "type">;
65
76
  export type SelectFilterParams = {
@@ -70,16 +81,23 @@ export type TargetParams = {
70
81
  data?: GenericData | undefined;
71
82
  tenant?: string | undefined;
72
83
  };
84
+ type ConstructorOpts = {
85
+ trackLocationFromWindow?: boolean;
86
+ };
73
87
  export declare class KnockGuideClient {
74
88
  readonly knock: Knock;
75
89
  readonly channelId: string;
76
90
  readonly targetParams: TargetParams;
91
+ readonly options: ConstructorOpts;
77
92
  store: Store<StoreState, (state: StoreState) => StoreState>;
78
93
  private socket;
79
94
  private socketChannel;
80
95
  private socketChannelTopic;
81
96
  private socketEventTypes;
82
- constructor(knock: Knock, channelId: string, targetParams?: TargetParams);
97
+ private pushStateFn;
98
+ private replaceStateFn;
99
+ constructor(knock: Knock, channelId: string, targetParams?: TargetParams, options?: ConstructorOpts);
100
+ cleanup(): void;
83
101
  fetch(opts?: {
84
102
  filters?: QueryFilterParams;
85
103
  }): Promise<QueryStatus>;
@@ -98,6 +116,9 @@ export declare class KnockGuideClient {
98
116
  private addGuide;
99
117
  private replaceOrAddGuide;
100
118
  private removeGuide;
119
+ private handleLocationChange;
120
+ private listenForLocationChangesFromWindow;
121
+ private removeEventListeners;
101
122
  }
102
123
  export {};
103
124
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/clients/guide/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/clients/guide/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,MAAM,aAAa,CAAC;AAchC,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,WACrC,CAAC;AAE/B,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAE1B,OAAO,EAAE,GAAG,CAAC;CACd;AAED,UAAU,+BAA+B;IACvC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,SAAS;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,yBAAyB,EAAE,+BAA+B,EAAE,CAAC;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,gBAAgB,EAAE,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,UAAU,gCACR,SAAQ,+BAA+B;IACvC,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,yBAAyB,EAAE,gCAAgC,EAAE,CAAC;CAC/D;AAED,KAAK,oBAAoB,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAMF,MAAM,MAAM,8BAA8B,GAAG;IAE3C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AA6CF,KAAK,QAAQ,GAAG,MAAM,CAAC;AAEvB,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,CAAC;AAEF,KAAK,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;AAE5D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,qBAAa,gBAAgB;IAczB,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,YAAY,EAAE,YAAY;IACnC,QAAQ,CAAC,OAAO,EAAE,eAAe;IAhB5B,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC,CAAC;IAGnE,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAqD;IAG7E,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,cAAc,CAAsC;gBAGjD,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,YAAiB,EAC/B,OAAO,GAAE,eAAoB;IA0BxC,OAAO;IAKD,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAE;IA+ClD,SAAS;IA+BT,WAAW;IAcX,OAAO,CAAC,iBAAiB;IAwBzB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB;IAyDpD,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa;IAyBhD,gBAAgB,CACpB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,aAAa,EACnB,QAAQ,CAAC,EAAE,WAAW;IA0BlB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa;IAwB1D,OAAO,CAAC,SAAS;IA+CjB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,8BAA8B;IAatC,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,kCAAkC;IAwC1C,OAAO,CAAC,oBAAoB;CAa7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/client",
3
- "version": "0.14.4",
3
+ "version": "0.14.6",
4
4
  "description": "The clientside library for interacting with Knock",
5
5
  "homepage": "https://github.com/knocklabs/javascript/tree/main/packages/client",
6
6
  "author": "@knocklabs",
@@ -52,7 +52,7 @@
52
52
  "@babel/plugin-proposal-class-properties": "^7.16.7",
53
53
  "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
54
54
  "@babel/plugin-transform-runtime": "^7.25.4",
55
- "@babel/preset-env": "^7.26.0",
55
+ "@babel/preset-env": "^7.27.1",
56
56
  "@babel/preset-typescript": "^7.27.0",
57
57
  "@types/jsonwebtoken": "^9.0.9",
58
58
  "@typescript-eslint/eslint-plugin": "^8.19.1",
@@ -65,7 +65,7 @@
65
65
  "rimraf": "^6.0.1",
66
66
  "rollup": "^4.34.8",
67
67
  "typescript": "^5.8.3",
68
- "vite": "^5.4.18",
68
+ "vite": "^5.4.19",
69
69
  "vitest": "^3.1.1"
70
70
  },
71
71
  "dependencies": {
@@ -77,7 +77,9 @@
77
77
  "axios-retry": "^4.5.0",
78
78
  "eventemitter2": "^6.4.5",
79
79
  "jwt-decode": "^4.0.0",
80
+ "nanoid": "^5.1.5",
80
81
  "phoenix": "1.7.19",
82
+ "urlpattern-polyfill": "^10.0.0",
81
83
  "zustand": "^4.5.6"
82
84
  }
83
85
  }
@@ -1,6 +1,6 @@
1
1
  import { GenericData } from "@knocklabs/types";
2
2
  import EventEmitter from "eventemitter2";
3
- import { Channel } from "phoenix";
3
+ import { nanoid } from "nanoid";
4
4
  import type { StoreApi } from "zustand";
5
5
 
6
6
  import { isValidUuid } from "../../helpers";
@@ -19,6 +19,11 @@ import {
19
19
  FetchFeedOptions,
20
20
  FetchFeedOptionsForRequest,
21
21
  } from "./interfaces";
22
+ import {
23
+ FeedSocketManager,
24
+ SocketEventPayload,
25
+ SocketEventType,
26
+ } from "./socket-manager";
22
27
  import createStore from "./store";
23
28
  import {
24
29
  BindableFeedEvent,
@@ -39,11 +44,15 @@ const feedClientDefaults: Pick<FeedClientOptions, "archived"> = {
39
44
 
40
45
  const DEFAULT_DISCONNECT_DELAY = 2000;
41
46
 
47
+ const CLIENT_REF_ID_PREFIX = "client_";
48
+
42
49
  class Feed {
50
+ public readonly defaultOptions: FeedClientOptions;
51
+ public readonly referenceId: string;
52
+ public unsubscribeFromSocketEvents: (() => void) | undefined = undefined;
53
+ private socketManager: FeedSocketManager | undefined;
43
54
  private userFeedId: string;
44
- private channel?: Channel;
45
55
  private broadcaster: EventEmitter;
46
- private defaultOptions: FeedClientOptions;
47
56
  private broadcastChannel!: BroadcastChannel | null;
48
57
  private disconnectTimer: ReturnType<typeof setTimeout> | null = null;
49
58
  private hasSubscribedToRealTimeUpdates: boolean = false;
@@ -57,6 +66,7 @@ class Feed {
57
66
  readonly knock: Knock,
58
67
  readonly feedId: string,
59
68
  options: FeedClientOptions,
69
+ socketManager: FeedSocketManager | undefined,
60
70
  ) {
61
71
  if (!feedId || !isValidUuid(feedId)) {
62
72
  this.knock.log(
@@ -67,6 +77,8 @@ class Feed {
67
77
 
68
78
  this.feedId = feedId;
69
79
  this.userFeedId = this.buildUserFeedId();
80
+ this.referenceId = CLIENT_REF_ID_PREFIX + nanoid();
81
+ this.socketManager = socketManager;
70
82
  this.store = createStore();
71
83
  this.broadcaster = new EventEmitter({ wildcard: true, delimiter: "." });
72
84
  this.defaultOptions = {
@@ -84,7 +96,9 @@ class Feed {
84
96
  /**
85
97
  * Used to reinitialize a current feed instance, which is useful when reauthenticating users
86
98
  */
87
- reinitialize() {
99
+ reinitialize(socketManager?: FeedSocketManager) {
100
+ this.socketManager = socketManager;
101
+
88
102
  // Reinitialize the user feed id incase the userId changed
89
103
  this.userFeedId = this.buildUserFeedId();
90
104
 
@@ -102,12 +116,9 @@ class Feed {
102
116
  teardown() {
103
117
  this.knock.log("[Feed] Tearing down feed instance");
104
118
 
105
- if (this.channel) {
106
- this.channel.leave();
107
- this.channel.off("new-message");
108
- }
119
+ this.socketManager?.leave(this);
109
120
 
110
- this.teardownAutoSocketManager();
121
+ this.tearDownVisibilityListeners();
111
122
 
112
123
  if (this.disconnectTimer) {
113
124
  clearTimeout(this.disconnectTimer);
@@ -144,17 +155,7 @@ class Feed {
144
155
  return;
145
156
  }
146
157
 
147
- const maybeSocket = this.knock.client().socket;
148
-
149
- // Connect the socket only if we don't already have a connection
150
- if (maybeSocket && !maybeSocket.isConnected()) {
151
- maybeSocket.connect();
152
- }
153
-
154
- // Only join the channel if we're not already in a joining state
155
- if (this.channel && ["closed", "errored"].includes(this.channel.state)) {
156
- this.channel.join();
157
- }
158
+ this.unsubscribeFromSocketEvents = this.socketManager?.join(this);
158
159
  }
159
160
 
160
161
  /* Binds a handler to be invoked when event occurs */
@@ -587,6 +588,10 @@ class Feed {
587
588
  });
588
589
  }
589
590
 
591
+ get socketChannelTopic(): string {
592
+ return `feeds:${this.userFeedId}`;
593
+ }
594
+
590
595
  private broadcast(
591
596
  eventName: FeedEvent,
592
597
  data: FeedResponse | FeedEventPayload,
@@ -595,15 +600,19 @@ class Feed {
595
600
  }
596
601
 
597
602
  // Invoked when a new real-time message comes in from the socket
598
- private async onNewMessageReceived({
599
- metadata,
600
- }: FeedMessagesReceivedPayload) {
603
+ private async onNewMessageReceived({ data }: FeedMessagesReceivedPayload) {
601
604
  this.knock.log("[Feed] Received new real-time message");
605
+
602
606
  // Handle the new message coming in
603
607
  const { items, ...state } = this.store.getState();
604
608
  const currentHead: FeedItem | undefined = items[0];
609
+
605
610
  // Optimistically set the badge counts
606
- state.setMetadata(metadata);
611
+ const metadata = data[this.referenceId]?.metadata;
612
+ if (metadata) {
613
+ state.setMetadata(metadata);
614
+ }
615
+
607
616
  // Fetch the items before the current head (if it exists)
608
617
  this.fetch({ before: currentHead?.__cursor, __fetchSource: "socket" });
609
618
  }
@@ -767,28 +776,29 @@ class Feed {
767
776
  }
768
777
 
769
778
  private initializeRealtimeConnection() {
770
- const { socket: maybeSocket } = this.knock.client();
771
-
772
779
  // In server environments we might not have a socket connection
773
- if (!maybeSocket) return;
774
-
775
- // Reinitialize channel connections incase the socket changed
776
- this.channel = maybeSocket.channel(
777
- `feeds:${this.userFeedId}`,
778
- this.defaultOptions,
779
- );
780
-
781
- this.channel.on("new-message", (resp) => this.onNewMessageReceived(resp));
780
+ if (!this.socketManager) return;
782
781
 
783
782
  if (this.defaultOptions.auto_manage_socket_connection) {
784
- this.setupAutoSocketManager();
783
+ this.setUpVisibilityListeners();
785
784
  }
786
785
 
787
786
  // If we're initializing but they have previously opted to listen to real-time updates
788
787
  // then we will automatically reconnect on their behalf
789
788
  if (this.hasSubscribedToRealTimeUpdates && this.knock.isAuthenticated()) {
790
- if (!maybeSocket.isConnected()) maybeSocket.connect();
791
- this.channel.join();
789
+ this.unsubscribeFromSocketEvents = this.socketManager?.join(this);
790
+ }
791
+ }
792
+
793
+ async handleSocketEvent(payload: SocketEventPayload) {
794
+ switch (payload.event) {
795
+ case SocketEventType.NewMessage:
796
+ this.onNewMessageReceived(payload);
797
+ return;
798
+ default: {
799
+ const _exhaustiveCheck: never = payload.event;
800
+ return;
801
+ }
792
802
  }
793
803
  }
794
804
 
@@ -796,7 +806,7 @@ class Feed {
796
806
  * Listen for changes to document visibility and automatically disconnect
797
807
  * or reconnect the socket after a delay
798
808
  */
799
- private setupAutoSocketManager() {
809
+ private setUpVisibilityListeners() {
800
810
  if (
801
811
  typeof document === "undefined" ||
802
812
  this.visibilityChangeListenerConnected
@@ -809,7 +819,7 @@ class Feed {
809
819
  document.addEventListener("visibilitychange", this.visibilityChangeHandler);
810
820
  }
811
821
 
812
- private teardownAutoSocketManager() {
822
+ private tearDownVisibilityListeners() {
813
823
  if (typeof document === "undefined") return;
814
824
 
815
825
  document.removeEventListener(
@@ -860,7 +870,7 @@ class Feed {
860
870
 
861
871
  // If the socket is not connected, try to reconnect
862
872
  if (!client.socket?.isConnected()) {
863
- this.initializeRealtimeConnection();
873
+ client.socket?.connect();
864
874
  }
865
875
  }
866
876
  }
@@ -2,19 +2,27 @@ import Knock from "../../knock";
2
2
 
3
3
  import Feed from "./feed";
4
4
  import { FeedClientOptions } from "./interfaces";
5
+ import { FeedSocketManager } from "./socket-manager";
5
6
 
6
7
  class FeedClient {
7
8
  private instance: Knock;
8
9
  private feedInstances: Feed[] = [];
10
+ private socketManager: FeedSocketManager | undefined;
9
11
 
10
12
  constructor(instance: Knock) {
11
13
  this.instance = instance;
12
14
  }
13
15
 
14
16
  initialize(feedChannelId: string, options: FeedClientOptions = {}) {
15
- const feedInstance = new Feed(this.instance, feedChannelId, options);
17
+ this.initSocketManager();
18
+
19
+ const feedInstance = new Feed(
20
+ this.instance,
21
+ feedChannelId,
22
+ options,
23
+ this.socketManager,
24
+ );
16
25
  this.feedInstances.push(feedInstance);
17
-
18
26
  return feedInstance;
19
27
  }
20
28
 
@@ -30,7 +38,23 @@ class FeedClient {
30
38
 
31
39
  reinitializeInstances() {
32
40
  for (const feed of this.feedInstances) {
33
- feed.reinitialize();
41
+ this.socketManager?.leave(feed);
42
+ }
43
+
44
+ // The API client has a new socket once it's reinitialized,
45
+ // so we need to set up a new socket manager
46
+ this.socketManager = undefined;
47
+ this.initSocketManager();
48
+
49
+ for (const feed of this.feedInstances) {
50
+ feed.reinitialize(this.socketManager);
51
+ }
52
+ }
53
+
54
+ private initSocketManager() {
55
+ const socket = this.instance.client().socket;
56
+ if (socket && !this.socketManager) {
57
+ this.socketManager = new FeedSocketManager(socket);
34
58
  }
35
59
  }
36
60
  }