@knocklabs/client 0.8.18 → 0.8.19

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 (121) hide show
  1. package/dist/api.d.ts +25 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +84 -0
  4. package/dist/cjs/api.js +2 -133
  5. package/dist/cjs/api.js.map +1 -1
  6. package/dist/cjs/clients/feed/feed.js +2 -939
  7. package/dist/cjs/clients/feed/feed.js.map +1 -1
  8. package/dist/cjs/clients/feed/index.js +2 -34
  9. package/dist/cjs/clients/feed/index.js.map +1 -1
  10. package/dist/cjs/clients/feed/store.js +2 -111
  11. package/dist/cjs/clients/feed/store.js.map +1 -1
  12. package/dist/cjs/clients/feed/utils.js +2 -26
  13. package/dist/cjs/clients/feed/utils.js.map +1 -1
  14. package/dist/cjs/clients/preferences/index.js +2 -373
  15. package/dist/cjs/clients/preferences/index.js.map +1 -1
  16. package/dist/cjs/clients/users/index.js +2 -185
  17. package/dist/cjs/clients/users/index.js.map +1 -1
  18. package/dist/cjs/index.js +2 -102
  19. package/dist/cjs/index.js.map +1 -1
  20. package/dist/cjs/knock.js +6 -89
  21. package/dist/cjs/knock.js.map +1 -1
  22. package/dist/cjs/networkStatus.js +2 -18
  23. package/dist/cjs/networkStatus.js.map +1 -1
  24. package/dist/clients/feed/feed.d.ts +64 -0
  25. package/dist/clients/feed/feed.d.ts.map +1 -0
  26. package/dist/clients/feed/feed.js +572 -0
  27. package/dist/clients/feed/index.d.ts +15 -0
  28. package/dist/clients/feed/index.d.ts.map +1 -0
  29. package/dist/clients/feed/index.js +34 -0
  30. package/dist/clients/feed/interfaces.d.ts +60 -0
  31. package/dist/clients/feed/interfaces.d.ts.map +1 -0
  32. package/dist/clients/feed/interfaces.js +2 -0
  33. package/dist/clients/feed/store.d.ts +3 -0
  34. package/dist/clients/feed/store.d.ts.map +1 -0
  35. package/dist/clients/feed/store.js +72 -0
  36. package/dist/clients/feed/types.d.ts +34 -0
  37. package/dist/clients/feed/types.d.ts.map +1 -0
  38. package/dist/clients/feed/types.js +2 -0
  39. package/dist/clients/feed/utils.d.ts +4 -0
  40. package/dist/clients/feed/utils.d.ts.map +1 -0
  41. package/dist/clients/feed/utils.js +21 -0
  42. package/dist/clients/preferences/index.d.ts +46 -0
  43. package/dist/clients/preferences/index.d.ts.map +1 -0
  44. package/dist/clients/preferences/index.js +129 -0
  45. package/dist/clients/preferences/interfaces.d.ts +26 -0
  46. package/dist/clients/preferences/interfaces.d.ts.map +1 -0
  47. package/dist/clients/preferences/interfaces.js +2 -0
  48. package/dist/clients/users/index.d.ts +16 -0
  49. package/dist/clients/users/index.d.ts.map +1 -0
  50. package/dist/clients/users/index.js +56 -0
  51. package/dist/clients/users/interfaces.d.ts +8 -0
  52. package/dist/clients/users/interfaces.d.ts.map +1 -0
  53. package/dist/clients/users/interfaces.js +2 -0
  54. package/dist/esm/api.js +44 -84
  55. package/dist/esm/api.js.map +1 -1
  56. package/dist/esm/clients/feed/feed.js +296 -603
  57. package/dist/esm/clients/feed/feed.js.map +1 -1
  58. package/dist/esm/clients/feed/index.js +28 -12
  59. package/dist/esm/clients/feed/index.js.map +1 -1
  60. package/dist/esm/clients/feed/store.js +37 -71
  61. package/dist/esm/clients/feed/store.js.map +1 -1
  62. package/dist/esm/clients/feed/utils.js +10 -15
  63. package/dist/esm/clients/feed/utils.js.map +1 -1
  64. package/dist/esm/clients/preferences/index.js +79 -146
  65. package/dist/esm/clients/preferences/index.js.map +1 -1
  66. package/dist/esm/clients/users/index.js +52 -76
  67. package/dist/esm/clients/users/index.js.map +1 -1
  68. package/dist/esm/index.js +12 -11
  69. package/dist/esm/index.js.map +1 -1
  70. package/dist/esm/knock.js +72 -51
  71. package/dist/esm/knock.js.map +1 -1
  72. package/dist/esm/networkStatus.js +14 -10
  73. package/dist/esm/networkStatus.js.map +1 -1
  74. package/dist/index.d.ts +11 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +43 -0
  77. package/dist/interfaces.d.ts +41 -0
  78. package/dist/interfaces.d.ts.map +1 -0
  79. package/dist/interfaces.js +2 -0
  80. package/dist/knock.d.ts +30 -0
  81. package/dist/knock.d.ts.map +1 -0
  82. package/dist/knock.js +135 -0
  83. package/dist/networkStatus.d.ts +8 -0
  84. package/dist/networkStatus.d.ts.map +1 -0
  85. package/dist/networkStatus.js +18 -0
  86. package/dist/types/api.d.ts +0 -2
  87. package/dist/types/api.d.ts.map +1 -1
  88. package/dist/types/clients/feed/feed.d.ts +12 -4
  89. package/dist/types/clients/feed/feed.d.ts.map +1 -1
  90. package/dist/types/clients/feed/index.d.ts +4 -0
  91. package/dist/types/clients/feed/index.d.ts.map +1 -1
  92. package/dist/types/clients/feed/store.d.ts.map +1 -1
  93. package/dist/types/clients/feed/types.d.ts +0 -1
  94. package/dist/types/clients/feed/types.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +1 -1
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/interfaces.d.ts +7 -0
  98. package/dist/types/interfaces.d.ts.map +1 -1
  99. package/dist/types/knock.d.ts +12 -4
  100. package/dist/types/knock.d.ts.map +1 -1
  101. package/package.json +12 -8
  102. package/dist/cjs/clients/feed/interfaces.js +0 -6
  103. package/dist/cjs/clients/feed/interfaces.js.map +0 -1
  104. package/dist/cjs/clients/feed/types.js +0 -6
  105. package/dist/cjs/clients/feed/types.js.map +0 -1
  106. package/dist/cjs/clients/preferences/interfaces.js +0 -6
  107. package/dist/cjs/clients/preferences/interfaces.js.map +0 -1
  108. package/dist/cjs/clients/users/interfaces.js +0 -6
  109. package/dist/cjs/clients/users/interfaces.js.map +0 -1
  110. package/dist/cjs/interfaces.js +0 -6
  111. package/dist/cjs/interfaces.js.map +0 -1
  112. package/dist/esm/clients/feed/interfaces.js +0 -2
  113. package/dist/esm/clients/feed/interfaces.js.map +0 -1
  114. package/dist/esm/clients/feed/types.js +0 -2
  115. package/dist/esm/clients/feed/types.js.map +0 -1
  116. package/dist/esm/clients/preferences/interfaces.js +0 -2
  117. package/dist/esm/clients/preferences/interfaces.js.map +0 -1
  118. package/dist/esm/clients/users/interfaces.js +0 -2
  119. package/dist/esm/clients/users/interfaces.js.map +0 -1
  120. package/dist/esm/interfaces.js +0 -2
  121. package/dist/esm/interfaces.js.map +0 -1
