@knocklabs/client 0.9.4 → 0.10.1

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 (43) hide show
  1. package/CHANGELOG.md +13 -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/messages/index.js +2 -0
  5. package/dist/cjs/clients/messages/index.js.map +1 -0
  6. package/dist/cjs/clients/slack/index.js.map +1 -1
  7. package/dist/cjs/knock.js +2 -2
  8. package/dist/cjs/knock.js.map +1 -1
  9. package/dist/esm/clients/feed/feed.mjs +38 -37
  10. package/dist/esm/clients/feed/feed.mjs.map +1 -1
  11. package/dist/esm/clients/messages/index.mjs +63 -0
  12. package/dist/esm/clients/messages/index.mjs.map +1 -0
  13. package/dist/esm/clients/slack/index.mjs.map +1 -1
  14. package/dist/esm/knock.mjs +23 -21
  15. package/dist/esm/knock.mjs.map +1 -1
  16. package/dist/types/clients/feed/feed.d.ts +13 -11
  17. package/dist/types/clients/feed/feed.d.ts.map +1 -1
  18. package/dist/types/clients/feed/interfaces.d.ts +1 -4
  19. package/dist/types/clients/feed/interfaces.d.ts.map +1 -1
  20. package/dist/types/clients/messages/index.d.ts +15 -0
  21. package/dist/types/clients/messages/index.d.ts.map +1 -0
  22. package/dist/types/clients/messages/interfaces.d.ts +39 -0
  23. package/dist/types/clients/messages/interfaces.d.ts.map +1 -0
  24. package/dist/types/clients/slack/index.d.ts +2 -2
  25. package/dist/types/clients/slack/index.d.ts.map +1 -1
  26. package/dist/types/clients/slack/interfaces.d.ts +4 -0
  27. package/dist/types/clients/slack/interfaces.d.ts.map +1 -1
  28. package/dist/types/index.d.ts +3 -0
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/types/interfaces.d.ts +16 -0
  31. package/dist/types/interfaces.d.ts.map +1 -1
  32. package/dist/types/knock.d.ts +2 -0
  33. package/dist/types/knock.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/clients/feed/feed.ts +58 -50
  36. package/src/clients/feed/interfaces.ts +1 -5
  37. package/src/clients/messages/index.ts +90 -0
  38. package/src/clients/messages/interfaces.ts +53 -0
  39. package/src/clients/slack/index.ts +4 -1
  40. package/src/clients/slack/interfaces.ts +5 -0
  41. package/src/index.ts +3 -0
  42. package/src/interfaces.ts +15 -0
  43. package/src/knock.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../src/clients/slack/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../src/clients/slack/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC"}
@@ -9,6 +9,9 @@ export * from "./clients/preferences/interfaces";
9
9
  export * from "./clients/slack";
10
10
  export * from "./clients/slack/interfaces";
11
11
  export * from "./clients/users";
12
+ export * from "./clients/users/interfaces";
13
+ export * from "./clients/messages";
14
+ export * from "./clients/messages/interfaces";
12
15
  export * from "./networkStatus";
13
16
  export default Knock;
14
17
  export { Feed, FeedClient };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,eAAe,KAAK,CAAC;AACrB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iBAAiB,CAAC;AAEhC,eAAe,KAAK,CAAC;AACrB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC"}
@@ -21,6 +21,10 @@ export interface User extends GenericData {
21
21
  created_at: string | null;
22
22
  }
23
23
  export type Recipient = User | KnockObject;
