@knocklabs/react-core 0.12.2 → 0.12.4
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.
- package/CHANGELOG.md +13 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/modules/core/hooks/useAuthPolling.js +2 -0
- package/dist/cjs/modules/core/hooks/useAuthPolling.js.map +1 -0
- package/dist/cjs/modules/core/hooks/useAuthPostMessageListener.js +2 -0
- package/dist/cjs/modules/core/hooks/useAuthPostMessageListener.js.map +1 -0
- package/dist/cjs/modules/ms-teams/context/KnockMsTeamsProvider.js +1 -1
- package/dist/cjs/modules/ms-teams/context/KnockMsTeamsProvider.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useMsTeamsConnectionStatus.js.map +1 -1
- package/dist/cjs/modules/slack/context/KnockSlackProvider.js +1 -1
- package/dist/cjs/modules/slack/context/KnockSlackProvider.js.map +1 -1
- package/dist/cjs/modules/slack/hooks/useSlackConnectionStatus.js.map +1 -1
- package/dist/esm/index.mjs +70 -66
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/modules/core/hooks/useAuthPolling.mjs +50 -0
- package/dist/esm/modules/core/hooks/useAuthPolling.mjs.map +1 -0
- package/dist/esm/modules/core/hooks/useAuthPostMessageListener.mjs +19 -0
- package/dist/esm/modules/core/hooks/useAuthPostMessageListener.mjs.map +1 -0
- package/dist/esm/modules/ms-teams/context/KnockMsTeamsProvider.mjs +28 -26
- package/dist/esm/modules/ms-teams/context/KnockMsTeamsProvider.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useMsTeamsConnectionStatus.mjs.map +1 -1
- package/dist/esm/modules/slack/context/KnockSlackProvider.mjs +24 -22
- package/dist/esm/modules/slack/context/KnockSlackProvider.mjs.map +1 -1
- package/dist/esm/modules/slack/hooks/useSlackConnectionStatus.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modules/core/hooks/index.d.ts +2 -0
- package/dist/types/modules/core/hooks/index.d.ts.map +1 -1
- package/dist/types/modules/core/hooks/useAuthPolling.d.ts +34 -0
- package/dist/types/modules/core/hooks/useAuthPolling.d.ts.map +1 -0
- package/dist/types/modules/core/hooks/useAuthPostMessageListener.d.ts +27 -0
- package/dist/types/modules/core/hooks/useAuthPostMessageListener.d.ts.map +1 -0
- package/dist/types/modules/core/index.d.ts +2 -1
- package/dist/types/modules/core/index.d.ts.map +1 -1
- package/dist/types/modules/core/types.d.ts +20 -0
- package/dist/types/modules/core/types.d.ts.map +1 -0
- package/dist/types/modules/ms-teams/context/KnockMsTeamsProvider.d.ts +2 -1
- package/dist/types/modules/ms-teams/context/KnockMsTeamsProvider.d.ts.map +1 -1
- package/dist/types/modules/ms-teams/hooks/useMsTeamsConnectionStatus.d.ts +1 -1
- package/dist/types/modules/ms-teams/hooks/useMsTeamsConnectionStatus.d.ts.map +1 -1
- package/dist/types/modules/slack/context/KnockSlackProvider.d.ts +2 -1
- package/dist/types/modules/slack/context/KnockSlackProvider.d.ts.map +1 -1
- package/dist/types/modules/slack/hooks/useSlackConnectionStatus.d.ts +1 -1
- package/dist/types/modules/slack/hooks/useSlackConnectionStatus.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +4 -0
- package/src/modules/core/hooks/index.ts +2 -0
- package/src/modules/core/hooks/useAuthPolling.ts +115 -0
- package/src/modules/core/hooks/useAuthPostMessageListener.ts +70 -0
- package/src/modules/core/index.ts +7 -1
- package/src/modules/core/types.ts +25 -0
- package/src/modules/ms-teams/context/KnockMsTeamsProvider.tsx +5 -3
- package/src/modules/ms-teams/hooks/useMsTeamsConnectionStatus.ts +1 -7
- package/src/modules/slack/context/KnockSlackProvider.tsx +5 -3
- package/src/modules/slack/hooks/useSlackConnectionStatus.ts +1 -7
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
import
|
|
1
|
+
import S from "../hooks/useSlackConnectionStatus.mjs";
|
|
2
2
|
import * as o from "react";
|
|
3
|
+
import { useRef as C } from "react";
|
|
3
4
|
import "swr/infinite";
|
|
4
|
-
import { useKnockClient as
|
|
5
|
+
import { useKnockClient as f } from "../../core/context/KnockProvider.mjs";
|
|
5
6
|
import "@knocklabs/client";
|
|
6
7
|
import "fast-deep-equal";
|
|
7
|
-
import { slackProviderKey as
|
|
8
|
+
import { slackProviderKey as p } from "../../core/utils.mjs";
|
|
8
9
|
import "swr";
|
|
9
10
|
import "../../i18n/context/KnockI18nProvider.mjs";
|
|
10
|
-
const
|
|
11
|
+
const i = o.createContext(null), E = (t) => {
|
|
11
12
|
const {
|
|
12
13
|
knockSlackChannelId: e,
|
|
13
|
-
children:
|
|
14
|
-
} = t, n = "tenantId" in t ? t.tenantId : t.tenant, l =
|
|
14
|
+
children: a
|
|
15
|
+
} = t, n = "tenantId" in t ? t.tenantId : t.tenant, l = f(), s = C(null), {
|
|
15
16
|
connectionStatus: r,
|
|
16
|
-
setConnectionStatus:
|
|
17
|
+
setConnectionStatus: k,
|
|
17
18
|
errorLabel: c,
|
|
18
|
-
setErrorLabel:
|
|
19
|
-
actionLabel:
|
|
20
|
-
setActionLabel:
|
|
21
|
-
} =
|
|
22
|
-
return /* @__PURE__ */ o.createElement(
|
|
19
|
+
setErrorLabel: m,
|
|
20
|
+
actionLabel: u,
|
|
21
|
+
setActionLabel: d
|
|
22
|
+
} = S(l, e, n);
|
|
23
|
+
return /* @__PURE__ */ o.createElement(i.Provider, { key: p({
|
|
23
24
|
knockSlackChannelId: e,
|
|
24
25
|
tenantId: n,
|
|
25
26
|
connectionStatus: r,
|
|
26
27
|
errorLabel: c
|
|
27
28
|
}), value: {
|
|
28
29
|
connectionStatus: r,
|
|
29
|
-
setConnectionStatus:
|
|
30
|
+
setConnectionStatus: k,
|
|
30
31
|
errorLabel: c,
|
|
31
|
-
setErrorLabel:
|
|
32
|
-
actionLabel:
|
|
33
|
-
setActionLabel:
|
|
32
|
+
setErrorLabel: m,
|
|
33
|
+
actionLabel: u,
|
|
34
|
+
setActionLabel: d,
|
|
34
35
|
knockSlackChannelId: e,
|
|
35
36
|
// Assign the same value to both tenant and tenantId for backwards compatibility
|
|
36
37
|
tenant: n,
|
|
37
|
-
tenantId: n
|
|
38
|
-
|
|
39
|
-
},
|
|
40
|
-
|
|
38
|
+
tenantId: n,
|
|
39
|
+
popupWindowRef: s
|
|
40
|
+
} }, a);
|
|
41
|
+
}, R = () => {
|
|
42
|
+
const t = o.useContext(i);
|
|
41
43
|
if (t === void 0)
|
|
42
44
|
throw new Error("useKnockSlackClient must be used within a KnockSlackProvider");
|
|
43
45
|
return t;
|
|
44
46
|
};
|
|
45
47
|
export {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
E as KnockSlackProvider,
|
|
49
|
+
R as useKnockSlackClient
|
|
48
50
|
};
|
|
49
51
|
//# sourceMappingURL=KnockSlackProvider.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockSlackProvider.mjs","sources":["../../../../../src/modules/slack/context/KnockSlackProvider.tsx"],"sourcesContent":["import { useSlackConnectionStatus } from \"..\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { slackProviderKey } from \"../../core\";\nimport { useKnockClient } from \"../../core\";\
|
|
1
|
+
{"version":3,"file":"KnockSlackProvider.mjs","sources":["../../../../../src/modules/slack/context/KnockSlackProvider.tsx"],"sourcesContent":["import { useSlackConnectionStatus } from \"..\";\nimport * as React from \"react\";\nimport { PropsWithChildren, useRef } from \"react\";\n\nimport { type ConnectionStatus, slackProviderKey } from \"../../core\";\nimport { useKnockClient } from \"../../core\";\n\nexport interface KnockSlackProviderState {\n knockSlackChannelId: string;\n tenantId: string;\n /**\n * @deprecated Use `tenantId` instead. This field will be removed in a future release.\n */\n tenant: string;\n connectionStatus: ConnectionStatus;\n setConnectionStatus: (connectionStatus: ConnectionStatus) => void;\n errorLabel: string | null;\n setErrorLabel: (label: string) => void;\n actionLabel: string | null;\n setActionLabel: (label: string | null) => void;\n popupWindowRef: React.MutableRefObject<Window | null>;\n}\n\nconst SlackProviderStateContext =\n React.createContext<KnockSlackProviderState | null>(null);\n\nexport type KnockSlackProviderProps =\n | {\n knockSlackChannelId: string;\n /**\n * @deprecated Use `tenantId` instead. This field will be removed in a future release.\n */\n tenant: string;\n }\n | {\n knockSlackChannelId: string;\n tenantId: string;\n };\n\nexport const KnockSlackProvider: React.FC<\n PropsWithChildren<KnockSlackProviderProps>\n> = (props) => {\n const { knockSlackChannelId, children } = props;\n const tenantId = \"tenantId\" in props ? props.tenantId : props.tenant;\n\n const knock = useKnockClient();\n const popupWindowRef = useRef<Window | null>(null);\n\n const {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n } = useSlackConnectionStatus(knock, knockSlackChannelId, tenantId);\n\n return (\n <SlackProviderStateContext.Provider\n key={slackProviderKey({\n knockSlackChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n })}\n value={{\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n knockSlackChannelId,\n // Assign the same value to both tenant and tenantId for backwards compatibility\n tenant: tenantId,\n tenantId,\n popupWindowRef,\n }}\n >\n {children}\n </SlackProviderStateContext.Provider>\n );\n};\n\nexport const useKnockSlackClient = (): KnockSlackProviderState => {\n const context = React.useContext(\n SlackProviderStateContext,\n ) as KnockSlackProviderState;\n if (context === undefined) {\n throw new Error(\n \"useKnockSlackClient must be used within a KnockSlackProvider\",\n );\n }\n return context as KnockSlackProviderState;\n};\n"],"names":["SlackProviderStateContext","React","createContext","KnockSlackProvider","props","knockSlackChannelId","children","tenantId","tenant","knock","useKnockClient","popupWindowRef","useRef","connectionStatus","setConnectionStatus","errorLabel","setErrorLabel","actionLabel","setActionLabel","useSlackConnectionStatus","slackProviderKey","useKnockSlackClient","context","useContext","undefined","Error"],"mappings":";;;;;;;;;;AAuBA,MAAMA,IACJC,EAAMC,cAA8C,IAAI,GAe7CC,IAERC,CAAUA,MAAA;AACP,QAAA;AAAA,IAAEC,qBAAAA;AAAAA,IAAqBC,UAAAA;AAAAA,EAAAA,IAAaF,GACpCG,IAAW,cAAcH,IAAQA,EAAMG,WAAWH,EAAMI,QAExDC,IAAQC,EAAe,GACvBC,IAAiBC,EAAsB,IAAI,GAE3C;AAAA,IACJC,kBAAAA;AAAAA,IACAC,qBAAAA;AAAAA,IACAC,YAAAA;AAAAA,IACAC,eAAAA;AAAAA,IACAC,aAAAA;AAAAA,IACAC,gBAAAA;AAAAA,EACEC,IAAAA,EAAyBV,GAAOJ,GAAqBE,CAAQ;AAEjE,SACG,gBAAAN,EAAA,cAAAD,EAA0B,UAA1B,EACC,KAAKoB,EAAiB;AAAA,IACpBf,qBAAAA;AAAAA,IACAE,UAAAA;AAAAA,IACAM,kBAAAA;AAAAA,IACAE,YAAAA;AAAAA,EACD,CAAA,GACD,OAAO;AAAA,IACLF,kBAAAA;AAAAA,IACAC,qBAAAA;AAAAA,IACAC,YAAAA;AAAAA,IACAC,eAAAA;AAAAA,IACAC,aAAAA;AAAAA,IACAC,gBAAAA;AAAAA,IACAb,qBAAAA;AAAAA;AAAAA,IAEAG,QAAQD;AAAAA,IACRA,UAAAA;AAAAA,IACAI,gBAAAA;AAAAA,OAGDL,CACH;AAEJ,GAEae,IAAsBA,MAA+B;AAC1DC,QAAAA,IAAUrB,EAAMsB,WACpBvB,CACF;AACA,MAAIsB,MAAYE;AACR,UAAA,IAAIC,MACR,8DACF;AAEKH,SAAAA;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlackConnectionStatus.mjs","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"useSlackConnectionStatus.mjs","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport { type ConnectionStatus } from \"../../core/types\";\nimport { useTranslations } from \"../../i18n\";\n\ntype UseSlackConnectionStatusOutput = {\n connectionStatus: ConnectionStatus;\n setConnectionStatus: (status: ConnectionStatus) => void;\n errorLabel: string | null;\n setErrorLabel: (errorLabel: string) => void;\n actionLabel: string | null;\n setActionLabel: (actionLabel: string | null) => void;\n};\n\n/**\n * Transforms a slack error message into\n * a formatted one. Slack error messages: https://api.slack.com/methods/auth.test#errors\n *\n * Ex.: \"account_inactive\" -> \"Account inactive\"\n */\nconst formatSlackErrorMessage = (errorMessage: string) => {\n const firstLetter = errorMessage.substring(0, 1).toUpperCase();\n const rest = errorMessage.substring(1);\n return firstLetter?.concat(rest).replace(\"_\", \" \");\n};\n\nfunction useSlackConnectionStatus(\n knock: Knock,\n knockSlackChannelId: string,\n tenantId: string,\n): UseSlackConnectionStatusOutput {\n const { t } = useTranslations();\n const [connectionStatus, setConnectionStatus] =\n useState<ConnectionStatus>(\"connecting\");\n const [errorLabel, setErrorLabel] = useState<string | null>(null);\n const [actionLabel, setActionLabel] = useState<string | null>(null);\n\n useEffect(() => {\n const checkAuthStatus = async () => {\n if (connectionStatus !== \"connecting\") return;\n\n try {\n const authRes = await knock.slack.authCheck({\n tenant: tenantId,\n knockChannelId: knockSlackChannelId,\n });\n\n if (authRes.connection?.ok) {\n return setConnectionStatus(\"connected\");\n }\n\n // This is a normal response for a tenant that doesn't have an access\n // token set on it, meaning it's not connected to Slack, so we\n // give it a \"disconnected\" status instead of an error status.\n if (\n authRes.code === \"ERR_BAD_REQUEST\" &&\n authRes.response?.data?.message === t(\"slackAccessTokenNotSet\")\n ) {\n return setConnectionStatus(\"disconnected\");\n }\n\n // This is for an error coming directly from Slack.\n if (authRes.connection && authRes.connection.error) {\n const errorLabel = formatSlackErrorMessage(authRes.connection.error);\n setErrorLabel(errorLabel);\n setConnectionStatus(\"error\");\n return;\n }\n\n if (authRes.connection) {\n return setConnectionStatus(\"disconnected\");\n }\n\n setConnectionStatus(\"error\");\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n };\n\n checkAuthStatus();\n }, [connectionStatus, tenantId, knockSlackChannelId, knock.slack, t]);\n\n return {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n };\n}\n\nexport default useSlackConnectionStatus;\n"],"names":["formatSlackErrorMessage","errorMessage","firstLetter","substring","toUpperCase","rest","concat","replace","useSlackConnectionStatus","knock","knockSlackChannelId","tenantId","t","useTranslations","connectionStatus","setConnectionStatus","useState","errorLabel","setErrorLabel","actionLabel","setActionLabel","useEffect","authRes","slack","authCheck","tenant","knockChannelId","connection","ok","code","response","data","message","error"],"mappings":";;;AAqBA,MAAMA,IAA0BA,CAACC,MAAyB;AACxD,QAAMC,IAAcD,EAAaE,UAAU,GAAG,CAAC,EAAEC,YAAY,GACvDC,IAAOJ,EAAaE,UAAU,CAAC;AACrC,SAAOD,KAAAA,gBAAAA,EAAaI,OAAOD,GAAME,QAAQ,KAAK;AAChD;AAEA,SAASC,EACPC,GACAC,GACAC,GACgC;AAC1B,QAAA;AAAA,IAAEC,GAAAA;AAAAA,MAAMC,EAAgB,GACxB,CAACC,GAAkBC,CAAmB,IAC1CC,EAA2B,YAAY,GACnC,CAACC,GAAYC,CAAa,IAAIF,EAAwB,IAAI,GAC1D,CAACG,GAAaC,CAAc,IAAIJ,EAAwB,IAAI;AAElEK,SAAAA,EAAU,MAAM;AA0CE,KAzCQ,YAAY;;AAClC,UAAIP,MAAqB;AAErB,YAAA;AACF,gBAAMQ,IAAU,MAAMb,EAAMc,MAAMC,UAAU;AAAA,YAC1CC,QAAQd;AAAAA,YACRe,gBAAgBhB;AAAAA,UAAAA,CACjB;AAEGY,eAAAA,IAAAA,EAAQK,eAARL,QAAAA,EAAoBM;AACtB,mBAAOb,EAAoB,WAAW;AAOtCO,cAAAA,EAAQO,SAAS,uBACjBP,KAAAA,IAAAA,EAAQQ,aAARR,gBAAAA,EAAkBS,SAAlBT,gBAAAA,EAAwBU,aAAYpB,EAAE,wBAAwB;AAE9D,mBAAOG,EAAoB,cAAc;AAI3C,cAAIO,EAAQK,cAAcL,EAAQK,WAAWM,OAAO;AAClD,kBAAMhB,IAAajB,EAAwBsB,EAAQK,WAAWM,KAAK;AACnEf,YAAAA,EAAcD,CAAU,GACxBF,EAAoB,OAAO;AAC3B;AAAA,UAAA;AAGF,cAAIO,EAAQK;AACV,mBAAOZ,EAAoB,cAAc;AAG3CA,UAAAA,EAAoB,OAAO;AAAA,gBACZ;AACfA,UAAAA,EAAoB,OAAO;AAAA,QAAA;AAAA,IAE/B,GAEgB;AAAA,EAAA,GACf,CAACD,GAAkBH,GAAUD,GAAqBD,EAAMc,OAAOX,CAAC,CAAC,GAE7D;AAAA,IACLE,kBAAAA;AAAAA,IACAC,qBAAAA;AAAAA,IACAE,YAAAA;AAAAA,IACAC,eAAAA;AAAAA,IACAC,aAAAA;AAAAA,IACAC,gBAAAA;AAAAA,EACF;AACF;"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { FilterStatus, KnockProvider, feedProviderKey, formatBadgeCount, formatTimestamp, msTeamsProviderKey, renderNodeOrFallback, slackProviderKey, toSentenceCase, type ColorMode, type KnockProviderProps, type KnockProviderState, useAuthenticatedKnockClient, useKnockClient, useStableOptions, } from './modules/core';
|
|
1
|
+
export { FilterStatus, KnockProvider, feedProviderKey, formatBadgeCount, formatTimestamp, msTeamsProviderKey, renderNodeOrFallback, slackProviderKey, toSentenceCase, type AuthCheckResult, type ColorMode, type ConnectionStatus, type KnockProviderProps, type KnockProviderState, useAuthenticatedKnockClient, useAuthPolling, useAuthPostMessageListener, useKnockClient, useStableOptions, } from './modules/core';
|
|
2
2
|
export { KnockFeedProvider, type KnockFeedProviderProps, type KnockFeedProviderState, type Selector, useCreateNotificationStore, useFeedSettings, useKnockFeed, useNotificationStore, useNotifications, } from './modules/feed';
|
|
3
3
|
export { KnockGuideProvider, KnockGuideContext, type KnockGuideProviderProps, useGuide, useGuides, useGuideContext, } from './modules/guide';
|
|
4
4
|
export { type MsTeamsChannelQueryOptions, type MsTeamsTeamQueryOptions, KnockMsTeamsProvider, type KnockMsTeamsProviderProps, type KnockMsTeamsProviderState, useConnectedMsTeamsChannels, useKnockMsTeamsClient, useMsTeamsAuth, useMsTeamsChannels, useMsTeamsConnectionStatus, useMsTeamsTeams, } from './modules/ms-teams';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,2BAA2B,EAC3B,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,0BAA0B,EAC1B,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,uBAAuB,EAC5B,QAAQ,EACR,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,yBAAyB,EACzB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAMvD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,2BAA2B,EAC3B,cAAc,EACd,0BAA0B,EAC1B,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,0BAA0B,EAC1B,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,uBAAuB,EAC5B,QAAQ,EACR,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,yBAAyB,EACzB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAMvD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { default as useAuthenticatedKnockClient } from './useAuthenticatedKnockClient';
|
|
2
2
|
export { default as useStableOptions } from './useStableOptions';
|
|
3
|
+
export { useAuthPostMessageListener } from './useAuthPostMessageListener';
|
|
4
|
+
export { useAuthPolling } from './useAuthPolling';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AuthCheckResult, ConnectionStatus } from '../types';
|
|
2
|
+
export interface UseAuthPollingOptions {
|
|
3
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
4
|
+
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
5
|
+
authCheckFn: () => Promise<AuthCheckResult>;
|
|
6
|
+
onAuthenticationComplete?: (authenticationResp: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hook that polls an authentication check endpoint until success or timeout.
|
|
10
|
+
*
|
|
11
|
+
* Polls every 2 seconds for up to 3 minutes (90 iterations). Has three stop conditions:
|
|
12
|
+
* 1. Max timeout reached → sets error status
|
|
13
|
+
* 2. Popup closed + 10s grace period → stops silently
|
|
14
|
+
* 3. Success detected via authCheckFn → updates status and closes popup
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration options for the polling mechanism
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* useAuthPolling({
|
|
21
|
+
* popupWindowRef,
|
|
22
|
+
* setConnectionStatus,
|
|
23
|
+
* onAuthenticationComplete,
|
|
24
|
+
* authCheckFn: useCallback(async () => {
|
|
25
|
+
* return knock.slack.authCheck({
|
|
26
|
+
* tenant: tenantId,
|
|
27
|
+
* knockChannelId: knockSlackChannelId,
|
|
28
|
+
* });
|
|
29
|
+
* }, [knock.slack, tenantId, knockSlackChannelId]),
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function useAuthPolling(options: UseAuthPollingOptions): void;
|
|
34
|
+
//# sourceMappingURL=useAuthPolling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthPolling.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/useAuthPolling.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,mBAAmB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,WAAW,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5C,wBAAwB,CAAC,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CA8EnE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ConnectionStatus } from '../types';
|
|
2
|
+
export interface UseAuthPostMessageListenerOptions {
|
|
3
|
+
knockHost: string;
|
|
4
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
5
|
+
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
6
|
+
onAuthenticationComplete?: (authenticationResp: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hook that listens for postMessage events from OAuth popup windows.
|
|
10
|
+
*
|
|
11
|
+
* Handles "authComplete" and "authFailed" messages sent from the OAuth flow popup,
|
|
12
|
+
* validates the message origin, updates connection status, and closes the popup.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Configuration options for the postMessage listener
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* useAuthPostMessageListener({
|
|
19
|
+
* knockHost: knock.host,
|
|
20
|
+
* popupWindowRef,
|
|
21
|
+
* setConnectionStatus,
|
|
22
|
+
* onAuthenticationComplete,
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useAuthPostMessageListener(options: UseAuthPostMessageListenerOptions): void;
|
|
27
|
+
//# sourceMappingURL=useAuthPostMessageListener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthPostMessageListener.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/useAuthPostMessageListener.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,mBAAmB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,wBAAwB,CAAC,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,IAAI,CAsCN"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { KnockProvider, useKnockClient, type KnockProviderProps, type KnockProviderState, } from './context';
|
|
2
|
-
export { useAuthenticatedKnockClient, useStableOptions } from './hooks';
|
|
2
|
+
export { useAuthenticatedKnockClient, useStableOptions, useAuthPostMessageListener, useAuthPolling, } from './hooks';
|
|
3
3
|
export { FilterStatus, type ColorMode } from './constants';
|
|
4
4
|
export { formatBadgeCount, formatTimestamp, toSentenceCase, renderNodeOrFallback, feedProviderKey, slackProviderKey, msTeamsProviderKey, } from './utils';
|
|
5
|
+
export { type ConnectionStatus, type AuthCheckResult } from './types';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,2BAA2B,EAC3B,gBAAgB,EAChB,0BAA0B,EAC1B,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the connection status for OAuth-based integrations (Slack, MS Teams, etc.)
|
|
3
|
+
*/
|
|
4
|
+
export type ConnectionStatus = "connecting" | "connected" | "disconnected" | "error" | "disconnecting";
|
|
5
|
+
/**
|
|
6
|
+
* Result returned by authentication check API calls
|
|
7
|
+
*/
|
|
8
|
+
export interface AuthCheckResult {
|
|
9
|
+
connection?: {
|
|
10
|
+
ok?: boolean;
|
|
11
|
+
error?: string;
|
|
12
|
+
};
|
|
13
|
+
code?: string;
|
|
14
|
+
response?: {
|
|
15
|
+
data?: {
|
|
16
|
+
message?: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,WAAW,GACX,cAAc,GACd,OAAO,GACP,eAAe,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE;QACX,EAAE,CAAC,EAAE,OAAO,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE;YACL,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;CACH"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import { ConnectionStatus } from '
|
|
2
|
+
import { ConnectionStatus } from '../../core';
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
export interface KnockMsTeamsProviderState {
|
|
5
5
|
knockMsTeamsChannelId: string;
|
|
@@ -10,6 +10,7 @@ export interface KnockMsTeamsProviderState {
|
|
|
10
10
|
setErrorLabel: (label: string) => void;
|
|
11
11
|
actionLabel: string | null;
|
|
12
12
|
setActionLabel: (label: string | null) => void;
|
|
13
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
13
14
|
}
|
|
14
15
|
export interface KnockMsTeamsProviderProps {
|
|
15
16
|
knockMsTeamsChannelId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockMsTeamsProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ms-teams/context/KnockMsTeamsProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"KnockMsTeamsProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ms-teams/context/KnockMsTeamsProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAU,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,KAAK,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AAInE,MAAM,WAAW,yBAAyB;IACxC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvD;AAKD,MAAM,WAAW,yBAAyB;IACxC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CACzC,iBAAiB,CAAC,yBAAyB,CAAC,CAqC7C,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,yBAQxC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as Knock } from '@knocklabs/client';
|
|
2
|
-
|
|
2
|
+
import { ConnectionStatus } from '../../core/types';
|
|
3
3
|
type UseMsTeamsConnectionStatusOutput = {
|
|
4
4
|
connectionStatus: ConnectionStatus;
|
|
5
5
|
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsTeamsConnectionStatus.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsConnectionStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"useMsTeamsConnectionStatus.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsConnectionStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AAGtC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,KAAK,gCAAgC,GAAG;IACtC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,iBAAS,0BAA0B,CACjC,KAAK,EAAE,KAAK,EACZ,qBAAqB,EAAE,MAAM,EAC7B,QAAQ,EAAE,MAAM,GACf,gCAAgC,CAsDlC;AAED,eAAe,0BAA0B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import { ConnectionStatus } from '
|
|
2
|
+
import { ConnectionStatus } from '../../core';
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
export interface KnockSlackProviderState {
|
|
5
5
|
knockSlackChannelId: string;
|
|
@@ -14,6 +14,7 @@ export interface KnockSlackProviderState {
|
|
|
14
14
|
setErrorLabel: (label: string) => void;
|
|
15
15
|
actionLabel: string | null;
|
|
16
16
|
setActionLabel: (label: string | null) => void;
|
|
17
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
17
18
|
}
|
|
18
19
|
export type KnockSlackProviderProps = {
|
|
19
20
|
knockSlackChannelId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockSlackProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/slack/context/KnockSlackProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"KnockSlackProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/slack/context/KnockSlackProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAU,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAGrE,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvD;AAKD,MAAM,MAAM,uBAAuB,GAC/B;IACE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEN,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CACvC,iBAAiB,CAAC,uBAAuB,CAAC,CA0C3C,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,uBAUtC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as Knock } from '@knocklabs/client';
|
|
2
|
-
|
|
2
|
+
import { ConnectionStatus } from '../../core/types';
|
|
3
3
|
type UseSlackConnectionStatusOutput = {
|
|
4
4
|
connectionStatus: ConnectionStatus;
|
|
5
5
|
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlackConnectionStatus.d.ts","sourceRoot":"","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"useSlackConnectionStatus.d.ts","sourceRoot":"","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AAGtC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,KAAK,8BAA8B,GAAG;IACpC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD,CAAC;AAcF,iBAAS,wBAAwB,CAC/B,KAAK,EAAE,KAAK,EACZ,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,GACf,8BAA8B,CA4DhC;AAED,eAAe,wBAAwB,CAAC"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@knocklabs/react-core",
|
|
3
3
|
"description": "A set of React components to build notification experiences powered by Knock",
|
|
4
4
|
"author": "@knocklabs",
|
|
5
|
-
"version": "0.12.
|
|
5
|
+
"version": "0.12.4",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/cjs/index.js",
|
|
8
8
|
"module": "dist/esm/index.mjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@knocklabs/client": "^0.20.
|
|
50
|
+
"@knocklabs/client": "^0.20.3",
|
|
51
51
|
"@tanstack/react-store": "^0.7.3",
|
|
52
52
|
"date-fns": "^4.0.0",
|
|
53
53
|
"fast-deep-equal": "^3.1.3",
|
package/src/index.ts
CHANGED
|
@@ -8,10 +8,14 @@ export {
|
|
|
8
8
|
renderNodeOrFallback,
|
|
9
9
|
slackProviderKey,
|
|
10
10
|
toSentenceCase,
|
|
11
|
+
type AuthCheckResult,
|
|
11
12
|
type ColorMode,
|
|
13
|
+
type ConnectionStatus,
|
|
12
14
|
type KnockProviderProps,
|
|
13
15
|
type KnockProviderState,
|
|
14
16
|
useAuthenticatedKnockClient,
|
|
17
|
+
useAuthPolling,
|
|
18
|
+
useAuthPostMessageListener,
|
|
15
19
|
useKnockClient,
|
|
16
20
|
useStableOptions,
|
|
17
21
|
} from "./modules/core";
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as useAuthenticatedKnockClient } from "./useAuthenticatedKnockClient";
|
|
2
2
|
export { default as useStableOptions } from "./useStableOptions";
|
|
3
|
+
export { useAuthPostMessageListener } from "./useAuthPostMessageListener";
|
|
4
|
+
export { useAuthPolling } from "./useAuthPolling";
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
import { AuthCheckResult, ConnectionStatus } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface UseAuthPollingOptions {
|
|
6
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
7
|
+
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
8
|
+
authCheckFn: () => Promise<AuthCheckResult>;
|
|
9
|
+
onAuthenticationComplete?: (authenticationResp: string) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Hook that polls an authentication check endpoint until success or timeout.
|
|
14
|
+
*
|
|
15
|
+
* Polls every 2 seconds for up to 3 minutes (90 iterations). Has three stop conditions:
|
|
16
|
+
* 1. Max timeout reached → sets error status
|
|
17
|
+
* 2. Popup closed + 10s grace period → stops silently
|
|
18
|
+
* 3. Success detected via authCheckFn → updates status and closes popup
|
|
19
|
+
*
|
|
20
|
+
* @param options - Configuration options for the polling mechanism
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* useAuthPolling({
|
|
25
|
+
* popupWindowRef,
|
|
26
|
+
* setConnectionStatus,
|
|
27
|
+
* onAuthenticationComplete,
|
|
28
|
+
* authCheckFn: useCallback(async () => {
|
|
29
|
+
* return knock.slack.authCheck({
|
|
30
|
+
* tenant: tenantId,
|
|
31
|
+
* knockChannelId: knockSlackChannelId,
|
|
32
|
+
* });
|
|
33
|
+
* }, [knock.slack, tenantId, knockSlackChannelId]),
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function useAuthPolling(options: UseAuthPollingOptions): void {
|
|
38
|
+
const {
|
|
39
|
+
popupWindowRef,
|
|
40
|
+
setConnectionStatus,
|
|
41
|
+
onAuthenticationComplete,
|
|
42
|
+
authCheckFn,
|
|
43
|
+
} = options;
|
|
44
|
+
|
|
45
|
+
useEffect(
|
|
46
|
+
() => {
|
|
47
|
+
let pollCount = 0;
|
|
48
|
+
const maxPolls = 90;
|
|
49
|
+
let popupClosedAt: number | null = null;
|
|
50
|
+
let isActive = true;
|
|
51
|
+
|
|
52
|
+
const pollInterval = setInterval(async () => {
|
|
53
|
+
if (!isActive) {
|
|
54
|
+
clearInterval(pollInterval);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const popupWindow = popupWindowRef.current;
|
|
59
|
+
if (!popupWindow) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pollCount++;
|
|
64
|
+
|
|
65
|
+
const isPopupClosed = popupWindow.closed;
|
|
66
|
+
if (isPopupClosed && !popupClosedAt) {
|
|
67
|
+
popupClosedAt = Date.now();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Stop condition 1: Max timeout reached
|
|
71
|
+
if (pollCount >= maxPolls) {
|
|
72
|
+
clearInterval(pollInterval);
|
|
73
|
+
setConnectionStatus("error");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Stop condition 2: Popup closed + grace period expired
|
|
78
|
+
if (popupClosedAt && Date.now() - popupClosedAt > 10000) {
|
|
79
|
+
clearInterval(pollInterval);
|
|
80
|
+
popupWindowRef.current = null;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const authRes = await authCheckFn();
|
|
86
|
+
|
|
87
|
+
// Stop condition 3: Success detected
|
|
88
|
+
if (authRes.connection?.ok) {
|
|
89
|
+
clearInterval(pollInterval);
|
|
90
|
+
setConnectionStatus("connected");
|
|
91
|
+
if (onAuthenticationComplete) {
|
|
92
|
+
onAuthenticationComplete("authComplete");
|
|
93
|
+
}
|
|
94
|
+
if (popupWindow && !popupWindow.closed) {
|
|
95
|
+
popupWindow.close();
|
|
96
|
+
}
|
|
97
|
+
popupWindowRef.current = null;
|
|
98
|
+
}
|
|
99
|
+
} catch (_error) {
|
|
100
|
+
// Continue polling on error
|
|
101
|
+
}
|
|
102
|
+
}, 2000);
|
|
103
|
+
|
|
104
|
+
return () => {
|
|
105
|
+
isActive = false;
|
|
106
|
+
clearInterval(pollInterval);
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
|
+
[
|
|
111
|
+
// Empty deps - run once on mount and keep polling
|
|
112
|
+
// This is intentionally simple/brute force
|
|
113
|
+
],
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
import { ConnectionStatus } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface UseAuthPostMessageListenerOptions {
|
|
6
|
+
knockHost: string;
|
|
7
|
+
popupWindowRef: React.MutableRefObject<Window | null>;
|
|
8
|
+
setConnectionStatus: (status: ConnectionStatus) => void;
|
|
9
|
+
onAuthenticationComplete?: (authenticationResp: string) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Hook that listens for postMessage events from OAuth popup windows.
|
|
14
|
+
*
|
|
15
|
+
* Handles "authComplete" and "authFailed" messages sent from the OAuth flow popup,
|
|
16
|
+
* validates the message origin, updates connection status, and closes the popup.
|
|
17
|
+
*
|
|
18
|
+
* @param options - Configuration options for the postMessage listener
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* useAuthPostMessageListener({
|
|
23
|
+
* knockHost: knock.host,
|
|
24
|
+
* popupWindowRef,
|
|
25
|
+
* setConnectionStatus,
|
|
26
|
+
* onAuthenticationComplete,
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function useAuthPostMessageListener(
|
|
31
|
+
options: UseAuthPostMessageListenerOptions,
|
|
32
|
+
): void {
|
|
33
|
+
const {
|
|
34
|
+
knockHost,
|
|
35
|
+
popupWindowRef,
|
|
36
|
+
setConnectionStatus,
|
|
37
|
+
onAuthenticationComplete,
|
|
38
|
+
} = options;
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const receiveMessage = (event: MessageEvent) => {
|
|
42
|
+
// Validate message origin for security
|
|
43
|
+
if (event.origin !== knockHost) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (event.data === "authComplete") {
|
|
48
|
+
setConnectionStatus("connected");
|
|
49
|
+
onAuthenticationComplete?.(event.data);
|
|
50
|
+
// Clear popup ref so polling stops and doesn't trigger callback again
|
|
51
|
+
if (popupWindowRef.current && !popupWindowRef.current.closed) {
|
|
52
|
+
popupWindowRef.current.close();
|
|
53
|
+
}
|
|
54
|
+
popupWindowRef.current = null;
|
|
55
|
+
} else if (event.data === "authFailed") {
|
|
56
|
+
setConnectionStatus("error");
|
|
57
|
+
onAuthenticationComplete?.(event.data);
|
|
58
|
+
popupWindowRef.current = null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
window.addEventListener("message", receiveMessage, false);
|
|
63
|
+
return () => window.removeEventListener("message", receiveMessage);
|
|
64
|
+
}, [
|
|
65
|
+
knockHost,
|
|
66
|
+
onAuthenticationComplete,
|
|
67
|
+
setConnectionStatus,
|
|
68
|
+
popupWindowRef,
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
@@ -4,7 +4,12 @@ export {
|
|
|
4
4
|
type KnockProviderProps,
|
|
5
5
|
type KnockProviderState,
|
|
6
6
|
} from "./context";
|
|
7
|
-
export {
|
|
7
|
+
export {
|
|
8
|
+
useAuthenticatedKnockClient,
|
|
9
|
+
useStableOptions,
|
|
10
|
+
useAuthPostMessageListener,
|
|
11
|
+
useAuthPolling,
|
|
12
|
+
} from "./hooks";
|
|
8
13
|
export { FilterStatus, type ColorMode } from "./constants";
|
|
9
14
|
export {
|
|
10
15
|
formatBadgeCount,
|
|
@@ -15,3 +20,4 @@ export {
|
|
|
15
20
|
slackProviderKey,
|
|
16
21
|
msTeamsProviderKey,
|
|
17
22
|
} from "./utils";
|
|
23
|
+
export { type ConnectionStatus, type AuthCheckResult } from "./types";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the connection status for OAuth-based integrations (Slack, MS Teams, etc.)
|
|
3
|
+
*/
|
|
4
|
+
export type ConnectionStatus =
|
|
5
|
+
| "connecting"
|
|
6
|
+
| "connected"
|
|
7
|
+
| "disconnected"
|
|
8
|
+
| "error"
|
|
9
|
+
| "disconnecting";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Result returned by authentication check API calls
|
|
13
|
+
*/
|
|
14
|
+
export interface AuthCheckResult {
|
|
15
|
+
connection?: {
|
|
16
|
+
ok?: boolean;
|
|
17
|
+
error?: string;
|
|
18
|
+
};
|
|
19
|
+
code?: string;
|
|
20
|
+
response?: {
|
|
21
|
+
data?: {
|
|
22
|
+
message?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|