package/dist/esm/knock.js CHANGED
@@ -1,69 +1,90 @@
1
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import ApiClient from "./api";
3
- import FeedClient from "./clients/feed";
4
- import Preferences from "./clients/preferences";
5
- import UserClient from "./clients/users";
6
- var DEFAULT_HOST = "https://api.knock.app";
7
- class Knock {
8
- constructor(apiKey) {
9
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10
- this.apiKey = apiKey;
11
- _defineProperty(this, "host", void 0);
12
- _defineProperty(this, "apiClient", null);
13
- _defineProperty(this, "userId", void 0);
14
- _defineProperty(this, "userToken", void 0);
15
- _defineProperty(this, "feeds", new FeedClient(this));
16
- _defineProperty(this, "preferences", new Preferences(this));
17
- _defineProperty(this, "user", new UserClient(this));
18
- this.host = options.host || DEFAULT_HOST;
19
-
20
- // Fail loudly if we're using the wrong API key
21
- if (this.apiKey && this.apiKey.startsWith("sk_")) {
22
- throw new Error("[Knock] You are using your secret API key on the client. Please use the public key.");
23
- }
1
+ var c = Object.defineProperty;
2
+ var l = (s, e, t) => e in s ? c(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var i = (s, e, t) => (l(s, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import { jwtDecode as u } from "jwt-decode";
5
+ import p from "./api.js";
6
+ import k from "./clients/feed/index.js";
7
+ import d from "./clients/preferences/index.js";
8
+ import f from "./clients/users/index.js";
9
+ const T = "https://api.knock.app";
10
+ class x {
11
+ constructor(e, t = {}) {
12
+ i(this, "host");
13
+ i(this, "apiClient", null);
14
+ i(this, "userId");
15
+ i(this, "userToken");
16
+ i(this, "logLevel");
17
+ i(this, "tokenExpirationTimer", null);
18
+ i(this, "feeds", new k(this));
19
+ i(this, "preferences", new d(this));
20
+ i(this, "user", new f(this));
21
+ if (this.apiKey = e, this.host = t.host || T, this.logLevel = t.logLevel, this.log("Initialized Knock instance"), this.apiKey && this.apiKey.startsWith("sk_"))
22
+ throw new Error(
23
+ "[Knock] You are using your secret API key on the client. Please use the public key."
24
+ );
24
25
  }
25
26
  client() {
26
- if (!this.userId) {
27
- console.warn("[Knock] You must call authenticate(userId, userToken) first before trying to make a request.\n Typically you'll see this message when you're creating a feed instance before having called\n authenticate with a user Id and token. That means we won't know who to issue the request\n to Knock on behalf of.\n ");
28
- }
29
-
30
- // Initiate a new API client if we don't have one yet
31
- if (!this.apiClient) {
32
- this.apiClient = new ApiClient({
33
- apiKey: this.apiKey,
34
- host: this.host,
35
- userToken: this.userToken
36
- });
37
- }
38
- return this.apiClient;
27
+ return this.userId || console.warn(
28
+ `[Knock] You must call authenticate(userId, userToken) first before trying to make a request.
29
+ Typically you'll see this message when you're creating a feed instance before having called
30
+ authenticate with a user Id and token. That means we won't know who to issue the request
31
+ to Knock on behalf of.
32
+ `
33
+ ), this.apiClient || (this.apiClient = this.createApiClient()), this.apiClient;
39
34
  }
40
-
41
35
  /*
42
36
  Authenticates the current user. In non-sandbox environments
43
37
  the userToken must be specified.
44
38
  */
45
- authenticate(userId, userToken) {
46
- this.userId = userId;
47
- this.userToken = userToken;
48
- return;
39
+ authenticate(e, t, n) {
40
+ let r = !1;
41
+ this.apiClient && (this.userId !== e || this.userToken !== t) && (this.log("userId or userToken changed; reinitializing connections"), this.feeds.teardownInstances(), this.teardown(), r = !0), this.userId = e, this.userToken = t, this.log(`Authenticated with userId ${e}`), this.userToken && (n == null ? void 0 : n.onUserTokenExpiring) instanceof Function && this.maybeScheduleUserTokenExpiration(
42
+ n.onUserTokenExpiring,
43
+ n.timeBeforeExpirationInMs
44
+ ), r && (this.apiClient = this.createApiClient(), this.feeds.reinitializeInstances(), this.log("Reinitialized real-time connections"));
49
45
  }
50
-
51
46
  /*
52
47
  Returns whether or this Knock instance is authenticated. Passing `true` will check the presence
53
48
  of the userToken as well.
54
49
  */
55
- isAuthenticated() {
56
- var checkUserToken = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
57
- return checkUserToken ? this.userId && this.userToken : this.userId;
50
+ isAuthenticated(e = !1) {
51
+ return e ? !!(this.userId && this.userToken) : !!this.userId;
58
52
  }
59
-
60
53
  // Used to teardown any connected instances
61
54
  teardown() {
62
- if (!this.apiClient) return;
63
- if (this.apiClient.socket) {
64
- this.apiClient.socket.disconnect();
55
+ var e;
56
+ this.tokenExpirationTimer && clearTimeout(this.tokenExpirationTimer), (e = this.apiClient) != null && e.socket && this.apiClient.socket.isConnected() && this.apiClient.socket.disconnect();
57
+ }
58
+ log(e) {
59
+ this.logLevel === "debug" && console.log(`[Knock] ${e}`);
60
+ }
61
+ /**
62
+ * Initiates an API client
63
+ */
64
+ createApiClient() {
65
+ return new p({
66
+ apiKey: this.apiKey,
67
+ host: this.host,
68
+ userToken: this.userToken
69
+ });
70
+ }
71
+ async maybeScheduleUserTokenExpiration(e, t = 3e4) {
72
+ if (!this.userToken)
73
+ return;
74
+ const n = u(this.userToken), r = (n.exp ?? 0) * 1e3, o = Date.now();
75
+ if (r && r > o) {
76
+ const h = r - t - o;
77
+ this.tokenExpirationTimer = setTimeout(async () => {
78
+ const a = await e(this.userToken, n);
79
+ typeof a == "string" && this.authenticate(this.userId, a, {
80
+ onUserTokenExpiring: e,
81
+ timeBeforeExpirationInMs: t
82
+ });
83
+ }, h);
65
84
  }
66
85
  }
67
86
  }
68
- export default Knock;
69
- //# sourceMappingURL=knock.js.map
87
+ export {
88
+ x as default
89
+ };
90
+ //# sourceMappingURL=knock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"knock.js","names":["ApiClient","FeedClient","Preferences","UserClient","DEFAULT_HOST","Knock","constructor","apiKey","options","arguments","length","undefined","_defineProperty","host","startsWith","Error","client","userId","console","warn","apiClient","userToken","authenticate","isAuthenticated","checkUserToken","teardown","socket","disconnect"],"sources":["../../src/knock.ts"],"sourcesContent":["import ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport Preferences from \"./clients/preferences\";\nimport UserClient from \"./clients/users\";\nimport { KnockOptions } from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n private host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined;\n public userToken: string | undefined;\n\n readonly feeds = new FeedClient(this);\n readonly preferences = new Preferences(this);\n readonly user = new UserClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n if (!this.userId) {\n console.warn(\n `[Knock] You must call authenticate(userId, userToken) first before trying to make a request.\n Typically you'll see this message when you're creating a feed instance before having called\n authenticate with a user Id and token. That means we won't know who to issue the request\n to Knock on behalf of.\n `,\n );\n }\n\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n return this.apiClient;\n }\n\n /*\n Authenticates the current user. In non-sandbox environments\n the userToken must be specified.\n */\n authenticate(userId: string, userToken?: string) {\n this.userId = userId;\n this.userToken = userToken;\n\n return;\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? this.userId && this.userToken : this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (!this.apiClient) return;\n if (this.apiClient.socket) {\n this.apiClient.socket.disconnect();\n }\n }\n}\n\nexport default Knock;\n"],"mappings":";AAAA,OAAOA,SAAS,MAAM,OAAO;AAC7B,OAAOC,UAAU,MAAM,gBAAgB;AACvC,OAAOC,WAAW,MAAM,uBAAuB;AAC/C,OAAOC,UAAU,MAAM,iBAAiB;AAGxC,IAAMC,YAAY,GAAG,uBAAuB;AAE5C,MAAMC,KAAK,CAAC;EAUVC,WAAWA,CACAC,MAAc,EAEvB;IAAA,IADAC,OAAqB,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;IAAA,KADjBF,MAAc,GAAdA,MAAc;IAAAK,eAAA;IAAAA,eAAA,oBATa,IAAI;IAAAA,eAAA;IAAAA,eAAA;IAAAA,eAAA,gBAIzB,IAAIX,UAAU,CAAC,IAAI,CAAC;IAAAW,eAAA,sBACd,IAAIV,WAAW,CAAC,IAAI,CAAC;IAAAU,eAAA,eAC5B,IAAIT,UAAU,CAAC,IAAI,CAAC;IAMlC,IAAI,CAACU,IAAI,GAAGL,OAAO,CAACK,IAAI,IAAIT,YAAY;;IAExC;IACA,IAAI,IAAI,CAACG,MAAM,IAAI,IAAI,CAACA,MAAM,CAACO,UAAU,CAAC,KAAK,CAAC,EAAE;MAChD,MAAM,IAAIC,KAAK,CACb,qFACF,CAAC;IACH;EACF;EAEAC,MAAMA,CAAA,EAAG;IACP,IAAI,CAAC,IAAI,CAACC,MAAM,EAAE;MAChBC,OAAO,CAACC,IAAI,gVAMZ,CAAC;IACH;;IAEA;IACA,IAAI,CAAC,IAAI,CAACC,SAAS,EAAE;MACnB,IAAI,CAACA,SAAS,GAAG,IAAIpB,SAAS,CAAC;QAC7BO,MAAM,EAAE,IAAI,CAACA,MAAM;QACnBM,IAAI,EAAE,IAAI,CAACA,IAAI;QACfQ,SAAS,EAAE,IAAI,CAACA;MAClB,CAAC,CAAC;IACJ;IAEA,OAAO,IAAI,CAACD,SAAS;EACvB;;EAEA;AACF;AACA;AACA;EACEE,YAAYA,CAACL,MAAc,EAAEI,SAAkB,EAAE;IAC/C,IAAI,CAACJ,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACI,SAAS,GAAGA,SAAS;IAE1B;EACF;;EAEA;AACF;AACA;AACA;EACEE,eAAeA,CAAA,EAAyB;IAAA,IAAxBC,cAAc,GAAAf,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;IACpC,OAAOe,cAAc,GAAG,IAAI,CAACP,MAAM,IAAI,IAAI,CAACI,SAAS,GAAG,IAAI,CAACJ,MAAM;EACrE;;EAEA;EACAQ,QAAQA,CAAA,EAAG;IACT,IAAI,CAAC,IAAI,CAACL,SAAS,EAAE;IACrB,IAAI,IAAI,CAACA,SAAS,CAACM,MAAM,EAAE;MACzB,IAAI,CAACN,SAAS,CAACM,MAAM,CAACC,UAAU,CAAC,CAAC;IACpC;EACF;AACF;AAEA,eAAetB,KAAK"}
1
+ {"version":3,"file":"knock.js","sources":["../../src/knock.ts"],"sourcesContent":["import { jwtDecode } from \"jwt-decode\";\n\nimport ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport Preferences from \"./clients/preferences\";\nimport UserClient from \"./clients/users\";\nimport {\n AuthenticateOptions,\n KnockOptions,\n LogLevel,\n UserTokenExpiringCallback,\n} from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n private host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined;\n public userToken?: string;\n public logLevel?: LogLevel;\n private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;\n readonly feeds = new FeedClient(this);\n readonly preferences = new Preferences(this);\n readonly user = new UserClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n this.logLevel = options.logLevel;\n\n this.log(\"Initialized Knock instance\");\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n if (!this.userId) {\n console.warn(\n `[Knock] You must call authenticate(userId, userToken) first before trying to make a request.\n Typically you'll see this message when you're creating a feed instance before having called\n authenticate with a user Id and token. That means we won't know who to issue the request\n to Knock on behalf of.\n `,\n );\n }\n\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = this.createApiClient();\n }\n\n return this.apiClient;\n }\n\n /*\n Authenticates the current user. In non-sandbox environments\n the userToken must be specified.\n */\n authenticate(\n userId: string,\n userToken?: string,\n options?: AuthenticateOptions,\n ) {\n let reinitializeApi = false;\n const currentApiClient = this.apiClient;\n\n // If we've previously been initialized and the values have now changed, then we\n // need to reinitialize any stateful connections we have\n if (\n currentApiClient &&\n (this.userId !== userId || this.userToken !== userToken)\n ) {\n this.log(\"userId or userToken changed; reinitializing connections\");\n this.feeds.teardownInstances();\n this.teardown();\n reinitializeApi = true;\n }\n\n this.userId = userId;\n this.userToken = userToken;\n\n this.log(`Authenticated with userId ${userId}`);\n\n if (this.userToken && options?.onUserTokenExpiring instanceof Function) {\n this.maybeScheduleUserTokenExpiration(\n options.onUserTokenExpiring,\n options.timeBeforeExpirationInMs,\n );\n }\n\n // If we get the signal to reinitialize the api client, then we want to create a new client\n // and the reinitialize any existing feed real-time connections we have so everything continues\n // to work with the new credentials we've been given\n if (reinitializeApi) {\n this.apiClient = this.createApiClient();\n this.feeds.reinitializeInstances();\n this.log(\"Reinitialized real-time connections\");\n }\n\n return;\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (this.tokenExpirationTimer) {\n clearTimeout(this.tokenExpirationTimer);\n }\n if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {\n this.apiClient.socket.disconnect();\n }\n }\n\n log(message: string) {\n if (this.logLevel === \"debug\") {\n console.log(`[Knock] ${message}`);\n }\n }\n\n /**\n * Initiates an API client\n */\n private createApiClient() {\n return new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n private async maybeScheduleUserTokenExpiration(\n callbackFn: UserTokenExpiringCallback,\n timeBeforeExpirationInMs: number = 30_000,\n ) {\n if (!this.userToken) return;\n\n const decoded = jwtDecode(this.userToken);\n const expiresAtMs = (decoded.exp ?? 0) * 1000;\n const nowMs = Date.now();\n\n // Expiration is in the future\n if (expiresAtMs && expiresAtMs > nowMs) {\n // Check how long until the token should be regenerated\n // | ----------------- | ----------------------- |\n // ^ now ^ expiration offset ^ expires at\n const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;\n\n this.tokenExpirationTimer = setTimeout(async () => {\n const newToken = await callbackFn(this.userToken as string, decoded);\n\n // Reauthenticate which will handle reinitializing sockets\n if (typeof newToken === \"string\") {\n this.authenticate(this.userId!, newToken, {\n onUserTokenExpiring: callbackFn,\n timeBeforeExpirationInMs: timeBeforeExpirationInMs,\n });\n }\n }, msInFuture);\n }\n }\n}\n\nexport default Knock;\n"],"names":["DEFAULT_HOST","Knock","apiKey","options","__publicField","FeedClient","Preferences","UserClient","userId","userToken","reinitializeApi","checkUserToken","_a","message","ApiClient","callbackFn","timeBeforeExpirationInMs","decoded","jwtDecode","expiresAtMs","nowMs","msInFuture","newToken"],"mappings":";;;;;;;;AAaA,MAAMA,IAAe;AAErB,MAAMC,EAAM;AAAA,EAWV,YACWC,GACTC,IAAwB,IACxB;AAbM,IAAAC,EAAA;AACA,IAAAA,EAAA,mBAA8B;AAC/B,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACC,IAAAA,EAAA,8BAA6D;AAC5D,IAAAA,EAAA,eAAQ,IAAIC,EAAW,IAAI;AAC3B,IAAAD,EAAA,qBAAc,IAAIE,EAAY,IAAI;AAClC,IAAAF,EAAA,cAAO,IAAIG,EAAW,IAAI;AAYjC,QATS,KAAA,SAAAL,GAGJ,KAAA,OAAOC,EAAQ,QAAQH,GAC5B,KAAK,WAAWG,EAAQ,UAExB,KAAK,IAAI,4BAA4B,GAGjC,KAAK,UAAU,KAAK,OAAO,WAAW,KAAK;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,EAGN;AAAA,EAEA,SAAS;AACH,WAAC,KAAK,UACA,QAAA;AAAA,MACN;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,GASC,KAAK,cACH,KAAA,YAAY,KAAK,oBAGjB,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aACEK,GACAC,GACAN,GACA;AACA,QAAIO,IAAkB;AAKtB,IAJyB,KAAK,cAM3B,KAAK,WAAWF,KAAU,KAAK,cAAcC,OAE9C,KAAK,IAAI,yDAAyD,GAClE,KAAK,MAAM,qBACX,KAAK,SAAS,GACIC,IAAA,KAGpB,KAAK,SAASF,GACd,KAAK,YAAYC,GAEZ,KAAA,IAAI,6BAA6BD,CAAM,EAAE,GAE1C,KAAK,cAAaL,KAAA,gBAAAA,EAAS,gCAA+B,YACvD,KAAA;AAAA,MACHA,EAAQ;AAAA,MACRA,EAAQ;AAAA,IAAA,GAORO,MACG,KAAA,YAAY,KAAK,mBACtB,KAAK,MAAM,yBACX,KAAK,IAAI,qCAAqC;AAAA,EAIlD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgBC,IAAiB,IAAO;AAC/B,WAAAA,IAAiB,CAAC,EAAE,KAAK,UAAU,KAAK,aAAa,CAAC,CAAC,KAAK;AAAA,EACrE;AAAA;AAAA,EAGA,WAAW;;AACT,IAAI,KAAK,wBACP,aAAa,KAAK,oBAAoB,IAEpCC,IAAA,KAAK,cAAL,QAAAA,EAAgB,UAAU,KAAK,UAAU,OAAO,iBAC7C,KAAA,UAAU,OAAO;EAE1B;AAAA,EAEA,IAAIC,GAAiB;AACf,IAAA,KAAK,aAAa,WACZ,QAAA,IAAI,WAAWA,CAAO,EAAE;AAAA,EAEpC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB;AACxB,WAAO,IAAIC,EAAU;AAAA,MACnB,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,IAAA,CACjB;AAAA,EACH;AAAA,EAEA,MAAc,iCACZC,GACAC,IAAmC,KACnC;AACA,QAAI,CAAC,KAAK;AAAW;AAEf,UAAAC,IAAUC,EAAU,KAAK,SAAS,GAClCC,KAAeF,EAAQ,OAAO,KAAK,KACnCG,IAAQ,KAAK;AAGf,QAAAD,KAAeA,IAAcC,GAAO;AAIhC,YAAAC,IAAaF,IAAcH,IAA2BI;AAEvD,WAAA,uBAAuB,WAAW,YAAY;AACjD,cAAME,IAAW,MAAMP,EAAW,KAAK,WAAqBE,CAAO;AAG/D,QAAA,OAAOK,KAAa,YACjB,KAAA,aAAa,KAAK,QAASA,GAAU;AAAA,UACxC,qBAAqBP;AAAA,UACrB,0BAAAC;AAAA,QAAA,CACD;AAAA,SAEFK,CAAU;AAAA,IACf;AAAA,EACF;AACF;"}
@@ -1,11 +1,15 @@
1
- export var NetworkStatus = /*#__PURE__*/function (NetworkStatus) {
2
- NetworkStatus["loading"] = "loading";
3
- NetworkStatus["fetchMore"] = "fetchMore";
4
- NetworkStatus["ready"] = "ready";
5
- NetworkStatus["error"] = "error";
6
- return NetworkStatus;
7
- }({});
8
- export function isRequestInFlight(networkStatus) {
9
- return [NetworkStatus.loading, NetworkStatus.fetchMore].includes(networkStatus);
1
+ var e = /* @__PURE__ */ ((r) => (r.loading = "loading", r.fetchMore = "fetchMore", r.ready = "ready", r.error = "error", r))(e || {});
2
+ function n(r) {
3
+ return [
4
+ "loading",
5
+ "fetchMore"
6
+ /* fetchMore */
7
+ ].includes(
8
+ r
9
+ );
10
10
  }
11
- //# sourceMappingURL=networkStatus.js.map
11
+ export {
12
+ e as NetworkStatus,
13
+ n as isRequestInFlight
14
+ };
15
+ //# sourceMappingURL=networkStatus.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"networkStatus.js","names":["NetworkStatus","isRequestInFlight","networkStatus","loading","fetchMore","includes"],"sources":["../../src/networkStatus.ts"],"sourcesContent":["export enum NetworkStatus {\n // Performing a top level loading operation\n loading = \"loading\",\n\n // Performing a fetch more on some already loaded data\n fetchMore = \"fetchMore\",\n\n // No operation is currently in progress\n ready = \"ready\",\n\n // The last operation failed with an error\n error = \"error\",\n}\n\nexport function isRequestInFlight(networkStatus: NetworkStatus): boolean {\n return [NetworkStatus.loading, NetworkStatus.fetchMore].includes(\n networkStatus,\n );\n}\n"],"mappings":"AAAA,WAAYA,aAAa,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;AAczB,OAAO,SAASC,iBAAiBA,CAACC,aAA4B,EAAW;EACvE,OAAO,CAACF,aAAa,CAACG,OAAO,EAAEH,aAAa,CAACI,SAAS,CAAC,CAACC,QAAQ,CAC9DH,aACF,CAAC;AACH"}
1
+ {"version":3,"file":"networkStatus.js","sources":["../../src/networkStatus.ts"],"sourcesContent":["export enum NetworkStatus {\n // Performing a top level loading operation\n loading = \"loading\",\n\n // Performing a fetch more on some already loaded data\n fetchMore = \"fetchMore\",\n\n // No operation is currently in progress\n ready = \"ready\",\n\n // The last operation failed with an error\n error = \"error\",\n}\n\nexport function isRequestInFlight(networkStatus: NetworkStatus): boolean {\n return [NetworkStatus.loading, NetworkStatus.fetchMore].includes(\n networkStatus,\n );\n}\n"],"names":["NetworkStatus","isRequestInFlight","networkStatus"],"mappings":"AAAY,IAAAA,sBAAAA,OAEVA,EAAA,UAAU,WAGVA,EAAA,YAAY,aAGZA,EAAA,QAAQ,SAGRA,EAAA,QAAQ,SAXEA,IAAAA,KAAA,CAAA,CAAA;AAcL,SAASC,EAAkBC,GAAuC;AAChE,SAAA;AAAA,IAAC;AAAA,IAAuB;AAAA;AAAA,EAAA,EAAyB;AAAA,IACtDA;AAAA,EAAA;AAEJ;"}
@@ -0,0 +1,11 @@
1
+ import FeedClient, { Feed } from "./clients/feed";
2
+ import Knock from "./knock";
3
+ export * from "./interfaces";
4
+ export * from "./clients/feed/types";
5
+ export * from "./clients/feed/interfaces";
6
+ export * from "./clients/preferences/interfaces";
7
+ export * from "./clients/users";
8
+ export * from "./networkStatus";
9
+ export default Knock;
10
+ export { Feed, FeedClient };
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,eAAe,KAAK,CAAC;AACrB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
+ };
28
+ var __importDefault = (this && this.__importDefault) || function (mod) {
29
+ return (mod && mod.__esModule) ? mod : { "default": mod };
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.FeedClient = exports.Feed = void 0;
33
+ const feed_1 = __importStar(require("./clients/feed"));
34
+ exports.FeedClient = feed_1.default;
35
+ Object.defineProperty(exports, "Feed", { enumerable: true, get: function () { return feed_1.Feed; } });
36
+ const knock_1 = __importDefault(require("./knock"));
37
+ __exportStar(require("./interfaces"), exports);
38
+ __exportStar(require("./clients/feed/types"), exports);
39
+ __exportStar(require("./clients/feed/interfaces"), exports);
40
+ __exportStar(require("./clients/preferences/interfaces"), exports);
41
+ __exportStar(require("./clients/users"), exports);
42
+ __exportStar(require("./networkStatus"), exports);
43
+ exports.default = knock_1.default;
@@ -0,0 +1,41 @@
1
+ import { GenericData } from "@knocklabs/types";
2
+ export type LogLevel = "debug";
3
+ export interface KnockOptions {
4
+ host?: string;
5
+ logLevel?: LogLevel;
6
+ }
7
+ export interface KnockObject<T = GenericData> {
8
+ id: string;
9
+ collection: string;
10
+ properties: T;
11
+ updated_at: string;
12
+ created_at: string | null;
13
+ }
14
+ export interface User extends GenericData {
15
+ id: string;
16
+ email: string | null;
17
+ name: string | null;
18
+ phone_number: string | null;
19
+ avatar: string | null;
20
+ updated_at: string;
21
+ created_at: string | null;
22
+ }
23
+ export type Recipient = User | KnockObject;
24
+ export interface Activity<T = GenericData> {
25
+ id: string;
26
+ inserted_at: string;
27
+ updated_at: string;
28
+ recipient: Recipient;
29
+ actor: Recipient | null;
30
+ data: T | null;
31
+ }
32
+ export interface ChannelData<T = any> {
33
+ channel_id: string;
34
+ data: T;
35
+ }
36
+ export type UserTokenExpiringCallback = (currentToken: string, decodedToken: any) => Promise<string | void>;
37
+ export interface AuthenticateOptions {
38
+ onUserTokenExpiring?: UserTokenExpiringCallback;
39
+ timeBeforeExpirationInMs?: number;
40
+ }
41
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,30 @@
1
+ import ApiClient from "./api";
2
+ import FeedClient from "./clients/feed";
3
+ import Preferences from "./clients/preferences";
4
+ import UserClient from "./clients/users";
5
+ import { AuthenticateOptions, KnockOptions, LogLevel } from "./interfaces";
6
+ declare class Knock {
7
+ readonly apiKey: string;
8
+ private host;
9
+ private apiClient;
10
+ userId: string | undefined;
11
+ userToken?: string;
12
+ logLevel?: LogLevel;
13
+ private tokenExpirationTimer;
14
+ readonly feeds: FeedClient;
15
+ readonly preferences: Preferences;
16
+ readonly user: UserClient;
17
+ constructor(apiKey: string, options?: KnockOptions);
18
+ client(): ApiClient;
19
+ authenticate(userId: string, userToken?: string, options?: AuthenticateOptions): void;
20
+ isAuthenticated(checkUserToken?: boolean): boolean;
21
+ teardown(): void;
22
+ log(message: string): void;
23
+ /**
24
+ * Initiates an API client
25
+ */
26
+ private createApiClient;
27
+ private maybeScheduleUserTokenExpiration;
28
+ }
29
+ export default Knock;
30
+ //# sourceMappingURL=knock.d.ts.map
@@ -0,0 +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,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EAET,MAAM,cAAc,CAAC;AAItB,cAAM,KAAK;IAYP,QAAQ,CAAC,MAAM,EAAE,MAAM;IAXzB,OAAO,CAAC,IAAI,CAAS;IACrB,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,WAAW,cAAyB;IAC7C,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"}
package/dist/knock.js ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jwt_decode_1 = require("jwt-decode");
7
+ const api_1 = __importDefault(require("./api"));
8
+ const feed_1 = __importDefault(require("./clients/feed"));
9
+ const preferences_1 = __importDefault(require("./clients/preferences"));
10
+ const users_1 = __importDefault(require("./clients/users"));
11
+ const DEFAULT_HOST = "https://api.knock.app";
12
+ class Knock {
13
+ apiKey;
14
+ host;
15
+ apiClient = null;
16
+ userId;
17
+ userToken;
18
+ logLevel;
19
+ tokenExpirationTimer = null;
20
+ feeds = new feed_1.default(this);
21
+ preferences = new preferences_1.default(this);
22
+ user = new users_1.default(this);
23
+ constructor(apiKey, options = {}) {
24
+ this.apiKey = apiKey;
25
+ this.host = options.host || DEFAULT_HOST;
26
+ this.logLevel = options.logLevel;
27
+ this.log("Initialized Knock instance");
28
+ // Fail loudly if we're using the wrong API key
29
+ if (this.apiKey && this.apiKey.startsWith("sk_")) {
30
+ throw new Error("[Knock] You are using your secret API key on the client. Please use the public key.");
31
+ }
32
+ }
33
+ client() {
34
+ if (!this.userId) {
35
+ console.warn(`[Knock] You must call authenticate(userId, userToken) first before trying to make a request.
36
+ Typically you'll see this message when you're creating a feed instance before having called
37
+ authenticate with a user Id and token. That means we won't know who to issue the request
38
+ to Knock on behalf of.
39
+ `);
40
+ }
41
+ // Initiate a new API client if we don't have one yet
42
+ if (!this.apiClient) {
43
+ this.apiClient = this.createApiClient();
44
+ }
45
+ return this.apiClient;
46
+ }
47
+ /*
48
+ Authenticates the current user. In non-sandbox environments
49
+ the userToken must be specified.
50
+ */
51
+ authenticate(userId, userToken, options) {
52
+ let reinitializeApi = false;
53
+ const currentApiClient = this.apiClient;
54
+ // If we've previously been initialized and the values have now changed, then we
55
+ // need to reinitialize any stateful connections we have
56
+ if (currentApiClient &&
57
+ (this.userId !== userId || this.userToken !== userToken)) {
58
+ this.log("userId or userToken changed; reinitializing connections");
59
+ this.feeds.teardownInstances();
60
+ this.teardown();
61
+ reinitializeApi = true;
62
+ }
63
+ this.userId = userId;
64
+ this.userToken = userToken;
65
+ this.log(`Authenticated with userId ${userId}`);
66
+ if (this.userToken && options?.onUserTokenExpiring instanceof Function) {
67
+ this.maybeScheduleUserTokenExpiration(options.onUserTokenExpiring, options.timeBeforeExpirationInMs);
68
+ }
69
+ // If we get the signal to reinitialize the api client, then we want to create a new client
70
+ // and the reinitialize any existing feed real-time connections we have so everything continues
71
+ // to work with the new credentials we've been given
72
+ if (reinitializeApi) {
73
+ this.apiClient = this.createApiClient();
74
+ this.feeds.reinitializeInstances();
75
+ this.log("Reinitialized real-time connections");
76
+ }
77
+ return;
78
+ }
79
+ /*
80
+ Returns whether or this Knock instance is authenticated. Passing `true` will check the presence
81
+ of the userToken as well.
82
+ */
83
+ isAuthenticated(checkUserToken = false) {
84
+ return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;
85
+ }
86
+ // Used to teardown any connected instances
87
+ teardown() {
88
+ if (this.tokenExpirationTimer) {
89
+ clearTimeout(this.tokenExpirationTimer);
90
+ }
91
+ if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {
92
+ this.apiClient.socket.disconnect();
93
+ }
94
+ }
95
+ log(message) {
96
+ if (this.logLevel === "debug") {
97
+ console.log(`[Knock] ${message}`);
98
+ }
99
+ }
100
+ /**
101
+ * Initiates an API client
102
+ */
103
+ createApiClient() {
104
+ return new api_1.default({
105
+ apiKey: this.apiKey,
106
+ host: this.host,
107
+ userToken: this.userToken,
108
+ });
109
+ }
110
+ async maybeScheduleUserTokenExpiration(callbackFn, timeBeforeExpirationInMs = 30000) {
111
+ if (!this.userToken)
112
+ return;
113
+ const decoded = (0, jwt_decode_1.jwtDecode)(this.userToken);
114
+ const expiresAtMs = (decoded.exp ?? 0) * 1000;
115
+ const nowMs = Date.now();
116
+ // Expiration is in the future
117
+ if (expiresAtMs && expiresAtMs > nowMs) {
118
+ // Check how long until the token should be regenerated
119
+ // | ----------------- | ----------------------- |
120
+ // ^ now ^ expiration offset ^ expires at
121
+ const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;
122
+ this.tokenExpirationTimer = setTimeout(async () => {
123
+ const newToken = await callbackFn(this.userToken, decoded);
124
+ // Reauthenticate which will handle reinitializing sockets
125
+ if (typeof newToken === "string") {
126
+ this.authenticate(this.userId, newToken, {
127
+ onUserTokenExpiring: callbackFn,
128
+ timeBeforeExpirationInMs: timeBeforeExpirationInMs,
129
+ });
130
+ }
131
+ }, msInFuture);
132
+ }
133
+ }
134
+ }
135
+ exports.default = Knock;
@@ -0,0 +1,8 @@
1
+ export declare enum NetworkStatus {
2
+ loading = "loading",
3
+ fetchMore = "fetchMore",
4
+ ready = "ready",
5
+ error = "error"
6
+ }
7
+ export declare function isRequestInFlight(networkStatus: NetworkStatus): boolean;
8
+ //# sourceMappingURL=networkStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkStatus.d.ts","sourceRoot":"","sources":["../src/networkStatus.ts"],"names":[],"mappings":"AAAA,oBAAY,aAAa;IAEvB,OAAO,YAAY;IAGnB,SAAS,cAAc;IAGvB,KAAK,UAAU;IAGf,KAAK,UAAU;CAChB;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAIvE"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRequestInFlight = exports.NetworkStatus = void 0;
4
+ var NetworkStatus;
5
+ (function (NetworkStatus) {
6
+ // Performing a top level loading operation
7
+ NetworkStatus["loading"] = "loading";
8
+ // Performing a fetch more on some already loaded data
9
+ NetworkStatus["fetchMore"] = "fetchMore";
10
+ // No operation is currently in progress
11
+ NetworkStatus["ready"] = "ready";
12
+ // The last operation failed with an error
13
+ NetworkStatus["error"] = "error";
14
+ })(NetworkStatus || (exports.NetworkStatus = NetworkStatus = {}));
15
+ function isRequestInFlight(networkStatus) {
16
+ return [NetworkStatus.loading, NetworkStatus.fetchMore].includes(networkStatus);
17
+ }
18
+ exports.isRequestInFlight = isRequestInFlight;
@@ -19,8 +19,6 @@ declare class ApiClient {
19
19
  socket: Socket | undefined;
20
20
  constructor(options: ApiClientOptions);
21
21
  makeRequest(req: AxiosRequestConfig): Promise<ApiResponse>;
22
- reconnectSocket(): void;
23
- disconnectSocket(): void;
24
22
  private canRetryRequest;
25
23
  }
26
24
  export default ApiClient;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA,OAAc,EAAiB,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,WAAW;IAE1B,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,cAAM,SAAS;IACb,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,WAAW,CAAgB;IAE5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEtB,OAAO,EAAE,gBAAgB;IAgC/B,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAwBhE,eAAe;IAMf,gBAAgB;IAMhB,OAAO,CAAC,eAAe;CAuBxB;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA,OAAc,EAA6B,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,WAAW;IAE1B,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,cAAM,SAAS;IACb,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,WAAW,CAAgB;IAE5B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEtB,OAAO,EAAE,gBAAgB;IAgC/B,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAwBhE,OAAO,CAAC,eAAe;CAuBxB;AAED,eAAe,SAAS,CAAC"}
@@ -1,25 +1,31 @@
1
1
  import { StoreApi } from "zustand";
2
- import { BindableFeedEvent, FeedEventCallback, FeedItemOrItems, FeedStoreState, FeedRealTimeCallback } from "./types";
3
- import { FeedClientOptions, FetchFeedOptions } from "./interfaces";
4
2
  import Knock from "../../knock";
3
+ import { FeedClientOptions, FetchFeedOptions } from "./interfaces";
4
+ import { BindableFeedEvent, FeedEventCallback, FeedItemOrItems, FeedRealTimeCallback, FeedStoreState } from "./types";
5
5
  export type Status = "seen" | "read" | "interacted" | "archived" | "unseen" | "unread" | "unarchived";
6
6
  declare class Feed {
7
7
  readonly knock: Knock;
8
8
  readonly feedId: string;
9
- private apiClient;
10
9
  private userFeedId;
11
- private channel;
10
+ private channel?;
12
11
  private broadcaster;
13
12
  private defaultOptions;
14
13
  private broadcastChannel;
15
14
  private disconnectTimer;
15
+ private hasSubscribedToRealTimeUpdates;
16
16
  store: StoreApi<FeedStoreState>;
17
17
  constructor(knock: Knock, feedId: string, options: FeedClientOptions);
18
+ /**
19
+ * Used to reinitialize a current feed instance, which is useful when reauthenticating users
20
+ */
21
+ reinitialize(): void;
18
22
  /**
19
23
  * Cleans up a feed instance by destroying the store and disconnecting
20
24
  * an open socket connection.
21
25
  */
22
26
  teardown(): void;
27
+ /** Tears down an instance and removes it entirely from the feed manager */
28
+ dispose(): void;
23
29
  listenForUpdates(): void;
24
30
  on(eventName: BindableFeedEvent, callback: FeedEventCallback | FeedRealTimeCallback): void;
25
31
  off(eventName: BindableFeedEvent, callback: FeedEventCallback | FeedRealTimeCallback): void;
@@ -45,7 +51,9 @@ declare class Feed {
45
51
  private optimisticallyPerformStatusUpdate;
46
52
  private makeStatusUpdate;
47
53
  private makeBulkStatusUpdate;
54
+ private setupBroadcastChannel;
48
55
  private broadcastOverChannel;
56
+ private initializeRealtimeConnection;
49
57
  /**
50
58
  * Listen for changes to document visibility and automatically disconnect
51
59
  * or reconnect the socket after a delay
@@ -1 +1 @@
1
- {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../../../src/clients/feed/feed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInC,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EAEjB,eAAe,EACf,cAAc,EAEd,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,OAAO,EAEL,iBAAiB,EACjB,gBAAgB,EAGjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,MAAM,aAAa,CAAC;AAGhC,MAAM,MAAM,MAAM,GACd,MAAM,GACN,MAAM,GACN,YAAY,GACZ,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,YAAY,CAAC;AASjB,cAAM,IAAI;IAaN,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAbzB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,cAAc,CAAoB;IAC1C,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,eAAe,CAA8C;IAG9D,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAG5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,iBAAiB;IA+B5B;;;OAGG;IACH,QAAQ;IAkBR,gBAAgB;IAyChB,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;IA+Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA+Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAuB7C,cAAc,CAAC,WAAW,EAAE,eAAe;IA0E3C,iBAAiB;IAgCjB,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAS7C,KAAK,CAAC,OAAO,GAAE,gBAAqB;;;;IA6EpC,aAAa;IAgBnB,OAAO,CAAC,SAAS;YAQH,oBAAoB;IAalC,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iCAAiC;YAmD3B,gBAAgB;YAmBhB,oBAAoB;IAyBlC,OAAO,CAAC,oBAAoB;IAoB5B;;;OAGG;IACH,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":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,MAAM,aAAa,CAAC;AAGhC,OAAO,EACL,iBAAiB,EAIjB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EAEjB,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,MAAM,GACd,MAAM,GACN,MAAM,GACN,YAAY,GACZ,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,YAAY,CAAC;AASjB,cAAM,IAAI;IAaN,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAbzB,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;IAGjD,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAG5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,iBAAiB;IAgB5B;;OAEG;IACH,YAAY;IAWZ;;;OAGG;IACH,QAAQ;IAkBR,2EAA2E;IAC3E,OAAO;IAWP,gBAAgB;IAmBhB,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;IA+Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,UAAU,CAAC,WAAW,EAAE,eAAe;IAYvC,aAAa;IA+Cb,YAAY,CAAC,WAAW,EAAE,eAAe;IAWzC,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAuB7C,cAAc,CAAC,WAAW,EAAE,eAAe;IA0E3C,iBAAiB;IAgCjB,gBAAgB,CAAC,WAAW,EAAE,eAAe;IAS7C,KAAK,CAAC,OAAO,GAAE,gBAAqB;;;;IA6EpC,aAAa;IAgBnB,OAAO,CAAC,SAAS;YAQH,oBAAoB;IAelC,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iCAAiC;YAmD3B,gBAAgB;YAmBhB,oBAAoB;IAyBlC,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,4BAA4B;IA4BpC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;CA4B/B;AAED,eAAe,IAAI,CAAC"}
@@ -3,8 +3,12 @@ import Feed from "./feed";
3
3
  import { FeedClientOptions } from "./interfaces";
4
4
  declare class FeedClient {
5
5
  private instance;
6
+ private feedInstances;
6
7
  constructor(instance: Knock);
7
8
  initialize(feedChannelId: string, options?: FeedClientOptions): Feed;
9
+ removeInstance(feed: Feed): void;
10
+ teardownInstances(): void;
11
+ reinitializeInstances(): void;
8
12
  }
9
13
  export { Feed };
10
14
  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;AAChC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,cAAM,UAAU;IACd,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,QAAQ,EAAE,KAAK;IAI3B,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;CAGlE;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;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"}