24
+ export type RecipientRef = string | {
25
+ collection: string;
26
+ id: string;
27
+ };
24
28
  export interface Activity<T = GenericData> {
25
29
  id: string;
26
30
  inserted_at: string;
@@ -38,4 +42,16 @@ export interface AuthenticateOptions {
38
42
  onUserTokenExpiring?: UserTokenExpiringCallback;
39
43
  timeBeforeExpirationInMs?: number;
40
44
  }
45
+ export interface BulkOperation {
46
+ id: string;
47
+ name: string;
48
+ status: "queued" | "processing" | "completed" | "failed";
49
+ processed_rows: number;
50
+ estimated_total_rows: number;
51
+ started_at?: string;
52
+ completed_at?: string;
53
+ failed_at?: string;
54
+ inserted_at: string;
55
+ updated_at: string;
56
+ }
41
57
  //# sourceMappingURL=interfaces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC;AAE/B,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,WAAW;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,WAAW,CAAC;AAE3C,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,GAAG,KACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IAClC,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;IAChD,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC;AAE/B,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,WAAW;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,WAAW,CAAC;AAE3C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,GAAG,KACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IAClC,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;IAChD,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -1,5 +1,6 @@
1
1
  import ApiClient from "./api";
2
2
  import FeedClient from "./clients/feed";
3
+ import MessageClient from "./clients/messages";
3
4
  import ObjectClient from "./clients/objects";
4
5
  import Preferences from "./clients/preferences";
5
6
  import SlackClient from "./clients/slack";
@@ -18,6 +19,7 @@ declare class Knock {
18
19
  readonly preferences: Preferences;
19
20
  readonly slack: SlackClient;
20
21
  readonly user: UserClient;
22
+ readonly messages: MessageClient;
21
23
  constructor(apiKey: string, options?: KnockOptions);
22
24
  client(): ApiClient;
23
25
  authenticate(userId: string, userToken?: string, options?: AuthenticateOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"knock.d.ts","sourceRoot":"","sources":["../../src/knock.ts"],"names":[],"mappings":"AAEA,OAAO,SAAS,MAAM,OAAO,CAAC;AAC9B,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EAET,MAAM,cAAc,CAAC;AAItB,cAAM,KAAK;IAcP,QAAQ,CAAC,MAAM,EAAE,MAAM;IAblB,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,SAAS,CAA0B;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,QAAQ,CAAC,KAAK,aAAwB;IACtC,QAAQ,CAAC,OAAO,eAA0B;IAC1C,QAAQ,CAAC,WAAW,cAAyB;IAC7C,QAAQ,CAAC,KAAK,cAAyB;IACvC,QAAQ,CAAC,IAAI,aAAwB;gBAG1B,MAAM,EAAE,MAAM,EACvB,OAAO,GAAE,YAAiB;IAe5B,MAAM;IAuBN,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,mBAAmB;IA6C/B,eAAe,CAAC,cAAc,UAAQ;IAKtC,QAAQ;IASR,GAAG,CAAC,OAAO,EAAE,MAAM;IAMnB;;OAEG;IACH,OAAO,CAAC,eAAe;YAQT,gCAAgC;CA8B/C;AAED,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"knock.d.ts","sourceRoot":"","sources":["../../src/knock.ts"],"names":[],"mappings":"AAEA,OAAO,SAAS,MAAM,OAAO,CAAC;AAC9B,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EAET,MAAM,cAAc,CAAC;AAItB,cAAM,KAAK;IAeP,QAAQ,CAAC,MAAM,EAAE,MAAM;IAdlB,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,SAAS,CAA0B;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,QAAQ,CAAC,KAAK,aAAwB;IACtC,QAAQ,CAAC,OAAO,eAA0B;IAC1C,QAAQ,CAAC,WAAW,cAAyB;IAC7C,QAAQ,CAAC,KAAK,cAAyB;IACvC,QAAQ,CAAC,IAAI,aAAwB;IACrC,QAAQ,CAAC,QAAQ,gBAA2B;gBAGjC,MAAM,EAAE,MAAM,EACvB,OAAO,GAAE,YAAiB;IAe5B,MAAM;IAuBN,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,mBAAmB;IA6C/B,eAAe,CAAC,cAAc,UAAQ;IAKtC,QAAQ;IASR,GAAG,CAAC,OAAO,EAAE,MAAM;IAMnB;;OAEG;IACH,OAAO,CAAC,eAAe;YAQT,gCAAgC;CA8B/C;AAED,eAAe,KAAK,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/client",
3
- "version": "0.9.4",
3
+ "version": "0.10.1",
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",
@@ -4,6 +4,10 @@ import { StoreApi } from "zustand";
4
4
 
5
5
  import Knock from "../../knock";
6
6
  import { NetworkStatus, isRequestInFlight } from "../../networkStatus";
7
+ import {
8
+ BulkUpdateMessagesInChannelProperties,
9
+ MessageEngagementStatus,
10
+ } from "../messages/interfaces";
7
11
 
8
12
  import {
9
13
  FeedClientOptions,
@@ -24,15 +28,6 @@ import {
24
28
  FeedStoreState,
25
29
  } from "./types";
26
30
 
27
- export type Status =
28
- | "seen"
29
- | "read"
30
- | "interacted"
31
- | "archived"
32
- | "unseen"
33
- | "unread"
34
- | "unarchived";
35
-
36
31
  // Default options to apply
37
32
  const feedClientDefaults: Pick<FeedClientOptions, "archived"> = {
38
33
  archived: "exclude",
@@ -48,6 +43,7 @@ class Feed {
48
43
  private broadcastChannel!: BroadcastChannel | null;
49
44
  private disconnectTimer: ReturnType<typeof setTimeout> | null = null;
50
45
  private hasSubscribedToRealTimeUpdates: Boolean = false;
46
+ private visibilityChangeHandler: () => void;
51
47
 
52
48
  // The raw store instance, used for binding in React and other environments
53
49
  public store: StoreApi<FeedStoreState>;
@@ -97,6 +93,8 @@ class Feed {
97
93
  this.channel.off("new-message");
98
94
  }
99
95
 
96
+ this.teardownAutoSocketManager();
97
+
100
98
  if (this.disconnectTimer) {
101
99
  clearTimeout(this.disconnectTimer);
102
100
  this.disconnectTimer = null;
@@ -556,7 +554,7 @@ class Feed {
556
554
 
557
555
  private optimisticallyPerformStatusUpdate(
558
556
  itemOrItems: FeedItemOrItems,
559
- type: Status,
557
+ type: MessageEngagementStatus | "unread" | "unseen" | "unarchived",
560
558
  attrs: object,
561
559
  badgeCountAttr?: "unread_count" | "unseen_count",
562
560
  ) {
@@ -605,22 +603,21 @@ class Feed {
605
603
  setState((store) => store.setItemAttrs(itemIds, attrs));
606
604
  }
607
605
 
608
- private async makeStatusUpdate(itemOrItems: FeedItemOrItems, type: Status) {
606
+ private async makeStatusUpdate(
607
+ itemOrItems: FeedItemOrItems,
608
+ type: MessageEngagementStatus | "unread" | "unseen" | "unarchived",
609
+ ) {
609
610
  // Always treat items as a batch to use the corresponding batch endpoint
610
611
  const items = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
611
612
  const itemIds = items.map((item) => item.id);
612
613
 
613
- const result = await this.knock.client().makeRequest({
614
- method: "POST",
615
- url: `/v1/messages/batch/${type}`,
616
- data: { message_ids: itemIds },
617
- });
614
+ const result = await this.knock.messages.batchUpdateStatuses(itemIds, type);
618
615
 
619
616
  // Emit the event that these items had their statuses changed
620
617
  // Note: we do this after the update to ensure that the server event actually completed
621
618
  this.broadcaster.emit(`items.${type}`, { items });
622
619
 
623
- // Note: `items.type` format is being deprecated in favor over the `items:type` format,
620
+ // Note: `items.type` format is being deprecated in favor over the `items:type` format,
624
621
  // but emit both formats to make it backward compatible for now.
625
622
  this.broadcaster.emit(`items:${type}`, { items });
626
623
  this.broadcastOverChannel(`items:${type}`, { items });
@@ -628,13 +625,15 @@ class Feed {
628
625
  return result;
629
626
  }
630
627
 
631
- private async makeBulkStatusUpdate(type: "seen" | "read" | "archive") {
628
+ private async makeBulkStatusUpdate(
629
+ status: BulkUpdateMessagesInChannelProperties["status"],
630
+ ) {
632
631
  // The base scope for the call should take into account all of the options currently
633
632
  // set on the feed, as well as being scoped for the current user. We do this so that
634
633
  // we ONLY make changes to the messages that are currently in view on this feed, and not
635
634
  // all messages that exist.
636
635
  const options = {
637
- user_ids: [this.knock.userId],
636
+ user_ids: [this.knock.userId!],
638
637
  engagement_status:
639
638
  this.defaultOptions.status !== "all"
640
639
  ? this.defaultOptions.status
@@ -646,10 +645,10 @@ class Feed {
646
645
  : undefined,
647
646
  };
648
647
 
649
- return await this.knock.client().makeRequest({
650
- method: "POST",
651
- url: `/v1/channels/${this.feedId}/messages/bulk/${type}`,
652
- data: options,
648
+ return await this.knock.messages.bulkUpdateAllStatusesInChannel({
649
+ channelId: this.feedId,
650
+ status,
651
+ options,
653
652
  });
654
653
  }
655
654
 
@@ -724,9 +723,7 @@ class Feed {
724
723
  this.channel.on("new-message", (resp) => this.onNewMessageReceived(resp));
725
724
 
726
725
  if (this.defaultOptions.auto_manage_socket_connection) {
727
- this.setupAutoSocketManager(
728
- this.defaultOptions.auto_manage_socket_connection_delay,
729
- );
726
+ this.setupAutoSocketManager();
730
727
  }
731
728
 
732
729
  // If we're initializing but they have previously opted to listen to real-time updates
@@ -741,33 +738,44 @@ class Feed {
741
738
  * Listen for changes to document visibility and automatically disconnect
742
739
  * or reconnect the socket after a delay
743
740
  */
744
- private setupAutoSocketManager(autoManageSocketConnectionDelay?: number) {
741
+ private setupAutoSocketManager() {
742
+ this.visibilityChangeHandler = this.handleVisibilityChange.bind(this);
743
+ document.addEventListener("visibilitychange", this.visibilityChangeHandler);
744
+ }
745
+
746
+ private teardownAutoSocketManager() {
747
+ document.removeEventListener(
748
+ "visibilitychange",
749
+ this.visibilityChangeHandler,
750
+ );
751
+ }
752
+
753
+ private handleVisibilityChange() {
745
754
  const disconnectDelay =
746
- autoManageSocketConnectionDelay ?? DEFAULT_DISCONNECT_DELAY;
747
-
748
- document.addEventListener("visibilitychange", () => {
749
- const client = this.knock.client();
750
-
751
- if (document.visibilityState === "hidden") {
752
- // When the tab is hidden, clean up the socket connection after a delay
753
- this.disconnectTimer = setTimeout(() => {
754
- client.socket?.disconnect();
755
- this.disconnectTimer = null;
756
- }, disconnectDelay);
757
- } else if (document.visibilityState === "visible") {
758
- // When the tab is visible, clear the disconnect timer if active to cancel disconnecting
759
- // This handles cases where the tab is only briefly hidden to avoid unnecessary disconnects
760
- if (this.disconnectTimer) {
761
- clearTimeout(this.disconnectTimer);
762
- this.disconnectTimer = null;
763
- }
755
+ this.defaultOptions.auto_manage_socket_connection_delay ??
756
+ DEFAULT_DISCONNECT_DELAY;
757
+
758
+ const client = this.knock.client();
759
+
760
+ if (document.visibilityState === "hidden") {
761
+ // When the tab is hidden, clean up the socket connection after a delay
762
+ this.disconnectTimer = setTimeout(() => {
763
+ client.socket?.disconnect();
764
+ this.disconnectTimer = null;
765
+ }, disconnectDelay);
766
+ } else if (document.visibilityState === "visible") {
767
+ // When the tab is visible, clear the disconnect timer if active to cancel disconnecting
768
+ // This handles cases where the tab is only briefly hidden to avoid unnecessary disconnects
769
+ if (this.disconnectTimer) {
770
+ clearTimeout(this.disconnectTimer);
771
+ this.disconnectTimer = null;
772
+ }
764
773
 
765
- // If the socket is not connected, try to reconnect
766
- if (!client.socket?.isConnected()) {
767
- this.initializeRealtimeConnection();
768
- }
774
+ // If the socket is not connected, try to reconnect
775
+ if (!client.socket?.isConnected()) {
776
+ this.initializeRealtimeConnection();
769
777
  }
770
- });
778
+ }
771
779
  }
772
780
  }
773
781
 
@@ -2,6 +2,7 @@ import { GenericData, PageInfo } from "@knocklabs/types";
2
2
 
3
3
  import { Activity, Recipient } from "../../interfaces";
4
4
  import { NetworkStatus } from "../../networkStatus";
5
+ import { NotificationSource } from "../messages/interfaces";
5
6
 
6
7
  // Specific feed interfaces
7
8
 
@@ -64,11 +65,6 @@ export interface MarkdownContentBlock extends ContentBlockBase {
64
65
  content: string;
65
66
  }
66
67
 
67
- export interface NotificationSource {
68
- key: string;
69
- version_id: string;
70
- }
71
-
72
68
  export type ContentBlock =
73
69
  | MarkdownContentBlock
74
70
  | TextContentBlock
@@ -0,0 +1,90 @@
1
+ import { ApiResponse } from "../../api";
2
+ import { BulkOperation } from "../../interfaces";
3
+ import Knock from "../../knock";
4
+
5
+ import {
6
+ BulkUpdateMessagesInChannelProperties,
7
+ Message,
8
+ MessageEngagementStatus,
9
+ } from "./interfaces";
10
+
11
+ class MessageClient {
12
+ private knock: Knock;
13
+
14
+ constructor(knock: Knock) {
15
+ this.knock = knock;
16
+ }
17
+
18
+ async get(messageId: string): Promise<Message> {
19
+ const result = await this.knock.client().makeRequest({
20
+ method: "GET",
21
+ url: `/v1/messages/${messageId}`,
22
+ });
23
+
24
+ return this.handleResponse<Message>(result);
25
+ }
26
+
27
+ async updateStatus(
28
+ messageId: string,
29
+ status: MessageEngagementStatus,
30
+ ): Promise<Message> {
31
+ const result = await this.knock.client().makeRequest({
32
+ method: "PUT",
33
+ url: `/v1/messages/${messageId}/${status}`,
34
+ });
35
+
36
+ return this.handleResponse<Message>(result);
37
+ }
38
+
39
+ async removeStatus(
40
+ messageId: string,
41
+ status: Exclude<MessageEngagementStatus, "interacted">,
42
+ ): Promise<Message> {
43
+ const result = await this.knock.client().makeRequest({
44
+ method: "DELETE",
45
+ url: `/v1/messages/${messageId}/${status}`,
46
+ });
47
+
48
+ return this.handleResponse<Message>(result);
49
+ }
50
+
51
+ async batchUpdateStatuses(
52
+ messageIds: string[],
53
+ status: MessageEngagementStatus | "unseen" | "unread" | "unarchived",
54
+ ): Promise<Message[]> {
55
+ const result = await this.knock.client().makeRequest({
56
+ method: "POST",
57
+ url: `/v1/messages/batch/${status}`,
58
+ data: { message_ids: messageIds },
59
+ });
60
+
61
+ return this.handleResponse<Message[]>(result);
62
+ }
63
+
64
+ async bulkUpdateAllStatusesInChannel({
65
+ channelId,
66
+ status,
67
+ options,
68
+ }: BulkUpdateMessagesInChannelProperties): Promise<BulkOperation> {
69
+ const result = await this.knock.client().makeRequest({
70
+ method: "POST",
71
+ url: `/v1/channels/${channelId}/messages/bulk/${status}`,
72
+ data: options,
73
+ });
74
+
75
+ return this.handleResponse<BulkOperation>(result);
76
+ }
77
+
78
+ private handleResponse<T = any>(response: ApiResponse) {
79
+ if (response.statusCode === "error") {
80
+ if (response.error?.response?.status < 500) {
81
+ return response.error || response.body;
82
+ }
83
+ throw new Error(response.error || response.body);
84
+ }
85
+
86
+ return response.body as T;
87
+ }
88
+ }
89
+
90
+ export default MessageClient;
@@ -0,0 +1,53 @@
1
+ import { RecipientRef } from "../..";
2
+
3
+ export type MessageDeliveryStatus =
4
+ | "queued"
5
+ | "sent"
6
+ | "delivered"
7
+ | "delivery_attempted"
8
+ | "undelivered"
9
+ | "not_sent";
10
+
11
+ export interface NotificationSource {
12
+ key: string;
13
+ version_id: string;
14
+ categories: string[];
15
+ }
16
+
17
+ export type MessageEngagementStatus =
18
+ | "seen"
19
+ | "read"
20
+ | "interacted"
21
+ | "archived";
22
+
23
+ export interface Message<T = any> {
24
+ id: string;
25
+ channel_id: string;
26
+ recipient: RecipientRef;
27
+ actors: RecipientRef[];
28
+ inserted_at: string;
29
+ updated_at: string;
30
+ read_at: string | null;
31
+ seen_at: string | null;
32
+ archived_at: string | null;
33
+ tenant: string | null;
34
+ status: MessageDeliveryStatus;
35
+ engagement_statuses: MessageEngagementStatus[];
36
+ source: NotificationSource;
37
+ data: T | null;
38
+ metadata: {
39
+ external_id?: string;
40
+ };
41
+ }
42
+
43
+ export type BulkUpdateMessagesInChannelProperties = {
44
+ channelId: string;
45
+ status: "seen" | "read" | "archive";
46
+ options: {
47
+ user_ids?: string[];
48
+ engagement_status?: "seen" | "read" | "unseen" | "unread";
49
+ archived?: "exclude" | "include" | "only";
50
+ has_tenant?: boolean;
51
+ tenants?: string[];
52
+ };
53
+ };
@@ -4,6 +4,7 @@ import Knock from "../../knock";
4
4
  import {
5
5
  AuthCheckInput,
6
6
  GetSlackChannelsInput,
7
+ GetSlackChannelsResponse,
7
8
  RevokeAccessTokenInput,
8
9
  } from "./interfaces";
9
10
 
@@ -32,7 +33,9 @@ class SlackClient {
32
33
  return this.handleResponse(result);
33
34
  }
34
35
 
35
- async getChannels(input: GetSlackChannelsInput) {
36
+ async getChannels(
37
+ input: GetSlackChannelsInput,
38
+ ): Promise<GetSlackChannelsResponse> {
36
39
  const { knockChannelId, tenant } = input;
37
40
  const queryOptions = input.queryOptions || {};
38
41
 
@@ -27,6 +27,11 @@ export type RevokeAccessTokenInput = {
27
27
  knockChannelId: string;
28
28
  };
29
29
 
30
+ export type GetSlackChannelsResponse = {
31
+ slack_channels: SlackChannel[];
32
+ next_cursor: string | null;
33
+ };
34
+
30
35
  export type SlackChannel = {
31
36
  name: string;
32
37
  id: string;
package/src/index.ts CHANGED
@@ -10,6 +10,9 @@ export * from "./clients/preferences/interfaces";
10
10
  export * from "./clients/slack";
11
11
  export * from "./clients/slack/interfaces";
12
12
  export * from "./clients/users";
13
+ export * from "./clients/users/interfaces";
14
+ export * from "./clients/messages";
15
+ export * from "./clients/messages/interfaces";
13
16
  export * from "./networkStatus";
14
17
 
15
18
  export default Knock;
package/src/interfaces.ts CHANGED
@@ -27,6 +27,8 @@ export interface User extends GenericData {
27
27
 
28
28
  export type Recipient = User | KnockObject;
29
29
 
30
+ export type RecipientRef = string | { collection: string; id: string };
31
+
30
32
  export interface Activity<T = GenericData> {
31
33
  id: string;
32
34
  inserted_at: string;
@@ -50,3 +52,16 @@ export interface AuthenticateOptions {
50
52
  onUserTokenExpiring?: UserTokenExpiringCallback;
51
53
  timeBeforeExpirationInMs?: number;
52
54
  }
55
+
56
+ export interface BulkOperation {
57
+ id: string;
58
+ name: string;
59
+ status: "queued" | "processing" | "completed" | "failed";
60
+ processed_rows: number;
61
+ estimated_total_rows: number;
62
+ started_at?: string;
63
+ completed_at?: string;
64
+ failed_at?: string;
65
+ inserted_at: string;
66
+ updated_at: string;
67
+ }
package/src/knock.ts CHANGED
@@ -2,6 +2,7 @@ import { jwtDecode } from "jwt-decode";
2
2
 
3
3
  import ApiClient from "./api";
4
4
  import FeedClient from "./clients/feed";
5
+ import MessageClient from "./clients/messages";
5
6
  import ObjectClient from "./clients/objects";
6
7
  import Preferences from "./clients/preferences";
7
8
  import SlackClient from "./clients/slack";
@@ -27,6 +28,7 @@ class Knock {
27
28
  readonly preferences = new Preferences(this);
28
29
  readonly slack = new SlackClient(this);
29
30
  readonly user = new UserClient(this);
31
+ readonly messages = new MessageClient(this);
30
32
 
31
33
  constructor(
32
34
  readonly apiKey: string,