@knocklabs/react-core 0.4.0 → 0.5.0-rc.1.0
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 +11 -0
- package/dist/cjs/modules/core/context/KnockProvider.js.map +1 -1
- package/dist/cjs/modules/core/hooks/useAuthenticatedKnockClient.js.map +1 -1
- package/dist/cjs/modules/core/hooks/useStableOptions.js +1 -1
- package/dist/cjs/modules/core/hooks/useStableOptions.js.map +1 -1
- package/dist/cjs/modules/core/utils.js.map +1 -1
- package/dist/cjs/modules/feed/context/KnockFeedProvider.js.map +1 -1
- package/dist/cjs/modules/feed/hooks/useFeedSettings.js.map +1 -1
- package/dist/cjs/modules/feed/hooks/useNotificationStore.js +1 -1
- package/dist/cjs/modules/feed/hooks/useNotificationStore.js.map +1 -1
- package/dist/cjs/modules/feed/hooks/useNotifications.js.map +1 -1
- package/dist/cjs/modules/i18n/context/KnockI18nProvider.js.map +1 -1
- package/dist/cjs/modules/i18n/hooks/useTranslations.js.map +1 -1
- package/dist/cjs/modules/ms-teams/context/KnockMsTeamsProvider.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useConnectedMsTeamsChannels.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useMsTeamsAuth.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useMsTeamsChannels.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useMsTeamsConnectionStatus.js.map +1 -1
- package/dist/cjs/modules/ms-teams/hooks/useMsTeamsTeams.js.map +1 -1
- package/dist/cjs/modules/slack/context/KnockSlackProvider.js.map +1 -1
- package/dist/cjs/modules/slack/hooks/useConnectedSlackChannels.js.map +1 -1
- package/dist/cjs/modules/slack/hooks/useSlackAuth.js.map +1 -1
- package/dist/cjs/modules/slack/hooks/useSlackChannels.js.map +1 -1
- package/dist/cjs/modules/slack/hooks/useSlackConnectionStatus.js.map +1 -1
- package/dist/esm/modules/core/context/KnockProvider.mjs.map +1 -1
- package/dist/esm/modules/core/hooks/useAuthenticatedKnockClient.mjs.map +1 -1
- package/dist/esm/modules/core/hooks/useStableOptions.mjs +1 -1
- package/dist/esm/modules/core/hooks/useStableOptions.mjs.map +1 -1
- package/dist/esm/modules/core/utils.mjs.map +1 -1
- package/dist/esm/modules/feed/context/KnockFeedProvider.mjs.map +1 -1
- package/dist/esm/modules/feed/hooks/useFeedSettings.mjs.map +1 -1
- package/dist/esm/modules/feed/hooks/useNotificationStore.mjs +11 -13
- package/dist/esm/modules/feed/hooks/useNotificationStore.mjs.map +1 -1
- package/dist/esm/modules/feed/hooks/useNotifications.mjs.map +1 -1
- package/dist/esm/modules/i18n/context/KnockI18nProvider.mjs.map +1 -1
- package/dist/esm/modules/i18n/hooks/useTranslations.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/context/KnockMsTeamsProvider.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useConnectedMsTeamsChannels.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useMsTeamsAuth.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useMsTeamsChannels.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useMsTeamsConnectionStatus.mjs.map +1 -1
- package/dist/esm/modules/ms-teams/hooks/useMsTeamsTeams.mjs.map +1 -1
- package/dist/esm/modules/slack/context/KnockSlackProvider.mjs.map +1 -1
- package/dist/esm/modules/slack/hooks/useConnectedSlackChannels.mjs.map +1 -1
- package/dist/esm/modules/slack/hooks/useSlackAuth.mjs.map +1 -1
- package/dist/esm/modules/slack/hooks/useSlackChannels.mjs.map +1 -1
- package/dist/esm/modules/slack/hooks/useSlackConnectionStatus.mjs.map +1 -1
- package/dist/types/modules/feed/context/KnockFeedProvider.d.ts +2 -2
- package/dist/types/modules/feed/context/KnockFeedProvider.d.ts.map +1 -1
- package/dist/types/modules/feed/hooks/useNotificationStore.d.ts +19 -3
- package/dist/types/modules/feed/hooks/useNotificationStore.d.ts.map +1 -1
- package/package.json +8 -6
- package/src/modules/core/hooks/useStableOptions.ts +1 -1
- package/src/modules/feed/context/KnockFeedProvider.tsx +2 -2
- package/src/modules/feed/hooks/useNotificationStore.ts +48 -34
package/CHANGELOG.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockProvider.js","sources":["../../../../../src/modules/core/context/KnockProvider.tsx"],"sourcesContent":["import Knock, { AuthenticateOptions, LogLevel } from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { I18nContent, KnockI18nProvider } from \"../../i18n\";\nimport { useAuthenticatedKnockClient } from \"../hooks\";\n\nexport interface KnockProviderState {\n knock: Knock;\n}\n\nconst ProviderStateContext = React.createContext<KnockProviderState | null>(\n null,\n);\n\nexport interface KnockProviderProps {\n // Knock client props\n apiKey: string;\n host?: string;\n // Authentication props\n userId: Knock[\"userId\"];\n userToken?: Knock[\"userToken\"];\n onUserTokenExpiring?: AuthenticateOptions[\"onUserTokenExpiring\"];\n timeBeforeExpirationInMs?: AuthenticateOptions[\"timeBeforeExpirationInMs\"];\n // i18n translations\n i18n?: I18nContent;\n logLevel?: LogLevel;\n}\n\nexport const KnockProvider: React.FC<PropsWithChildren<KnockProviderProps>> = ({\n apiKey,\n host,\n logLevel,\n userId,\n userToken,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n children,\n i18n,\n}) => {\n // We memoize the options here so that we don't create a new object on every re-render\n const authenticateOptions = React.useMemo(\n () => ({\n host,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n logLevel,\n }),\n [host, onUserTokenExpiring, timeBeforeExpirationInMs, logLevel],\n );\n\n const knock = useAuthenticatedKnockClient(\n apiKey,\n userId,\n userToken,\n authenticateOptions,\n );\n\n return (\n <ProviderStateContext.Provider\n value={{\n knock,\n }}\n >\n <KnockI18nProvider i18n={i18n}>{children}</KnockI18nProvider>\n </ProviderStateContext.Provider>\n );\n};\n\nexport const useKnockClient = (): Knock => {\n const context = React.useContext(ProviderStateContext) as KnockProviderState;\n if (context === undefined) {\n throw new Error(\"useKnock must be used within a KnockProvider\");\n }\n return context.knock;\n};\n"],"names":["ProviderStateContext","React","createContext","KnockProvider","apiKey","host","logLevel","userId","userToken","onUserTokenExpiring","timeBeforeExpirationInMs","children","i18n","authenticateOptions","useMemo","knock","useAuthenticatedKnockClient","KnockI18nProvider","useKnockClient","context","useContext","undefined","Error"],"mappings":"yjBAWMA,EAAuBC,EAAMC,cACjC,IACF,EAgBaC,EAAiEA,CAAC,CAC7EC,OAAAA,EACAC,KAAAA,EACAC,SAAAA,EACAC,OAAAA,EACAC,UAAAA,EACAC,oBAAAA,EACAC,yBAAAA,EACAC,SAAAA,EACAC,KAAAA,CACF,IAAM,CAEEC,MAAAA,EAAsBZ,EAAMa,QAChC,KAAO,CACLT,KAAAA,EACAI,oBAAAA,EACAC,yBAAAA,EACAJ,SAAAA,
|
|
1
|
+
{"version":3,"file":"KnockProvider.js","sources":["../../../../../src/modules/core/context/KnockProvider.tsx"],"sourcesContent":["import Knock, { AuthenticateOptions, LogLevel } from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { I18nContent, KnockI18nProvider } from \"../../i18n\";\nimport { useAuthenticatedKnockClient } from \"../hooks\";\n\nexport interface KnockProviderState {\n knock: Knock;\n}\n\nconst ProviderStateContext = React.createContext<KnockProviderState | null>(\n null,\n);\n\nexport interface KnockProviderProps {\n // Knock client props\n apiKey: string;\n host?: string;\n // Authentication props\n userId: Knock[\"userId\"];\n userToken?: Knock[\"userToken\"];\n onUserTokenExpiring?: AuthenticateOptions[\"onUserTokenExpiring\"];\n timeBeforeExpirationInMs?: AuthenticateOptions[\"timeBeforeExpirationInMs\"];\n // i18n translations\n i18n?: I18nContent;\n logLevel?: LogLevel;\n}\n\nexport const KnockProvider: React.FC<PropsWithChildren<KnockProviderProps>> = ({\n apiKey,\n host,\n logLevel,\n userId,\n userToken,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n children,\n i18n,\n}) => {\n // We memoize the options here so that we don't create a new object on every re-render\n const authenticateOptions = React.useMemo(\n () => ({\n host,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n logLevel,\n }),\n [host, onUserTokenExpiring, timeBeforeExpirationInMs, logLevel],\n );\n\n const knock = useAuthenticatedKnockClient(\n apiKey,\n userId,\n userToken,\n authenticateOptions,\n );\n\n return (\n <ProviderStateContext.Provider\n value={{\n knock,\n }}\n >\n <KnockI18nProvider i18n={i18n}>{children}</KnockI18nProvider>\n </ProviderStateContext.Provider>\n );\n};\n\nexport const useKnockClient = (): Knock => {\n const context = React.useContext(ProviderStateContext) as KnockProviderState;\n if (context === undefined) {\n throw new Error(\"useKnock must be used within a KnockProvider\");\n }\n return context.knock;\n};\n"],"names":["ProviderStateContext","React","createContext","KnockProvider","apiKey","host","logLevel","userId","userToken","onUserTokenExpiring","timeBeforeExpirationInMs","children","i18n","authenticateOptions","useMemo","knock","useAuthenticatedKnockClient","KnockI18nProvider","useKnockClient","context","useContext","undefined","Error"],"mappings":"yjBAWMA,EAAuBC,EAAMC,cACjC,IACF,EAgBaC,EAAiEA,CAAC,CAC7EC,OAAAA,EACAC,KAAAA,EACAC,SAAAA,EACAC,OAAAA,EACAC,UAAAA,EACAC,oBAAAA,EACAC,yBAAAA,EACAC,SAAAA,EACAC,KAAAA,CACF,IAAM,CAEEC,MAAAA,EAAsBZ,EAAMa,QAChC,KAAO,CACLT,KAAAA,EACAI,oBAAAA,EACAC,yBAAAA,EACAJ,SAAAA,IAEF,CAACD,EAAMI,EAAqBC,EAA0BJ,CAAQ,CAChE,EAEMS,EAAQC,EACZZ,EACAG,EACAC,EACAK,CACF,EAEA,OACGZ,EAAA,cAAAD,EAAqB,SAArB,CACC,MAAO,CACLe,MAAAA,CAAAA,CAGF,EAAAd,EAAA,cAACgB,EAAAA,kBAAkB,CAAA,KAAAL,CAAA,EAAaD,CAAS,CAC3C,CAEJ,EAEaO,EAAiBA,IAAa,CACnCC,MAAAA,EAAUlB,EAAMmB,WAAWpB,CAAoB,EACrD,GAAImB,IAAYE,OACR,MAAA,IAAIC,MAAM,8CAA8C,EAEhE,OAAOH,EAAQJ,KACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuthenticatedKnockClient.js","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const stableOptions = useStableOptions(options);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","stableOptions","useStableOptions","useMemo","currentKnock","current","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":"qPAKA,SAASA,EACPC,EACAC,EACAC,EACAC,EAA+B,CAAA,EAC/B,CACMC,EAAAA,aAAaH,EAAQC,EAAW,CACpCG,oBAAqBF,GAAAA,YAAAA,EAASE,oBAC9BC,yBAA0BH,GAAAA,YAAAA,EAASG,wBAAAA,CACpC,CACH,CAKA,SAASC,EACPC,EACAP,EACAC,EACAC,EAA2C,CAAA,EAC3C,CACMM,MAAAA,EAAWC,UAAMC,
|
|
1
|
+
{"version":3,"file":"useAuthenticatedKnockClient.js","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const stableOptions = useStableOptions(options);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","stableOptions","useStableOptions","useMemo","currentKnock","current","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":"qPAKA,SAASA,EACPC,EACAC,EACAC,EACAC,EAA+B,CAAA,EAC/B,CACMC,EAAAA,aAAaH,EAAQC,EAAW,CACpCG,oBAAqBF,GAAAA,YAAAA,EAASE,oBAC9BC,yBAA0BH,GAAAA,YAAAA,EAASG,wBAAAA,CACpC,CACH,CAKA,SAASC,EACPC,EACAP,EACAC,EACAC,EAA2C,CAAA,EAC3C,CACMM,MAAAA,EAAWC,UAAMC,OAA0B,EAC3CC,EAAgBC,EAAiBV,CAAO,EAEvCO,OAAAA,EAAAA,QAAMI,QAAQ,IAAM,CACzB,MAAMC,EAAeN,EAASO,QAI5BD,GAAAA,GACAA,EAAaE,gBAAgB,IAC5BF,EAAad,SAAWA,GAAUc,EAAab,YAAcA,GAEtCa,OAAAA,EAAAA,EAAcd,EAAQC,EAAWU,CAAa,EAC/DG,EAGLA,GACFA,EAAaG,SAAS,EAIlBlB,MAAAA,EAAQ,IAAImB,EAAAA,QAAMX,EAAQ,CAC9BY,KAAMR,EAAcQ,KACpBC,SAAUT,EAAcS,QAAAA,CACzB,EAEuBrB,OAAAA,EAAAA,EAAOC,EAAQC,EAAWU,CAAa,EAC/DH,EAASO,QAAUhB,EAEZA,GACN,CAACQ,EAAQP,EAAQC,EAAWU,CAAa,CAAC,CAC/C"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const u=require("react"),n=require("zustand/shallow")
|
|
1
|
+
"use strict";const u=require("react"),n=require("zustand/shallow");function s(e){const t=u.useRef();return u.useMemo(()=>{const r=t.current;return r&&n.shallow(e,r)?r:(t.current=e,e)},[e])}module.exports=s;
|
|
2
2
|
//# sourceMappingURL=useStableOptions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStableOptions.js","sources":["../../../../../src/modules/core/hooks/useStableOptions.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport shallow from \"zustand/shallow\";\n\nexport default function useStableOptions<T>(options: T): T {\n const optionsRef = useRef<T>();\n\n return useMemo(() => {\n const currentOptions = optionsRef.current;\n\n if (currentOptions && shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n}\n"],"names":["useStableOptions","options","optionsRef","useRef","useMemo","currentOptions","current","shallow"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useStableOptions.js","sources":["../../../../../src/modules/core/hooks/useStableOptions.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { shallow } from \"zustand/shallow\";\n\nexport default function useStableOptions<T>(options: T): T {\n const optionsRef = useRef<T>();\n\n return useMemo(() => {\n const currentOptions = optionsRef.current;\n\n if (currentOptions && shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n}\n"],"names":["useStableOptions","options","optionsRef","useRef","useMemo","currentOptions","current","shallow"],"mappings":"mEAGA,SAAwBA,EAAoBC,EAAe,CACzD,MAAMC,EAAaC,EAAAA,OAAU,EAE7B,OAAOC,UAAQ,IAAM,CACnB,MAAMC,EAAiBH,EAAWI,QAElC,OAAID,GAAkBE,EAAAA,QAAQN,EAASI,CAAc,EAC5CA,GAGTH,EAAWI,QAAUL,EACdA,EAAAA,EACN,CAACA,CAAO,CAAC,CACd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import Knock, { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (_e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: Knock[\"userId\"],\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockMsTeamsProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockMsTeamsChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockMsTeamsChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","tenantId","connectionStatus","errorLabel","msTeamsProviderKey","knockMsTeamsChannelId"],"mappings":"4GAIO,SAASA,EAAiBC,EAAgC,CACxDA,OAAAA,EAAQ,EAAI,KAAOA,CAC5B,CAMO,SAASC,EACdC,EACAC,EAAkC,GAClC,CACI,GAAA,CACIC,MAAAA,EAAWC,WAASH,CAAE,EAKrBI,OAJWC,EAAAA,mBAAmBH,EAAU,IAAII,KAAQ,CACzDC,OAAQN,EAAQM,MAAAA,CACjB,OAGU,CACJP,OAAAA,
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import Knock, { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (_e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: Knock[\"userId\"],\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockMsTeamsProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockMsTeamsChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockMsTeamsChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","tenantId","connectionStatus","errorLabel","msTeamsProviderKey","knockMsTeamsChannelId"],"mappings":"4GAIO,SAASA,EAAiBC,EAAgC,CACxDA,OAAAA,EAAQ,EAAI,KAAOA,CAC5B,CAMO,SAASC,EACdC,EACAC,EAAkC,GAClC,CACI,GAAA,CACIC,MAAAA,EAAWC,WAASH,CAAE,EAKrBI,OAJWC,EAAAA,mBAAmBH,EAAU,IAAII,KAAQ,CACzDC,OAAQN,EAAQM,MAAAA,CACjB,OAGU,CACJP,OAAAA,CAAAA,CAEX,CAEO,SAASQ,EAAeC,EAAwB,CAC9CA,OAAAA,EAAOC,OAAO,CAAC,EAAEC,cAAgBF,EAAOG,MAAM,CAAC,CACxD,CAEgBC,SAAAA,EAAqBC,EAAiBC,EAAqB,CAClED,OAAAA,IAASE,OAAYF,EAAOC,CACrC,CAMO,SAASE,EACdC,EACAC,EACAlB,EAA6B,CAAA,EAC7B,CACO,MAAA,CACLiB,EACAC,EACAlB,EAAQmB,OACRnB,EAAQoB,OACRpB,EAAQqB,WACRrB,EAAQsB,QAAQ,EAEfC,UAAcC,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb,CAMO,SAASC,EAAiB,CAC/BC,oBAAAA,EACAC,SAAAA,EACAC,iBAAAA,EACAC,WAAAA,CAMF,EAAG,CACD,MAAO,CAACH,EAAqBC,EAAUC,EAAkBC,CAAU,EAChEP,OAAcC,GAAAA,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb,CAMO,SAASM,EAAmB,CACjCC,sBAAAA,EACAJ,SAAAA,EACAC,iBAAAA,EACAC,WAAAA,CAMF,EAAG,CACD,MAAO,CAACE,EAAuBJ,EAAUC,EAAkBC,CAAU,EAClEP,OAAcC,GAAAA,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockFeedProvider.js","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport { UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport { useCreateNotificationStore } from \"../hooks\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<FeedStoreState
|
|
1
|
+
{"version":3,"file":"KnockFeedProvider.js","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport type { StoreApi, UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport { useCreateNotificationStore } from \"../hooks\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<StoreApi<FeedStoreState>>;\n colorMode: ColorMode;\n}\n\nconst FeedStateContext = React.createContext<\n KnockFeedProviderState | undefined\n>(undefined);\n\nexport interface KnockFeedProviderProps {\n // Feed props\n feedId: string;\n\n // Extra options\n colorMode?: ColorMode;\n\n // Feed client options\n defaultFeedOptions?: FeedClientOptions;\n}\n\nexport const KnockFeedProvider: React.FC<\n PropsWithChildren<KnockFeedProviderProps>\n> = ({ feedId, children, defaultFeedOptions = {}, colorMode = \"light\" }) => {\n const knock = useKnockClient();\n const feedClient = useNotifications(knock, feedId, defaultFeedOptions);\n const useFeedStore = useCreateNotificationStore(feedClient);\n\n return (\n <FeedStateContext.Provider\n key={feedProviderKey(knock.userId, feedId, defaultFeedOptions)}\n value={{\n knock,\n feedClient,\n useFeedStore,\n colorMode,\n }}\n >\n {children}\n </FeedStateContext.Provider>\n );\n};\n\nexport const useKnockFeed = (): KnockFeedProviderState => {\n const context = React.useContext(FeedStateContext);\n\n if (!context) {\n throw new Error(\"useKnockFeed must be used within a KnockFeedProvider\");\n }\n\n return context;\n};\n"],"names":["FeedStateContext","React","createContext","undefined","KnockFeedProvider","feedId","children","defaultFeedOptions","colorMode","knock","useKnockClient","feedClient","useNotifications","useFeedStore","useCreateNotificationStore","feedProviderKey","userId","useKnockFeed","context","useContext","Error"],"mappings":"4pBAsBMA,EAAmBC,EAAMC,cAE7BC,MAAS,EAaEC,EAETA,CAAC,CAAEC,OAAAA,EAAQC,SAAAA,EAAUC,mBAAAA,EAAqB,CAAC,EAAGC,UAAAA,EAAY,OAAQ,IAAM,CAC1E,MAAMC,EAAQC,EAAAA,eAAe,EACvBC,EAAaC,EAAiBH,EAAOJ,EAAQE,CAAkB,EAC/DM,EAAeC,6BAA2BH,CAAU,EAGxD,OAAAV,EAAA,cAACD,EAAiB,SAAjB,CACC,IAAKe,kBAAgBN,EAAMO,OAAQX,EAAQE,CAAkB,EAC7D,MAAO,CACLE,MAAAA,EACAE,WAAAA,EACAE,aAAAA,EACAL,UAAAA,IAGDF,CACH,CAEJ,EAEaW,EAAeA,IAA8B,CAClDC,MAAAA,EAAUjB,EAAMkB,WAAWnB,CAAgB,EAEjD,GAAI,CAACkB,EACG,MAAA,IAAIE,MAAM,sDAAsD,EAGjEF,OAAAA,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFeedSettings.js","sources":["../../../../../src/modules/feed/hooks/useFeedSettings.ts"],"sourcesContent":["import { Feed } from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nexport type FeedSettings = {\n features: {\n branding_required: boolean;\n };\n};\n\nfunction useFeedSettings(feedClient: Feed): {\n settings: FeedSettings | null;\n loading: boolean;\n} {\n const [settings, setSettings] = useState(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // TODO: consider moving this into the feed client and into the feed store state when\n // we're using this in other areas of the feed\n useEffect(() => {\n async function getSettings() {\n const knock = feedClient.knock;\n const apiClient = knock.client();\n const feedSettingsPath = `/v1/users/${knock.userId}/feeds/${feedClient.feedId}/settings`;\n setIsLoading(true);\n\n const response = await apiClient.makeRequest({\n method: \"GET\",\n url: feedSettingsPath,\n });\n\n if (!response.error) {\n setSettings(response.body);\n }\n\n setIsLoading(false);\n }\n\n getSettings();\n // TODO: Check if we can remove this disable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { settings, loading: isLoading };\n}\n\nexport default useFeedSettings;\n"],"names":["useFeedSettings","feedClient","settings","setSettings","useState","isLoading","setIsLoading","useEffect","getSettings","knock","apiClient","client","feedSettingsPath","userId","feedId","response","makeRequest","method","url","error","body","loading"],"mappings":"sCASA,SAASA,EAAgBC,EAGvB,CACA,KAAM,CAACC,EAAUC,CAAW,EAAIC,
|
|
1
|
+
{"version":3,"file":"useFeedSettings.js","sources":["../../../../../src/modules/feed/hooks/useFeedSettings.ts"],"sourcesContent":["import { Feed } from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nexport type FeedSettings = {\n features: {\n branding_required: boolean;\n };\n};\n\nfunction useFeedSettings(feedClient: Feed): {\n settings: FeedSettings | null;\n loading: boolean;\n} {\n const [settings, setSettings] = useState(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // TODO: consider moving this into the feed client and into the feed store state when\n // we're using this in other areas of the feed\n useEffect(() => {\n async function getSettings() {\n const knock = feedClient.knock;\n const apiClient = knock.client();\n const feedSettingsPath = `/v1/users/${knock.userId}/feeds/${feedClient.feedId}/settings`;\n setIsLoading(true);\n\n const response = await apiClient.makeRequest({\n method: \"GET\",\n url: feedSettingsPath,\n });\n\n if (!response.error) {\n setSettings(response.body);\n }\n\n setIsLoading(false);\n }\n\n getSettings();\n // TODO: Check if we can remove this disable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { settings, loading: isLoading };\n}\n\nexport default useFeedSettings;\n"],"names":["useFeedSettings","feedClient","settings","setSettings","useState","isLoading","setIsLoading","useEffect","getSettings","knock","apiClient","client","feedSettingsPath","userId","feedId","response","makeRequest","method","url","error","body","loading"],"mappings":"sCASA,SAASA,EAAgBC,EAGvB,CACA,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,IAAI,EACvC,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAIhDG,OAAAA,EAAAA,UAAU,IAAM,CACd,eAAeC,GAAc,CAC3B,MAAMC,EAAQR,EAAWQ,MACnBC,EAAYD,EAAME,OAAO,EACzBC,EAAmB,aAAaH,EAAMI,MAAM,UAAUZ,EAAWa,MAAM,YAC7ER,EAAa,EAAI,EAEXS,MAAAA,EAAW,MAAML,EAAUM,YAAY,CAC3CC,OAAQ,MACRC,IAAKN,CAAAA,CACN,EAEIG,EAASI,OACZhB,EAAYY,EAASK,IAAI,EAG3Bd,EAAa,EAAK,CAAA,CAGRE,EAAA,CAGd,EAAG,EAAE,EAEE,CAAEN,SAAAA,EAAUmB,QAAShB,CAAU,CACxC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=require("zustand");function n(e,t){const o=i.useStore(e.store);return u=>{const r=u??t;return r?r(o):o}}function s(e,t){return n(e,t)}exports.default=s;exports.useCreateNotificationStore=n;
|
|
2
2
|
//# sourceMappingURL=useNotificationStore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNotificationStore.js","sources":["../../../../../src/modules/feed/hooks/useNotificationStore.ts"],"sourcesContent":["import { Feed, FeedStoreState } from \"@knocklabs/client\";\nimport
|
|
1
|
+
{"version":3,"file":"useNotificationStore.js","sources":["../../../../../src/modules/feed/hooks/useNotificationStore.ts"],"sourcesContent":["import { Feed, type FeedStoreState } from \"@knocklabs/client\";\nimport { type StoreApi, type UseBoundStore, useStore } from \"zustand\";\n\n// A hook designed to create a `UseBoundStore` instance.\n// https://zustand.docs.pmnd.rs/guides/typescript#bounded-usestore-hook-for-vanilla-stores\nfunction useCreateNotificationStore(\n feedClient: Feed,\n): UseBoundStore<StoreApi<FeedStoreState>>;\nfunction useCreateNotificationStore<T, U = T>(\n feedClient: Feed,\n externalSelector: (state: FeedStoreState) => U,\n): U;\n/**\n * Access a Bounded Store instance\n * Allow passing a selector down from useCreateNotificationStore OR useNotificationStore\n * We'll favor the the one passed later outside of useCreateNotificationStore instantiation\n */\nfunction useCreateNotificationStore<T, U = T>(\n feedClient: Feed,\n externalSelector?: (state: FeedStoreState) => U,\n) {\n const store = useStore(feedClient.store);\n\n return (selector?: (state: FeedStoreState) => U) => {\n const innerSelector = selector ?? externalSelector;\n return innerSelector ? innerSelector(store) : store;\n };\n}\n\n/**\n * A hook used to access content within the notification store.\n *\n * A selector can be used to access a subset of the store state.\n *\n * @example\n *\n * ```ts\n * const { items, metadata } = useNotificationStore(feedClient, (state) => ({\n * items: state.items,\n * metadata: state.metadata,\n * }));\n * ```\n */\nfunction useNotificationStore(\n feedClient: Feed,\n): UseBoundStore<StoreApi<FeedStoreState>>;\nfunction useNotificationStore<T>(\n feedClient: Feed,\n selector: (state: FeedStoreState) => T,\n): T;\nfunction useNotificationStore<T, U = T>(\n feedClient: Feed,\n selector?: (state: FeedStoreState) => U,\n) {\n return useCreateNotificationStore(feedClient, selector!);\n}\n\nexport { useCreateNotificationStore };\nexport default useNotificationStore;\n"],"names":["useCreateNotificationStore","feedClient","externalSelector","store","useStore","selector","innerSelector","useNotificationStore"],"mappings":"uIAiBA,SAASA,EACPC,EACAC,EACA,CACMC,MAAAA,EAAQC,EAAAA,SAASH,EAAWE,KAAK,EAEvC,OAAQE,GAA4C,CAClD,MAAMC,EAAgBD,GAAYH,EAC3BI,OAAAA,EAAgBA,EAAcH,CAAK,EAAIA,CAChD,CACF,CAuBA,SAASI,EACPN,EACAI,EACA,CACOL,OAAAA,EAA2BC,EAAYI,CAAS,CACzD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNotifications.js","sources":["../../../../../src/modules/feed/hooks/useNotifications.ts"],"sourcesContent":["import Knock, { Feed, FeedClientOptions } from \"@knocklabs/client\";\nimport { useMemo, useRef } from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction useNotifications(\n knock: Knock,\n feedChannelId: string,\n options: FeedClientOptions = {},\n) {\n const feedClientRef = useRef<Feed>();\n const stableOptions = useStableOptions(options);\n\n return useMemo(() => {\n if (feedClientRef.current) {\n feedClientRef.current.dispose();\n }\n\n feedClientRef.current = knock.feeds.initialize(\n feedChannelId,\n stableOptions,\n );\n\n // In development, we need to introduce this extra set state to force a render\n // for Zustand as otherwise the state doesn't get reflected correctly\n feedClientRef.current.store.subscribe((t) =>\n feedClientRef?.current?.store.setState(t),\n );\n\n feedClientRef.current.listenForUpdates();\n\n return feedClientRef.current;\n }, [knock, feedChannelId, stableOptions]);\n}\n\nexport default useNotifications;\n"],"names":["useNotifications","knock","feedChannelId","options","feedClientRef","useRef","stableOptions","useStableOptions","useMemo","current","dispose","feeds","initialize","store","subscribe","t","setState","listenForUpdates"],"mappings":"8LAKA,SAASA,EACPC,EACAC,EACAC,EAA6B,CAAA,EAC7B,CACA,MAAMC,EAAgBC,EAAAA,
|
|
1
|
+
{"version":3,"file":"useNotifications.js","sources":["../../../../../src/modules/feed/hooks/useNotifications.ts"],"sourcesContent":["import Knock, { Feed, FeedClientOptions } from \"@knocklabs/client\";\nimport { useMemo, useRef } from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction useNotifications(\n knock: Knock,\n feedChannelId: string,\n options: FeedClientOptions = {},\n) {\n const feedClientRef = useRef<Feed>();\n const stableOptions = useStableOptions(options);\n\n return useMemo(() => {\n if (feedClientRef.current) {\n feedClientRef.current.dispose();\n }\n\n feedClientRef.current = knock.feeds.initialize(\n feedChannelId,\n stableOptions,\n );\n\n // In development, we need to introduce this extra set state to force a render\n // for Zustand as otherwise the state doesn't get reflected correctly\n feedClientRef.current.store.subscribe((t) =>\n feedClientRef?.current?.store.setState(t),\n );\n\n feedClientRef.current.listenForUpdates();\n\n return feedClientRef.current;\n }, [knock, feedChannelId, stableOptions]);\n}\n\nexport default useNotifications;\n"],"names":["useNotifications","knock","feedChannelId","options","feedClientRef","useRef","stableOptions","useStableOptions","useMemo","current","dispose","feeds","initialize","store","subscribe","t","setState","listenForUpdates"],"mappings":"8LAKA,SAASA,EACPC,EACAC,EACAC,EAA6B,CAAA,EAC7B,CACA,MAAMC,EAAgBC,EAAAA,OAAa,EAC7BC,EAAgBC,EAAiBJ,CAAO,EAE9C,OAAOK,UAAQ,KACTJ,EAAcK,SAChBL,EAAcK,QAAQC,QAAQ,EAGhCN,EAAcK,QAAUR,EAAMU,MAAMC,WAClCV,EACAI,CACF,EAIcG,EAAAA,QAAQI,MAAMC,UAAWC,UACrCX,OAAAA,EAAAA,GAAAA,YAAAA,EAAeK,UAAfL,YAAAA,EAAwBS,MAAMG,SAASD,GACzC,EAEAX,EAAcK,QAAQQ,iBAAiB,EAEhCb,EAAcK,SACpB,CAACR,EAAOC,EAAeI,CAAa,CAAC,CAC1C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockI18nProvider.js","sources":["../../../../../src/modules/i18n/context/KnockI18nProvider.tsx"],"sourcesContent":["import React from \"react\";\nimport { FunctionComponent, PropsWithChildren } from \"react\";\n\nimport { I18nContent, locales } from \"../languages\";\n\nexport const I18nContext = React.createContext<I18nContent>(locales.en);\n\nexport interface KnockI18nProviderProps {\n i18n?: I18nContent;\n}\n\nexport const KnockI18nProvider: FunctionComponent<\n PropsWithChildren<KnockI18nProviderProps>\n> = ({ i18n = locales.en, ...props }) => {\n return <I18nContext.Provider {...props} value={i18n} />;\n};\n"],"names":["I18nContext","React","createContext","locales","en","KnockI18nProvider","i18n","props"],"mappings":"2MAKaA,EAAcC,EAAAA,QAAMC,cAA2BC,EAAAA,QAAQC,EAAE,EAMzDC,EAETA,CAAC,CAAEC,KAAAA,EAAOH,EAAQC,QAAAA,GAAI,GAAGG,CAAM,4BACzBP,EAAY,SAAZ,CAAyBO,GAAAA,EAAO,MAAOD,
|
|
1
|
+
{"version":3,"file":"KnockI18nProvider.js","sources":["../../../../../src/modules/i18n/context/KnockI18nProvider.tsx"],"sourcesContent":["import React from \"react\";\nimport { FunctionComponent, PropsWithChildren } from \"react\";\n\nimport { I18nContent, locales } from \"../languages\";\n\nexport const I18nContext = React.createContext<I18nContent>(locales.en);\n\nexport interface KnockI18nProviderProps {\n i18n?: I18nContent;\n}\n\nexport const KnockI18nProvider: FunctionComponent<\n PropsWithChildren<KnockI18nProviderProps>\n> = ({ i18n = locales.en, ...props }) => {\n return <I18nContext.Provider {...props} value={i18n} />;\n};\n"],"names":["I18nContext","React","createContext","locales","en","KnockI18nProvider","i18n","props"],"mappings":"2MAKaA,EAAcC,EAAAA,QAAMC,cAA2BC,EAAAA,QAAQC,EAAE,EAMzDC,EAETA,CAAC,CAAEC,KAAAA,EAAOH,EAAQC,QAAAA,GAAI,GAAGG,CAAM,4BACzBP,EAAY,SAAZ,CAAyBO,GAAAA,EAAO,MAAOD,EAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTranslations.js","sources":["../../../../../src/modules/i18n/hooks/useTranslations.ts"],"sourcesContent":["import { useContext } from \"react\";\n\nimport { I18nContext } from \"../context/KnockI18nProvider\";\nimport { I18nContent, locales } from \"../languages\";\n\nexport function useTranslations() {\n const { translations, locale } = useContext<I18nContent>(I18nContext);\n\n return {\n locale,\n t: (key: keyof typeof translations) => {\n // We always use english as the default translation when a key doesn't exist\n return translations[key] || locales.en.translations[key];\n },\n };\n}\n"],"names":["useTranslations","translations","locale","useContext","I18nContext","t","key","locales","en"],"mappings":"yLAKO,SAASA,GAAkB,CAC1B,KAAA,CAAEC,aAAAA,EAAcC,OAAAA,CAAAA,EAAWC,EAAAA,WAAwBC,EAAAA,WAAW,EAE7D,MAAA,CACLF,OAAAA,EACAG,EAAIC,GAEKL,EAAaK,CAAG,GAAKC,
|
|
1
|
+
{"version":3,"file":"useTranslations.js","sources":["../../../../../src/modules/i18n/hooks/useTranslations.ts"],"sourcesContent":["import { useContext } from \"react\";\n\nimport { I18nContext } from \"../context/KnockI18nProvider\";\nimport { I18nContent, locales } from \"../languages\";\n\nexport function useTranslations() {\n const { translations, locale } = useContext<I18nContent>(I18nContext);\n\n return {\n locale,\n t: (key: keyof typeof translations) => {\n // We always use english as the default translation when a key doesn't exist\n return translations[key] || locales.en.translations[key];\n },\n };\n}\n"],"names":["useTranslations","translations","locale","useContext","I18nContext","t","key","locales","en"],"mappings":"yLAKO,SAASA,GAAkB,CAC1B,KAAA,CAAEC,aAAAA,EAAcC,OAAAA,CAAAA,EAAWC,EAAAA,WAAwBC,EAAAA,WAAW,EAE7D,MAAA,CACLF,OAAAA,EACAG,EAAIC,GAEKL,EAAaK,CAAG,GAAKC,EAAQC,QAAAA,GAAGP,aAAaK,CAAG,CAE3D,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockMsTeamsProvider.js","sources":["../../../../../src/modules/ms-teams/context/KnockMsTeamsProvider.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\nimport { msTeamsProviderKey } from \"../../core/utils\";\nimport { useMsTeamsConnectionStatus } from \"../hooks\";\nimport { ConnectionStatus } from \"../hooks/useMsTeamsConnectionStatus\";\n\nexport interface KnockMsTeamsProviderState {\n knockMsTeamsChannelId: string;\n tenantId: 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}\n\nconst MsTeamsProviderStateContext =\n React.createContext<KnockMsTeamsProviderState | null>(null);\n\nexport interface KnockMsTeamsProviderProps {\n knockMsTeamsChannelId: string;\n tenantId: string;\n}\n\nexport const KnockMsTeamsProvider: React.FC<\n PropsWithChildren<KnockMsTeamsProviderProps>\n> = ({ knockMsTeamsChannelId, tenantId, children }) => {\n const knock = useKnockClient();\n\n const {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n } = useMsTeamsConnectionStatus(knock, knockMsTeamsChannelId, tenantId);\n\n return (\n <MsTeamsProviderStateContext.Provider\n key={msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n })}\n value={{\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n knockMsTeamsChannelId,\n tenantId,\n }}\n >\n {children}\n </MsTeamsProviderStateContext.Provider>\n );\n};\n\nexport const useKnockMsTeamsClient = (): KnockMsTeamsProviderState => {\n const context = React.useContext(MsTeamsProviderStateContext);\n if (!context) {\n throw new Error(\n \"useKnockMsTeamsClient must be used within a KnockMsTeamsProvider\",\n );\n }\n return context;\n};\n"],"names":["MsTeamsProviderStateContext","React","createContext","KnockMsTeamsProvider","knockMsTeamsChannelId","tenantId","children","knock","useKnockClient","connectionStatus","setConnectionStatus","errorLabel","setErrorLabel","actionLabel","setActionLabel","useMsTeamsConnectionStatus","msTeamsProviderKey","useKnockMsTeamsClient","context","useContext","Error"],"mappings":"ktBAmBMA,EACJC,EAAMC,cAAgD,IAAI,EAO/CC,EAETA,CAAC,CAAEC,sBAAAA,EAAuBC,SAAAA,EAAUC,SAAAA,CAAS,IAAM,CACrD,MAAMC,EAAQC,EAAAA,
|
|
1
|
+
{"version":3,"file":"KnockMsTeamsProvider.js","sources":["../../../../../src/modules/ms-teams/context/KnockMsTeamsProvider.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\nimport { msTeamsProviderKey } from \"../../core/utils\";\nimport { useMsTeamsConnectionStatus } from \"../hooks\";\nimport { ConnectionStatus } from \"../hooks/useMsTeamsConnectionStatus\";\n\nexport interface KnockMsTeamsProviderState {\n knockMsTeamsChannelId: string;\n tenantId: 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}\n\nconst MsTeamsProviderStateContext =\n React.createContext<KnockMsTeamsProviderState | null>(null);\n\nexport interface KnockMsTeamsProviderProps {\n knockMsTeamsChannelId: string;\n tenantId: string;\n}\n\nexport const KnockMsTeamsProvider: React.FC<\n PropsWithChildren<KnockMsTeamsProviderProps>\n> = ({ knockMsTeamsChannelId, tenantId, children }) => {\n const knock = useKnockClient();\n\n const {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n } = useMsTeamsConnectionStatus(knock, knockMsTeamsChannelId, tenantId);\n\n return (\n <MsTeamsProviderStateContext.Provider\n key={msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n })}\n value={{\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n knockMsTeamsChannelId,\n tenantId,\n }}\n >\n {children}\n </MsTeamsProviderStateContext.Provider>\n );\n};\n\nexport const useKnockMsTeamsClient = (): KnockMsTeamsProviderState => {\n const context = React.useContext(MsTeamsProviderStateContext);\n if (!context) {\n throw new Error(\n \"useKnockMsTeamsClient must be used within a KnockMsTeamsProvider\",\n );\n }\n return context;\n};\n"],"names":["MsTeamsProviderStateContext","React","createContext","KnockMsTeamsProvider","knockMsTeamsChannelId","tenantId","children","knock","useKnockClient","connectionStatus","setConnectionStatus","errorLabel","setErrorLabel","actionLabel","setActionLabel","useMsTeamsConnectionStatus","msTeamsProviderKey","useKnockMsTeamsClient","context","useContext","Error"],"mappings":"ktBAmBMA,EACJC,EAAMC,cAAgD,IAAI,EAO/CC,EAETA,CAAC,CAAEC,sBAAAA,EAAuBC,SAAAA,EAAUC,SAAAA,CAAS,IAAM,CACrD,MAAMC,EAAQC,EAAAA,eAAe,EAEvB,CACJC,iBAAAA,EACAC,oBAAAA,EACAC,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,CACEC,EAAAA,EAA2BR,EAAOH,EAAuBC,CAAQ,EAErE,OACGJ,EAAA,cAAAD,EAA4B,SAA5B,CACC,IAAKgB,qBAAmB,CACtBZ,sBAAAA,EACAC,SAAAA,EACAI,iBAAAA,EACAE,WAAAA,CACD,CAAA,EACD,MAAO,CACLF,iBAAAA,EACAC,oBAAAA,EACAC,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,EACAV,sBAAAA,EACAC,SAAAA,IAGDC,CACH,CAEJ,EAEaW,EAAwBA,IAAiC,CAC9DC,MAAAA,EAAUjB,EAAMkB,WAAWnB,CAA2B,EAC5D,GAAI,CAACkB,EACG,MAAA,IAAIE,MACR,kEACF,EAEKF,OAAAA,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConnectedMsTeamsChannels.js","sources":["../../../../../src/modules/ms-teams/hooks/useConnectedMsTeamsChannels.ts"],"sourcesContent":["import { useKnockMsTeamsClient } from \"..\";\nimport { MsTeamsChannelConnection } from \"@knocklabs/client\";\nimport { GenericData } from \"@knocklabs/types\";\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\n\nimport { RecipientObject } from \"../../..\";\nimport { useKnockClient } from \"../../core\";\nimport { useTranslations } from \"../../i18n\";\n\nconst QUERY_KEY = \"MS_TEAMS_CONNECTED_CHANNELS\";\n\ntype UseConnectedMsTeamsChannelsProps = {\n msTeamsChannelsRecipientObject: RecipientObject;\n};\n\ntype UseConnectedMsTeamsChannelsOutput = {\n data: MsTeamsChannelConnection[] | null;\n updateConnectedChannels: (\n connectedChannels: MsTeamsChannelConnection[],\n ) => Promise<void>;\n loading: boolean;\n error: string | null;\n updating: boolean;\n};\n\nfunction useConnectedMsTeamsChannels({\n msTeamsChannelsRecipientObject: { objectId, collection },\n}: UseConnectedMsTeamsChannelsProps): UseConnectedMsTeamsChannelsOutput {\n const { t } = useTranslations();\n const knock = useKnockClient();\n const { connectionStatus, knockMsTeamsChannelId } = useKnockMsTeamsClient();\n\n const [error, setError] = useState<string | null>(null);\n const [isUpdating, setIsUpdating] = useState(false);\n\n const {\n data: connectedChannels,\n mutate,\n isValidating,\n isLoading,\n } = useSWR<MsTeamsChannelConnection[]>(\n // Only fetch when Microsoft Teams is connected\n connectionStatus === \"connected\"\n ? [QUERY_KEY, knockMsTeamsChannelId, collection, objectId]\n : null,\n async () => {\n return knock.objects\n .getChannelData({\n collection,\n objectId,\n channelId: knockMsTeamsChannelId,\n })\n .then((res) => res.data?.connections ?? [])\n .catch(() => []);\n },\n {\n onSuccess: () => {\n setError(null);\n },\n },\n );\n\n const updateConnectedChannels = async (\n channelsToSendToKnock: MsTeamsChannelConnection[],\n ) => {\n setIsUpdating(true);\n try {\n await mutate(\n () =>\n knock.objects\n .setChannelData({\n objectId,\n collection,\n channelId: knockMsTeamsChannelId,\n data: { connections: channelsToSendToKnock },\n })\n .then((res) => (res as GenericData).data?.connections ?? []),\n {\n populateCache: true,\n revalidate: false,\n optimisticData: channelsToSendToKnock,\n },\n );\n } catch (_error) {\n setError(t(\"msTeamsChannelSetError\") || \"\");\n }\n setIsUpdating(false);\n };\n\n return {\n data: connectedChannels ?? null,\n updateConnectedChannels,\n updating: isUpdating,\n loading: isLoading || isValidating,\n error,\n };\n}\n\nexport default useConnectedMsTeamsChannels;\n"],"names":["QUERY_KEY","useConnectedMsTeamsChannels","msTeamsChannelsRecipientObject","objectId","collection","t","useTranslations","knock","useKnockClient","connectionStatus","knockMsTeamsChannelId","useKnockMsTeamsClient","error","setError","useState","isUpdating","setIsUpdating","data","connectedChannels","mutate","isValidating","isLoading","useSWR","objects","getChannelData","channelId","then","res","connections","catch","onSuccess","updateConnectedChannels","channelsToSendToKnock","setChannelData","populateCache","revalidate","optimisticData","updating","loading"],"mappings":"ibAUMA,EAAY,8BAgBlB,SAASC,EAA4B,CACnCC,+BAAgC,CAAEC,SAAAA,EAAUC,WAAAA,
|
|
1
|
+
{"version":3,"file":"useConnectedMsTeamsChannels.js","sources":["../../../../../src/modules/ms-teams/hooks/useConnectedMsTeamsChannels.ts"],"sourcesContent":["import { useKnockMsTeamsClient } from \"..\";\nimport { MsTeamsChannelConnection } from \"@knocklabs/client\";\nimport { GenericData } from \"@knocklabs/types\";\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\n\nimport { RecipientObject } from \"../../..\";\nimport { useKnockClient } from \"../../core\";\nimport { useTranslations } from \"../../i18n\";\n\nconst QUERY_KEY = \"MS_TEAMS_CONNECTED_CHANNELS\";\n\ntype UseConnectedMsTeamsChannelsProps = {\n msTeamsChannelsRecipientObject: RecipientObject;\n};\n\ntype UseConnectedMsTeamsChannelsOutput = {\n data: MsTeamsChannelConnection[] | null;\n updateConnectedChannels: (\n connectedChannels: MsTeamsChannelConnection[],\n ) => Promise<void>;\n loading: boolean;\n error: string | null;\n updating: boolean;\n};\n\nfunction useConnectedMsTeamsChannels({\n msTeamsChannelsRecipientObject: { objectId, collection },\n}: UseConnectedMsTeamsChannelsProps): UseConnectedMsTeamsChannelsOutput {\n const { t } = useTranslations();\n const knock = useKnockClient();\n const { connectionStatus, knockMsTeamsChannelId } = useKnockMsTeamsClient();\n\n const [error, setError] = useState<string | null>(null);\n const [isUpdating, setIsUpdating] = useState(false);\n\n const {\n data: connectedChannels,\n mutate,\n isValidating,\n isLoading,\n } = useSWR<MsTeamsChannelConnection[]>(\n // Only fetch when Microsoft Teams is connected\n connectionStatus === \"connected\"\n ? [QUERY_KEY, knockMsTeamsChannelId, collection, objectId]\n : null,\n async () => {\n return knock.objects\n .getChannelData({\n collection,\n objectId,\n channelId: knockMsTeamsChannelId,\n })\n .then((res) => res.data?.connections ?? [])\n .catch(() => []);\n },\n {\n onSuccess: () => {\n setError(null);\n },\n },\n );\n\n const updateConnectedChannels = async (\n channelsToSendToKnock: MsTeamsChannelConnection[],\n ) => {\n setIsUpdating(true);\n try {\n await mutate(\n () =>\n knock.objects\n .setChannelData({\n objectId,\n collection,\n channelId: knockMsTeamsChannelId,\n data: { connections: channelsToSendToKnock },\n })\n .then((res) => (res as GenericData).data?.connections ?? []),\n {\n populateCache: true,\n revalidate: false,\n optimisticData: channelsToSendToKnock,\n },\n );\n } catch (_error) {\n setError(t(\"msTeamsChannelSetError\") || \"\");\n }\n setIsUpdating(false);\n };\n\n return {\n data: connectedChannels ?? null,\n updateConnectedChannels,\n updating: isUpdating,\n loading: isLoading || isValidating,\n error,\n };\n}\n\nexport default useConnectedMsTeamsChannels;\n"],"names":["QUERY_KEY","useConnectedMsTeamsChannels","msTeamsChannelsRecipientObject","objectId","collection","t","useTranslations","knock","useKnockClient","connectionStatus","knockMsTeamsChannelId","useKnockMsTeamsClient","error","setError","useState","isUpdating","setIsUpdating","data","connectedChannels","mutate","isValidating","isLoading","useSWR","objects","getChannelData","channelId","then","res","connections","catch","onSuccess","updateConnectedChannels","channelsToSendToKnock","setChannelData","populateCache","revalidate","optimisticData","updating","loading"],"mappings":"ibAUMA,EAAY,8BAgBlB,SAASC,EAA4B,CACnCC,+BAAgC,CAAEC,SAAAA,EAAUC,WAAAA,CAAAA,CACZ,EAAsC,CAChE,KAAA,CAAEC,EAAAA,GAAMC,kBAAgB,EACxBC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,iBAAAA,EAAkBC,sBAAAA,GAA0BC,wBAAsB,EAEpE,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAwB,IAAI,EAChD,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAS,EAAK,EAE5C,CACJG,KAAMC,EACNC,OAAAA,EACAC,aAAAA,EACAC,UAAAA,CAAAA,EACEC,EAAAA,QAEFb,IAAqB,YACjB,CAACT,EAAWU,EAAuBN,EAAYD,CAAQ,EACvD,KACJ,SACSI,EAAMgB,QACVC,eAAe,CACdpB,WAAAA,EACAD,SAAAA,EACAsB,UAAWf,CACZ,CAAA,EACAgB,KAAMC,GAAAA,OAAQA,QAAAA,EAAAA,EAAIV,OAAJU,YAAAA,EAAUC,cAAe,GAAE,EACzCC,MAAM,IAAM,EAAE,EAEnB,CACEC,UAAWA,IAAM,CACfjB,EAAS,IAAI,CAAA,CACf,CAEJ,EA6BO,MAAA,CACLI,KAAMC,GAAqB,KAC3Ba,wBA7B8B,MAC9BC,GACG,CACHhB,EAAc,EAAI,EACd,GAAA,CACF,MAAMG,EACJ,IACEZ,EAAMgB,QACHU,eAAe,CACd9B,SAAAA,EACAC,WAAAA,EACAqB,UAAWf,EACXO,KAAM,CAAEW,YAAaI,CAAAA,CAAsB,CAC5C,EACAN,KAAMC,GAAAA,OAASA,QAAAA,EAAAA,EAAoBV,OAApBU,YAAAA,EAA0BC,cAAe,CAAA,EAAE,EAC/D,CACEM,cAAe,GACfC,WAAY,GACZC,eAAgBJ,CAAAA,CAEpB,OACe,CACN3B,EAAAA,EAAE,wBAAwB,GAAK,EAAE,CAAA,CAE5CW,EAAc,EAAK,CACrB,EAKEqB,SAAUtB,EACVuB,QAASjB,GAAaD,EACtBR,MAAAA,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsTeamsAuth.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsAuth.ts"],"sourcesContent":["import { useKnockMsTeamsClient } from \"..\";\nimport { TENANT_OBJECT_COLLECTION } from \"@knocklabs/client\";\nimport { useCallback, useMemo } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst MS_TEAMS_ADMINCONSENT_URL =\n \"https://login.microsoftonline.com/organizations/adminconsent\";\n\nconst AUTH_REDIRECT_PATH = \"/providers/ms-teams/authenticate\";\n\ninterface UseMsTeamsAuthOutput {\n buildMsTeamsAuthUrl: () => string;\n disconnectFromMsTeams: () => void;\n}\n\nfunction useMsTeamsAuth(\n msTeamsBotId: string,\n redirectUrl?: string,\n): UseMsTeamsAuthOutput {\n const knock = useKnockClient();\n const {\n setConnectionStatus,\n knockMsTeamsChannelId,\n tenantId,\n setActionLabel,\n } = useKnockMsTeamsClient();\n\n const authRedirectUri = useMemo(\n () => knock.host + AUTH_REDIRECT_PATH,\n [knock.host],\n );\n\n const buildMsTeamsAuthUrl = useCallback(() => {\n const rawParams = {\n state: JSON.stringify({\n redirect_url: redirectUrl,\n ms_teams_tenant_object: {\n object_id: tenantId,\n collection: TENANT_OBJECT_COLLECTION,\n },\n channel_id: knockMsTeamsChannelId,\n public_key: knock.apiKey,\n user_token: knock.userToken,\n }),\n client_id: msTeamsBotId,\n redirect_uri: authRedirectUri,\n };\n return `${MS_TEAMS_ADMINCONSENT_URL}?${new URLSearchParams(rawParams)}`;\n }, [\n redirectUrl,\n tenantId,\n knockMsTeamsChannelId,\n knock.apiKey,\n knock.userToken,\n msTeamsBotId,\n authRedirectUri,\n ]);\n\n const disconnectFromMsTeams = useCallback(async () => {\n setActionLabel(null);\n setConnectionStatus(\"disconnecting\");\n try {\n const revokeResult = await knock.msTeams.revokeAccessToken({\n tenant: tenantId,\n knockChannelId: knockMsTeamsChannelId,\n });\n\n setConnectionStatus(revokeResult === \"ok\" ? \"disconnected\" : \"error\");\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n }, [\n setConnectionStatus,\n knock.msTeams,\n tenantId,\n knockMsTeamsChannelId,\n setActionLabel,\n ]);\n\n return { buildMsTeamsAuthUrl, disconnectFromMsTeams };\n}\n\nexport default useMsTeamsAuth;\n"],"names":["MS_TEAMS_ADMINCONSENT_URL","AUTH_REDIRECT_PATH","useMsTeamsAuth","msTeamsBotId","redirectUrl","knock","useKnockClient","setConnectionStatus","knockMsTeamsChannelId","tenantId","setActionLabel","useKnockMsTeamsClient","authRedirectUri","useMemo","host","buildMsTeamsAuthUrl","useCallback","rawParams","state","JSON","stringify","redirect_url","ms_teams_tenant_object","object_id","collection","TENANT_OBJECT_COLLECTION","channel_id","public_key","apiKey","user_token","userToken","client_id","redirect_uri","URLSearchParams","disconnectFromMsTeams","revokeResult","msTeams","revokeAccessToken","tenant","knockChannelId"],"mappings":"qTAMA,MAAMA,EACJ,+DAEIC,EAAqB,mCAO3B,SAASC,EACPC,EACAC,EACsB,CACtB,MAAMC,EAAQC,EAAAA,
|
|
1
|
+
{"version":3,"file":"useMsTeamsAuth.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsAuth.ts"],"sourcesContent":["import { useKnockMsTeamsClient } from \"..\";\nimport { TENANT_OBJECT_COLLECTION } from \"@knocklabs/client\";\nimport { useCallback, useMemo } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst MS_TEAMS_ADMINCONSENT_URL =\n \"https://login.microsoftonline.com/organizations/adminconsent\";\n\nconst AUTH_REDIRECT_PATH = \"/providers/ms-teams/authenticate\";\n\ninterface UseMsTeamsAuthOutput {\n buildMsTeamsAuthUrl: () => string;\n disconnectFromMsTeams: () => void;\n}\n\nfunction useMsTeamsAuth(\n msTeamsBotId: string,\n redirectUrl?: string,\n): UseMsTeamsAuthOutput {\n const knock = useKnockClient();\n const {\n setConnectionStatus,\n knockMsTeamsChannelId,\n tenantId,\n setActionLabel,\n } = useKnockMsTeamsClient();\n\n const authRedirectUri = useMemo(\n () => knock.host + AUTH_REDIRECT_PATH,\n [knock.host],\n );\n\n const buildMsTeamsAuthUrl = useCallback(() => {\n const rawParams = {\n state: JSON.stringify({\n redirect_url: redirectUrl,\n ms_teams_tenant_object: {\n object_id: tenantId,\n collection: TENANT_OBJECT_COLLECTION,\n },\n channel_id: knockMsTeamsChannelId,\n public_key: knock.apiKey,\n user_token: knock.userToken,\n }),\n client_id: msTeamsBotId,\n redirect_uri: authRedirectUri,\n };\n return `${MS_TEAMS_ADMINCONSENT_URL}?${new URLSearchParams(rawParams)}`;\n }, [\n redirectUrl,\n tenantId,\n knockMsTeamsChannelId,\n knock.apiKey,\n knock.userToken,\n msTeamsBotId,\n authRedirectUri,\n ]);\n\n const disconnectFromMsTeams = useCallback(async () => {\n setActionLabel(null);\n setConnectionStatus(\"disconnecting\");\n try {\n const revokeResult = await knock.msTeams.revokeAccessToken({\n tenant: tenantId,\n knockChannelId: knockMsTeamsChannelId,\n });\n\n setConnectionStatus(revokeResult === \"ok\" ? \"disconnected\" : \"error\");\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n }, [\n setConnectionStatus,\n knock.msTeams,\n tenantId,\n knockMsTeamsChannelId,\n setActionLabel,\n ]);\n\n return { buildMsTeamsAuthUrl, disconnectFromMsTeams };\n}\n\nexport default useMsTeamsAuth;\n"],"names":["MS_TEAMS_ADMINCONSENT_URL","AUTH_REDIRECT_PATH","useMsTeamsAuth","msTeamsBotId","redirectUrl","knock","useKnockClient","setConnectionStatus","knockMsTeamsChannelId","tenantId","setActionLabel","useKnockMsTeamsClient","authRedirectUri","useMemo","host","buildMsTeamsAuthUrl","useCallback","rawParams","state","JSON","stringify","redirect_url","ms_teams_tenant_object","object_id","collection","TENANT_OBJECT_COLLECTION","channel_id","public_key","apiKey","user_token","userToken","client_id","redirect_uri","URLSearchParams","disconnectFromMsTeams","revokeResult","msTeams","revokeAccessToken","tenant","knockChannelId"],"mappings":"qTAMA,MAAMA,EACJ,+DAEIC,EAAqB,mCAO3B,SAASC,EACPC,EACAC,EACsB,CACtB,MAAMC,EAAQC,EAAAA,eAAe,EACvB,CACJC,oBAAAA,EACAC,sBAAAA,EACAC,SAAAA,EACAC,eAAAA,GACEC,wBAAsB,EAEpBC,EAAkBC,UACtB,IAAMR,EAAMS,KAAOb,EACnB,CAACI,EAAMS,IAAI,CACb,EAEMC,EAAsBC,EAAAA,YAAY,IAAM,CAC5C,MAAMC,EAAY,CAChBC,MAAOC,KAAKC,UAAU,CACpBC,aAAcjB,EACdkB,uBAAwB,CACtBC,UAAWd,EACXe,WAAYC,EAAAA,wBACd,EACAC,WAAYlB,EACZmB,WAAYtB,EAAMuB,OAClBC,WAAYxB,EAAMyB,SAAAA,CACnB,EACDC,UAAW5B,EACX6B,aAAcpB,CAChB,EACA,MAAO,GAAGZ,CAAyB,IAAI,IAAIiC,gBAAgBhB,CAAS,CAAC,EACvE,EAAG,CACDb,EACAK,EACAD,EACAH,EAAMuB,OACNvB,EAAMyB,UACN3B,EACAS,CAAe,CAChB,EAEKsB,EAAwBlB,EAAAA,YAAY,SAAY,CACpDN,EAAe,IAAI,EACnBH,EAAoB,eAAe,EAC/B,GAAA,CACF,MAAM4B,EAAe,MAAM9B,EAAM+B,QAAQC,kBAAkB,CACzDC,OAAQ7B,EACR8B,eAAgB/B,CAAAA,CACjB,EAEmB2B,EAAAA,IAAiB,KAAO,eAAiB,OAAO,OACrD,CACf5B,EAAoB,OAAO,CAAA,CAC7B,EACC,CACDA,EACAF,EAAM+B,QACN3B,EACAD,EACAE,CAAc,CACf,EAEM,MAAA,CAAEK,oBAAAA,EAAqBmB,sBAAAA,CAAsB,CACtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsTeamsChannels.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsChannels.ts"],"sourcesContent":["import { GetMsTeamsChannelsResponse, MsTeamsChannel } from \"@knocklabs/client\";\nimport useSWR from \"swr\";\n\nimport { useKnockClient } from \"../../core\";\nimport { useKnockMsTeamsClient } from \"../context\";\nimport { MsTeamsChannelQueryOptions } from \"../interfaces\";\n\nconst QUERY_KEY = \"MS_TEAMS_CHANNELS\";\n\ntype UseMsTeamsChannelsProps = {\n teamId?: string;\n queryOptions?: MsTeamsChannelQueryOptions;\n};\n\ntype UseMsTeamsChannelsOutput = {\n data: MsTeamsChannel[];\n isLoading: boolean;\n refetch: () => void;\n};\n\nfunction useMsTeamsChannels({\n teamId,\n queryOptions,\n}: UseMsTeamsChannelsProps): UseMsTeamsChannelsOutput {\n const knock = useKnockClient();\n const { knockMsTeamsChannelId, tenantId } = useKnockMsTeamsClient();\n\n const fetchChannels = () =>\n knock.msTeams.getChannels({\n knockChannelId: knockMsTeamsChannelId,\n tenant: tenantId,\n teamId: teamId!,\n queryOptions: {\n $filter: queryOptions?.filter,\n $select: queryOptions?.select,\n },\n });\n\n const { data, isLoading, isValidating, mutate } =\n useSWR<GetMsTeamsChannelsResponse>(\n teamId ? [QUERY_KEY, teamId] : null,\n fetchChannels,\n { revalidateOnFocus: false },\n );\n\n return {\n data: data?.ms_teams_channels ?? [],\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useMsTeamsChannels;\n"],"names":["QUERY_KEY","useMsTeamsChannels","teamId","queryOptions","knock","useKnockClient","knockMsTeamsChannelId","tenantId","useKnockMsTeamsClient","fetchChannels","msTeams","getChannels","knockChannelId","tenant","$filter","filter","$select","select","data","isLoading","isValidating","mutate","useSWR","revalidateOnFocus","ms_teams_channels","refetch"],"mappings":"uSAOMA,EAAY,oBAalB,SAASC,EAAmB,CAC1BC,OAAAA,EACAC,aAAAA,CACuB,EAA6B,CACpD,MAAMC,EAAQC,EAAAA,
|
|
1
|
+
{"version":3,"file":"useMsTeamsChannels.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsChannels.ts"],"sourcesContent":["import { GetMsTeamsChannelsResponse, MsTeamsChannel } from \"@knocklabs/client\";\nimport useSWR from \"swr\";\n\nimport { useKnockClient } from \"../../core\";\nimport { useKnockMsTeamsClient } from \"../context\";\nimport { MsTeamsChannelQueryOptions } from \"../interfaces\";\n\nconst QUERY_KEY = \"MS_TEAMS_CHANNELS\";\n\ntype UseMsTeamsChannelsProps = {\n teamId?: string;\n queryOptions?: MsTeamsChannelQueryOptions;\n};\n\ntype UseMsTeamsChannelsOutput = {\n data: MsTeamsChannel[];\n isLoading: boolean;\n refetch: () => void;\n};\n\nfunction useMsTeamsChannels({\n teamId,\n queryOptions,\n}: UseMsTeamsChannelsProps): UseMsTeamsChannelsOutput {\n const knock = useKnockClient();\n const { knockMsTeamsChannelId, tenantId } = useKnockMsTeamsClient();\n\n const fetchChannels = () =>\n knock.msTeams.getChannels({\n knockChannelId: knockMsTeamsChannelId,\n tenant: tenantId,\n teamId: teamId!,\n queryOptions: {\n $filter: queryOptions?.filter,\n $select: queryOptions?.select,\n },\n });\n\n const { data, isLoading, isValidating, mutate } =\n useSWR<GetMsTeamsChannelsResponse>(\n teamId ? [QUERY_KEY, teamId] : null,\n fetchChannels,\n { revalidateOnFocus: false },\n );\n\n return {\n data: data?.ms_teams_channels ?? [],\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useMsTeamsChannels;\n"],"names":["QUERY_KEY","useMsTeamsChannels","teamId","queryOptions","knock","useKnockClient","knockMsTeamsChannelId","tenantId","useKnockMsTeamsClient","fetchChannels","msTeams","getChannels","knockChannelId","tenant","$filter","filter","$select","select","data","isLoading","isValidating","mutate","useSWR","revalidateOnFocus","ms_teams_channels","refetch"],"mappings":"uSAOMA,EAAY,oBAalB,SAASC,EAAmB,CAC1BC,OAAAA,EACAC,aAAAA,CACuB,EAA6B,CACpD,MAAMC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,sBAAAA,EAAuBC,SAAAA,GAAaC,wBAAsB,EAE5DC,EAAgBA,IACpBL,EAAMM,QAAQC,YAAY,CACxBC,eAAgBN,EAChBO,OAAQN,EACRL,OAAAA,EACAC,aAAc,CACZW,QAASX,GAAAA,YAAAA,EAAcY,OACvBC,QAASb,GAAAA,YAAAA,EAAcc,MAAAA,CACzB,CACD,EAEG,CAAEC,KAAAA,EAAMC,UAAAA,EAAWC,aAAAA,EAAcC,OAAAA,CAAAA,EACrCC,EAAAA,QACEpB,EAAS,CAACF,EAAWE,CAAM,EAAI,KAC/BO,EACA,CAAEc,kBAAmB,EAAA,CACvB,EAEK,MAAA,CACLL,MAAMA,GAAAA,YAAAA,EAAMM,oBAAqB,CAAE,EACnCL,UAAWA,GAAaC,EACxBK,QAASA,IAAMJ,EAAO,CACxB,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsTeamsConnectionStatus.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport { useTranslations } from \"../../i18n\";\n\nexport type ConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"error\"\n | \"disconnecting\";\n\ntype UseMsTeamsConnectionStatusOutput = {\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\nfunction useMsTeamsConnectionStatus(\n knock: Knock,\n knockMsTeamsChannelId: string,\n tenantId: string,\n): UseMsTeamsConnectionStatusOutput {\n const { t } = useTranslations();\n\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.msTeams.authCheck({\n tenant: tenantId,\n knockChannelId: knockMsTeamsChannelId,\n });\n\n if (authRes.connection?.ok === true) {\n return setConnectionStatus(\"connected\");\n }\n\n if (authRes.connection?.ok === false) {\n return setConnectionStatus(\"disconnected\");\n }\n\n // This is a normal response for a tenant that doesn't have\n // ms_teams_tenant_id set on it, meaning it's not connected to MS Teams,\n // so we give it a \"disconnected\" status instead of an error status.\n if (\n authRes.code === \"ERR_BAD_REQUEST\" &&\n authRes.response?.data?.message === t(\"msTeamsTenantIdNotSet\")\n ) {\n return setConnectionStatus(\"disconnected\");\n }\n\n // This is for any Knock errors that would require a reconnect.\n setConnectionStatus(\"error\");\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n };\n\n checkAuthStatus();\n }, [connectionStatus, tenantId, knockMsTeamsChannelId, knock.msTeams, t]);\n\n return {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n };\n}\n\nexport default useMsTeamsConnectionStatus;\n"],"names":["useMsTeamsConnectionStatus","knock","knockMsTeamsChannelId","tenantId","t","useTranslations","connectionStatus","setConnectionStatus","useState","errorLabel","setErrorLabel","actionLabel","setActionLabel","useEffect","authRes","msTeams","authCheck","tenant","knockChannelId","connection","ok","code","response","data","message"],"mappings":"gJAqBA,SAASA,EACPC,EACAC,EACAC,EACkC,CAC5B,KAAA,CAAEC,EAAAA,GAAMC,
|
|
1
|
+
{"version":3,"file":"useMsTeamsConnectionStatus.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport { useTranslations } from \"../../i18n\";\n\nexport type ConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"error\"\n | \"disconnecting\";\n\ntype UseMsTeamsConnectionStatusOutput = {\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\nfunction useMsTeamsConnectionStatus(\n knock: Knock,\n knockMsTeamsChannelId: string,\n tenantId: string,\n): UseMsTeamsConnectionStatusOutput {\n const { t } = useTranslations();\n\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.msTeams.authCheck({\n tenant: tenantId,\n knockChannelId: knockMsTeamsChannelId,\n });\n\n if (authRes.connection?.ok === true) {\n return setConnectionStatus(\"connected\");\n }\n\n if (authRes.connection?.ok === false) {\n return setConnectionStatus(\"disconnected\");\n }\n\n // This is a normal response for a tenant that doesn't have\n // ms_teams_tenant_id set on it, meaning it's not connected to MS Teams,\n // so we give it a \"disconnected\" status instead of an error status.\n if (\n authRes.code === \"ERR_BAD_REQUEST\" &&\n authRes.response?.data?.message === t(\"msTeamsTenantIdNotSet\")\n ) {\n return setConnectionStatus(\"disconnected\");\n }\n\n // This is for any Knock errors that would require a reconnect.\n setConnectionStatus(\"error\");\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n };\n\n checkAuthStatus();\n }, [connectionStatus, tenantId, knockMsTeamsChannelId, knock.msTeams, t]);\n\n return {\n connectionStatus,\n setConnectionStatus,\n errorLabel,\n setErrorLabel,\n actionLabel,\n setActionLabel,\n };\n}\n\nexport default useMsTeamsConnectionStatus;\n"],"names":["useMsTeamsConnectionStatus","knock","knockMsTeamsChannelId","tenantId","t","useTranslations","connectionStatus","setConnectionStatus","useState","errorLabel","setErrorLabel","actionLabel","setActionLabel","useEffect","authRes","msTeams","authCheck","tenant","knockChannelId","connection","ok","code","response","data","message"],"mappings":"gJAqBA,SAASA,EACPC,EACAC,EACAC,EACkC,CAC5B,KAAA,CAAEC,EAAAA,GAAMC,kBAAgB,EAExB,CAACC,EAAkBC,CAAmB,EAC1CC,EAAAA,SAA2B,YAAY,EACnC,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAwB,IAAI,EAC1D,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAwB,IAAI,EAElEK,OAAAA,EAAAA,UAAU,IAAM,EACU,SAAY,aAClC,GAAIP,IAAqB,aAErB,GAAA,CACF,MAAMQ,EAAU,MAAMb,EAAMc,QAAQC,UAAU,CAC5CC,OAAQd,EACRe,eAAgBhB,CAAAA,CACjB,EAEGY,KAAAA,EAAAA,EAAQK,aAARL,YAAAA,EAAoBM,MAAO,GAC7B,OAAOb,EAAoB,WAAW,EAWtCO,KAREA,EAAAA,EAAQK,aAARL,YAAAA,EAAoBM,MAAO,IAQ7BN,EAAQO,OAAS,qBACjBP,GAAAA,EAAAA,EAAQQ,WAARR,YAAAA,EAAkBS,OAAlBT,YAAAA,EAAwBU,WAAYpB,EAAE,uBAAuB,EAE7D,OAAOG,EAAoB,cAAc,EAI3CA,EAAoB,OAAO,OACZ,CACfA,EAAoB,OAAO,CAAA,CAE/B,GAEgB,CAAA,EACf,CAACD,EAAkBH,EAAUD,EAAuBD,EAAMc,QAASX,CAAC,CAAC,EAEjE,CACLE,iBAAAA,EACAC,oBAAAA,EACAE,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsTeamsTeams.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsTeams.ts"],"sourcesContent":["import { GetMsTeamsTeamsResponse, MsTeamsTeam } from \"@knocklabs/client\";\nimport { useEffect, useMemo } from \"react\";\nimport useSWRInfinite from \"swr/infinite\";\n\nimport { useKnockClient } from \"../../core\";\nimport { useKnockMsTeamsClient } from \"../context\";\nimport { MsTeamsTeamQueryOptions } from \"../interfaces\";\n\nconst MAX_COUNT = 1000;\n\nconst QUERY_KEY = \"MS_TEAMS_TEAMS\";\n\ntype UseMsTeamsTeamsProps = {\n queryOptions?: MsTeamsTeamQueryOptions;\n};\n\ntype UseMsTeamsTeamsOutput = {\n data: MsTeamsTeam[];\n isLoading: boolean;\n refetch: () => void;\n};\n\ntype QueryKey = [key: string, skiptoken: string] | null;\n\nfunction getQueryKey(\n pageIndex: number,\n previousPageData: GetMsTeamsTeamsResponse,\n): QueryKey {\n // First page so just pass empty\n if (pageIndex === 0) {\n return [QUERY_KEY, \"\"];\n }\n\n // If there's no more data then return an empty next skiptoken\n if (previousPageData && [\"\", null].includes(previousPageData.skip_token)) {\n return null;\n }\n\n // Next skiptoken exists so pass it\n return [QUERY_KEY, previousPageData.skip_token ?? \"\"];\n}\n\nfunction useMsTeamsTeams({\n queryOptions = {},\n}: UseMsTeamsTeamsProps): UseMsTeamsTeamsOutput {\n const knock = useKnockClient();\n const { knockMsTeamsChannelId, tenantId, connectionStatus } =\n useKnockMsTeamsClient();\n\n const fetchTeams = (queryKey: QueryKey) =>\n knock.msTeams.getTeams({\n knockChannelId: knockMsTeamsChannelId,\n tenant: tenantId,\n queryOptions: {\n $skiptoken: queryKey?.[1],\n $top: queryOptions?.limitPerPage,\n $filter: queryOptions?.filter,\n $select: queryOptions?.select,\n },\n });\n\n const { data, error, isLoading, isValidating, setSize, mutate } =\n useSWRInfinite<GetMsTeamsTeamsResponse>(getQueryKey, fetchTeams, {\n initialSize: 0,\n revalidateOnFocus: false,\n });\n\n const lastPage = data?.at(-1);\n const hasNextPage = lastPage === undefined || !!lastPage.skip_token;\n\n const teams = useMemo(\n () =>\n (data ?? [])\n .flatMap((page) => page?.ms_teams_teams)\n .filter((team) => !!team),\n [data],\n );\n\n const maxCount = queryOptions?.maxCount || MAX_COUNT;\n\n useEffect(() => {\n if (\n connectionStatus === \"connected\" &&\n !error &&\n hasNextPage &&\n !isLoading &&\n !isValidating &&\n teams.length < maxCount\n ) {\n // Fetch a page at a time until we have nothing else left to fetch\n // or we've already hit the max amount of teams to fetch\n setSize((size) => size + 1);\n }\n }, [\n teams.length,\n setSize,\n hasNextPage,\n isLoading,\n isValidating,\n maxCount,\n error,\n connectionStatus,\n ]);\n\n return {\n data: teams,\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useMsTeamsTeams;\n"],"names":["MAX_COUNT","QUERY_KEY","getQueryKey","pageIndex","previousPageData","includes","skip_token","useMsTeamsTeams","queryOptions","knock","useKnockClient","knockMsTeamsChannelId","tenantId","connectionStatus","useKnockMsTeamsClient","fetchTeams","queryKey","msTeams","getTeams","knockChannelId","tenant","$skiptoken","$top","limitPerPage","$filter","filter","$select","select","data","error","isLoading","isValidating","setSize","mutate","useSWRInfinite","initialSize","revalidateOnFocus","lastPage","at","hasNextPage","undefined","teams","useMemo","flatMap","page","ms_teams_teams","team","maxCount","useEffect","length","size","refetch"],"mappings":"kTAQMA,EAAY,IAEZC,EAAY,iBAclB,SAASC,EACPC,EACAC,EACU,CAEV,OAAID,IAAc,EACT,CAACF,EAAW,EAAE,EAInBG,GAAoB,CAAC,GAAI,IAAI,EAAEC,SAASD,EAAiBE,UAAU,EAC9D,KAIF,CAACL,EAAWG,EAAiBE,YAAc,EAAE,CACtD,CAEA,SAASC,EAAgB,CACvBC,aAAAA,EAAe,
|
|
1
|
+
{"version":3,"file":"useMsTeamsTeams.js","sources":["../../../../../src/modules/ms-teams/hooks/useMsTeamsTeams.ts"],"sourcesContent":["import { GetMsTeamsTeamsResponse, MsTeamsTeam } from \"@knocklabs/client\";\nimport { useEffect, useMemo } from \"react\";\nimport useSWRInfinite from \"swr/infinite\";\n\nimport { useKnockClient } from \"../../core\";\nimport { useKnockMsTeamsClient } from \"../context\";\nimport { MsTeamsTeamQueryOptions } from \"../interfaces\";\n\nconst MAX_COUNT = 1000;\n\nconst QUERY_KEY = \"MS_TEAMS_TEAMS\";\n\ntype UseMsTeamsTeamsProps = {\n queryOptions?: MsTeamsTeamQueryOptions;\n};\n\ntype UseMsTeamsTeamsOutput = {\n data: MsTeamsTeam[];\n isLoading: boolean;\n refetch: () => void;\n};\n\ntype QueryKey = [key: string, skiptoken: string] | null;\n\nfunction getQueryKey(\n pageIndex: number,\n previousPageData: GetMsTeamsTeamsResponse,\n): QueryKey {\n // First page so just pass empty\n if (pageIndex === 0) {\n return [QUERY_KEY, \"\"];\n }\n\n // If there's no more data then return an empty next skiptoken\n if (previousPageData && [\"\", null].includes(previousPageData.skip_token)) {\n return null;\n }\n\n // Next skiptoken exists so pass it\n return [QUERY_KEY, previousPageData.skip_token ?? \"\"];\n}\n\nfunction useMsTeamsTeams({\n queryOptions = {},\n}: UseMsTeamsTeamsProps): UseMsTeamsTeamsOutput {\n const knock = useKnockClient();\n const { knockMsTeamsChannelId, tenantId, connectionStatus } =\n useKnockMsTeamsClient();\n\n const fetchTeams = (queryKey: QueryKey) =>\n knock.msTeams.getTeams({\n knockChannelId: knockMsTeamsChannelId,\n tenant: tenantId,\n queryOptions: {\n $skiptoken: queryKey?.[1],\n $top: queryOptions?.limitPerPage,\n $filter: queryOptions?.filter,\n $select: queryOptions?.select,\n },\n });\n\n const { data, error, isLoading, isValidating, setSize, mutate } =\n useSWRInfinite<GetMsTeamsTeamsResponse>(getQueryKey, fetchTeams, {\n initialSize: 0,\n revalidateOnFocus: false,\n });\n\n const lastPage = data?.at(-1);\n const hasNextPage = lastPage === undefined || !!lastPage.skip_token;\n\n const teams = useMemo(\n () =>\n (data ?? [])\n .flatMap((page) => page?.ms_teams_teams)\n .filter((team) => !!team),\n [data],\n );\n\n const maxCount = queryOptions?.maxCount || MAX_COUNT;\n\n useEffect(() => {\n if (\n connectionStatus === \"connected\" &&\n !error &&\n hasNextPage &&\n !isLoading &&\n !isValidating &&\n teams.length < maxCount\n ) {\n // Fetch a page at a time until we have nothing else left to fetch\n // or we've already hit the max amount of teams to fetch\n setSize((size) => size + 1);\n }\n }, [\n teams.length,\n setSize,\n hasNextPage,\n isLoading,\n isValidating,\n maxCount,\n error,\n connectionStatus,\n ]);\n\n return {\n data: teams,\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useMsTeamsTeams;\n"],"names":["MAX_COUNT","QUERY_KEY","getQueryKey","pageIndex","previousPageData","includes","skip_token","useMsTeamsTeams","queryOptions","knock","useKnockClient","knockMsTeamsChannelId","tenantId","connectionStatus","useKnockMsTeamsClient","fetchTeams","queryKey","msTeams","getTeams","knockChannelId","tenant","$skiptoken","$top","limitPerPage","$filter","filter","$select","select","data","error","isLoading","isValidating","setSize","mutate","useSWRInfinite","initialSize","revalidateOnFocus","lastPage","at","hasNextPage","undefined","teams","useMemo","flatMap","page","ms_teams_teams","team","maxCount","useEffect","length","size","refetch"],"mappings":"kTAQMA,EAAY,IAEZC,EAAY,iBAclB,SAASC,EACPC,EACAC,EACU,CAEV,OAAID,IAAc,EACT,CAACF,EAAW,EAAE,EAInBG,GAAoB,CAAC,GAAI,IAAI,EAAEC,SAASD,EAAiBE,UAAU,EAC9D,KAIF,CAACL,EAAWG,EAAiBE,YAAc,EAAE,CACtD,CAEA,SAASC,EAAgB,CACvBC,aAAAA,EAAe,CAAA,CACK,EAA0B,CAC9C,MAAMC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,sBAAAA,EAAuBC,SAAAA,EAAUC,iBAAAA,GACvCC,wBAAsB,EAElBC,EAAcC,GAClBP,EAAMQ,QAAQC,SAAS,CACrBC,eAAgBR,EAChBS,OAAQR,EACRJ,aAAc,CACZa,WAAYL,GAAAA,YAAAA,EAAW,GACvBM,KAAMd,GAAAA,YAAAA,EAAce,aACpBC,QAAShB,GAAAA,YAAAA,EAAciB,OACvBC,QAASlB,GAAAA,YAAAA,EAAcmB,MAAAA,CACzB,CACD,EAEG,CAAEC,KAAAA,EAAMC,MAAAA,EAAOC,UAAAA,EAAWC,aAAAA,EAAcC,QAAAA,EAASC,OAAAA,CAAAA,EACrDC,EAAwChC,QAAAA,EAAaa,EAAY,CAC/DoB,YAAa,EACbC,kBAAmB,EAAA,CACpB,EAEGC,EAAWT,GAAAA,YAAAA,EAAMU,GAAG,IACpBC,EAAcF,IAAaG,QAAa,CAAC,CAACH,EAAS/B,WAEnDmC,EAAQC,EAAAA,QACZ,KACGd,GAAQ,IACNe,QAAkBC,GAAAA,GAAAA,YAAAA,EAAMC,cAAc,EACtCpB,UAAiB,CAAC,CAACqB,CAAI,EAC5B,CAAClB,CAAI,CACP,EAEMmB,GAAWvC,GAAAA,YAAAA,EAAcuC,WAAY/C,EAE3CgD,OAAAA,EAAAA,UAAU,IAAM,CAEZnC,IAAqB,aACrB,CAACgB,GACDU,GACA,CAACT,GACD,CAACC,GACDU,EAAMQ,OAASF,GAING,EAAAA,GAASA,EAAO,CAAC,CAE9B,EAAG,CACDT,EAAMQ,OACNjB,EACAO,EACAT,EACAC,EACAgB,EACAlB,EACAhB,CAAgB,CACjB,EAEM,CACLe,KAAMa,EACNX,UAAWA,GAAaC,EACxBoB,QAASA,IAAMlB,EAAO,CACxB,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockSlackProvider.js","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\";\nimport { ConnectionStatus } from \"../hooks/useSlackConnectionStatus\";\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}\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\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 }}\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","connectionStatus","setConnectionStatus","errorLabel","setErrorLabel","actionLabel","setActionLabel","useSlackConnectionStatus","slackProviderKey","useKnockSlackClient","context","useContext","undefined","Error"],"mappings":"stBAuBMA,EACJC,EAAMC,cAA8C,IAAI,EAe7CC,EAEEC,GAAA,CACP,KAAA,CAAEC,oBAAAA,EAAqBC,SAAAA,
|
|
1
|
+
{"version":3,"file":"KnockSlackProvider.js","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\";\nimport { ConnectionStatus } from \"../hooks/useSlackConnectionStatus\";\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}\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\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 }}\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","connectionStatus","setConnectionStatus","errorLabel","setErrorLabel","actionLabel","setActionLabel","useSlackConnectionStatus","slackProviderKey","useKnockSlackClient","context","useContext","undefined","Error"],"mappings":"stBAuBMA,EACJC,EAAMC,cAA8C,IAAI,EAe7CC,EAEEC,GAAA,CACP,KAAA,CAAEC,oBAAAA,EAAqBC,SAAAA,CAAAA,EAAaF,EACpCG,EAAW,aAAcH,EAAQA,EAAMG,SAAWH,EAAMI,OAExDC,EAAQC,EAAAA,eAAe,EAEvB,CACJC,iBAAAA,EACAC,oBAAAA,EACAC,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,CACEC,EAAAA,EAAyBR,EAAOJ,EAAqBE,CAAQ,EAEjE,OACGN,EAAA,cAAAD,EAA0B,SAA1B,CACC,IAAKkB,mBAAiB,CACpBb,oBAAAA,EACAE,SAAAA,EACAI,iBAAAA,EACAE,WAAAA,CACD,CAAA,EACD,MAAO,CACLF,iBAAAA,EACAC,oBAAAA,EACAC,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,EACAX,oBAAAA,EAEAG,OAAQD,EACRA,SAAAA,IAGDD,CACH,CAEJ,EAEaa,EAAsBA,IAA+B,CAC1DC,MAAAA,EAAUnB,EAAMoB,WACpBrB,CACF,EACA,GAAIoB,IAAYE,OACR,MAAA,IAAIC,MACR,8DACF,EAEKH,OAAAA,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConnectedSlackChannels.js","sources":["../../../../../src/modules/slack/hooks/useConnectedSlackChannels.ts"],"sourcesContent":["import { useKnockSlackClient } from \"..\";\nimport { SlackChannelConnection } from \"@knocklabs/client\";\nimport { GenericData } from \"@knocklabs/types\";\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\n\nimport { RecipientObject } from \"../../..\";\nimport { useKnockClient } from \"../../core\";\nimport { useTranslations } from \"../../i18n\";\n\nconst QUERY_KEY = \"SLACK_CONNECTED_CHANNELS\";\n\ntype UseConnectedSlackChannelsProps = {\n slackChannelsRecipientObject: RecipientObject;\n};\n\ntype UseConnectedSlackChannelsOutput = {\n data: SlackChannelConnection[] | null;\n updateConnectedChannels: (\n connectedChannels: SlackChannelConnection[],\n ) => Promise<void>;\n loading: boolean;\n error: string | null;\n updating: boolean;\n};\n\nfunction useConnectedSlackChannels({\n slackChannelsRecipientObject: { objectId, collection },\n}: UseConnectedSlackChannelsProps): UseConnectedSlackChannelsOutput {\n const { t } = useTranslations();\n const knock = useKnockClient();\n const { connectionStatus, knockSlackChannelId } = useKnockSlackClient();\n\n const [error, setError] = useState<string | null>(null);\n const [isUpdating, setIsUpdating] = useState(false);\n\n const {\n data: connectedChannels,\n mutate,\n isValidating,\n isLoading,\n } = useSWR<SlackChannelConnection[]>(\n // Only fetch when Slack is connected\n connectionStatus === \"connected\"\n ? [QUERY_KEY, knockSlackChannelId, collection, objectId]\n : null,\n async () => {\n return knock.objects\n .getChannelData({\n collection,\n objectId,\n channelId: knockSlackChannelId,\n })\n .then((res) => res.data?.connections ?? [])\n .catch(() => []);\n },\n {\n onSuccess: () => {\n setError(null);\n },\n },\n );\n\n const updateConnectedChannels = async (\n channelsToSendToKnock: SlackChannelConnection[],\n ) => {\n setIsUpdating(true);\n try {\n await mutate(\n () =>\n knock.objects\n .setChannelData({\n objectId,\n collection,\n channelId: knockSlackChannelId,\n data: { connections: channelsToSendToKnock },\n })\n .then((res) => (res as GenericData).data?.connections ?? []),\n {\n populateCache: true,\n revalidate: false,\n optimisticData: channelsToSendToKnock,\n },\n );\n } catch (_error) {\n setError(t(\"slackChannelSetError\") || \"\");\n }\n setIsUpdating(false);\n };\n\n return {\n data: connectedChannels ?? null,\n updateConnectedChannels,\n updating: isUpdating,\n loading: isLoading || isValidating,\n error,\n };\n}\n\nexport default useConnectedSlackChannels;\n"],"names":["QUERY_KEY","useConnectedSlackChannels","slackChannelsRecipientObject","objectId","collection","t","useTranslations","knock","useKnockClient","connectionStatus","knockSlackChannelId","useKnockSlackClient","error","setError","useState","isUpdating","setIsUpdating","data","connectedChannels","mutate","isValidating","isLoading","useSWR","objects","getChannelData","channelId","then","res","connections","catch","onSuccess","updateConnectedChannels","channelsToSendToKnock","setChannelData","populateCache","revalidate","optimisticData","updating","loading"],"mappings":"+aAUMA,EAAY,2BAgBlB,SAASC,EAA0B,CACjCC,6BAA8B,CAAEC,SAAAA,EAAUC,WAAAA,
|
|
1
|
+
{"version":3,"file":"useConnectedSlackChannels.js","sources":["../../../../../src/modules/slack/hooks/useConnectedSlackChannels.ts"],"sourcesContent":["import { useKnockSlackClient } from \"..\";\nimport { SlackChannelConnection } from \"@knocklabs/client\";\nimport { GenericData } from \"@knocklabs/types\";\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\n\nimport { RecipientObject } from \"../../..\";\nimport { useKnockClient } from \"../../core\";\nimport { useTranslations } from \"../../i18n\";\n\nconst QUERY_KEY = \"SLACK_CONNECTED_CHANNELS\";\n\ntype UseConnectedSlackChannelsProps = {\n slackChannelsRecipientObject: RecipientObject;\n};\n\ntype UseConnectedSlackChannelsOutput = {\n data: SlackChannelConnection[] | null;\n updateConnectedChannels: (\n connectedChannels: SlackChannelConnection[],\n ) => Promise<void>;\n loading: boolean;\n error: string | null;\n updating: boolean;\n};\n\nfunction useConnectedSlackChannels({\n slackChannelsRecipientObject: { objectId, collection },\n}: UseConnectedSlackChannelsProps): UseConnectedSlackChannelsOutput {\n const { t } = useTranslations();\n const knock = useKnockClient();\n const { connectionStatus, knockSlackChannelId } = useKnockSlackClient();\n\n const [error, setError] = useState<string | null>(null);\n const [isUpdating, setIsUpdating] = useState(false);\n\n const {\n data: connectedChannels,\n mutate,\n isValidating,\n isLoading,\n } = useSWR<SlackChannelConnection[]>(\n // Only fetch when Slack is connected\n connectionStatus === \"connected\"\n ? [QUERY_KEY, knockSlackChannelId, collection, objectId]\n : null,\n async () => {\n return knock.objects\n .getChannelData({\n collection,\n objectId,\n channelId: knockSlackChannelId,\n })\n .then((res) => res.data?.connections ?? [])\n .catch(() => []);\n },\n {\n onSuccess: () => {\n setError(null);\n },\n },\n );\n\n const updateConnectedChannels = async (\n channelsToSendToKnock: SlackChannelConnection[],\n ) => {\n setIsUpdating(true);\n try {\n await mutate(\n () =>\n knock.objects\n .setChannelData({\n objectId,\n collection,\n channelId: knockSlackChannelId,\n data: { connections: channelsToSendToKnock },\n })\n .then((res) => (res as GenericData).data?.connections ?? []),\n {\n populateCache: true,\n revalidate: false,\n optimisticData: channelsToSendToKnock,\n },\n );\n } catch (_error) {\n setError(t(\"slackChannelSetError\") || \"\");\n }\n setIsUpdating(false);\n };\n\n return {\n data: connectedChannels ?? null,\n updateConnectedChannels,\n updating: isUpdating,\n loading: isLoading || isValidating,\n error,\n };\n}\n\nexport default useConnectedSlackChannels;\n"],"names":["QUERY_KEY","useConnectedSlackChannels","slackChannelsRecipientObject","objectId","collection","t","useTranslations","knock","useKnockClient","connectionStatus","knockSlackChannelId","useKnockSlackClient","error","setError","useState","isUpdating","setIsUpdating","data","connectedChannels","mutate","isValidating","isLoading","useSWR","objects","getChannelData","channelId","then","res","connections","catch","onSuccess","updateConnectedChannels","channelsToSendToKnock","setChannelData","populateCache","revalidate","optimisticData","updating","loading"],"mappings":"+aAUMA,EAAY,2BAgBlB,SAASC,EAA0B,CACjCC,6BAA8B,CAAEC,SAAAA,EAAUC,WAAAA,CAAAA,CACZ,EAAoC,CAC5D,KAAA,CAAEC,EAAAA,GAAMC,kBAAgB,EACxBC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,iBAAAA,EAAkBC,oBAAAA,GAAwBC,sBAAoB,EAEhE,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAwB,IAAI,EAChD,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAS,EAAK,EAE5C,CACJG,KAAMC,EACNC,OAAAA,EACAC,aAAAA,EACAC,UAAAA,CAAAA,EACEC,EAAAA,QAEFb,IAAqB,YACjB,CAACT,EAAWU,EAAqBN,EAAYD,CAAQ,EACrD,KACJ,SACSI,EAAMgB,QACVC,eAAe,CACdpB,WAAAA,EACAD,SAAAA,EACAsB,UAAWf,CACZ,CAAA,EACAgB,KAAMC,GAAAA,OAAQA,QAAAA,EAAAA,EAAIV,OAAJU,YAAAA,EAAUC,cAAe,GAAE,EACzCC,MAAM,IAAM,EAAE,EAEnB,CACEC,UAAWA,IAAM,CACfjB,EAAS,IAAI,CAAA,CACf,CAEJ,EA6BO,MAAA,CACLI,KAAMC,GAAqB,KAC3Ba,wBA7B8B,MAC9BC,GACG,CACHhB,EAAc,EAAI,EACd,GAAA,CACF,MAAMG,EACJ,IACEZ,EAAMgB,QACHU,eAAe,CACd9B,SAAAA,EACAC,WAAAA,EACAqB,UAAWf,EACXO,KAAM,CAAEW,YAAaI,CAAAA,CAAsB,CAC5C,EACAN,KAAMC,GAAAA,OAASA,QAAAA,EAAAA,EAAoBV,OAApBU,YAAAA,EAA0BC,cAAe,CAAA,EAAE,EAC/D,CACEM,cAAe,GACfC,WAAY,GACZC,eAAgBJ,CAAAA,CAEpB,OACe,CACN3B,EAAAA,EAAE,sBAAsB,GAAK,EAAE,CAAA,CAE1CW,EAAc,EAAK,CACrB,EAKEqB,SAAUtB,EACVuB,QAASjB,GAAaD,EACtBR,MAAAA,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlackAuth.js","sources":["../../../../../src/modules/slack/hooks/useSlackAuth.ts"],"sourcesContent":["import { useKnockSlackClient } from \"..\";\nimport { TENANT_OBJECT_COLLECTION } from \"@knocklabs/client\";\nimport { useCallback } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst SLACK_AUTHORIZE_URL = \"https://slack.com/oauth/v2/authorize\";\nconst DEFAULT_SLACK_SCOPES = [\n \"chat:write\",\n \"chat:write.public\",\n \"channels:read\",\n \"groups:read\",\n];\n\ntype UseSlackAuthOutput = {\n buildSlackAuthUrl: () => string;\n disconnectFromSlack: () => void;\n};\n\nfunction useSlackAuth(\n slackClientId: string,\n redirectUrl?: string,\n additionalScopes?: string[],\n): UseSlackAuthOutput {\n const knock = useKnockClient();\n const { setConnectionStatus, knockSlackChannelId, tenantId, setActionLabel } =\n useKnockSlackClient();\n\n const combinedScopes =\n additionalScopes && additionalScopes.length > 0\n ? Array.from(new Set(DEFAULT_SLACK_SCOPES.concat(additionalScopes)))\n : DEFAULT_SLACK_SCOPES;\n\n const disconnectFromSlack = useCallback(async () => {\n setActionLabel(null);\n setConnectionStatus(\"disconnecting\");\n try {\n const revoke = await knock.slack.revokeAccessToken({\n tenant: tenantId,\n knockChannelId: knockSlackChannelId,\n });\n\n if (revoke === \"ok\") {\n setConnectionStatus(\"disconnected\");\n } else {\n setConnectionStatus(\"error\");\n }\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n }, [\n setConnectionStatus,\n knock.slack,\n tenantId,\n knockSlackChannelId,\n setActionLabel,\n ]);\n\n const buildSlackAuthUrl = useCallback(() => {\n const rawParams = {\n state: JSON.stringify({\n redirect_url: redirectUrl,\n access_token_object: {\n object_id: tenantId,\n collection: TENANT_OBJECT_COLLECTION,\n },\n channel_id: knockSlackChannelId,\n public_key: knock.apiKey,\n user_token: knock.userToken,\n }),\n client_id: slackClientId,\n scope: combinedScopes.join(\",\"),\n };\n return `${SLACK_AUTHORIZE_URL}?${new URLSearchParams(rawParams)}`;\n }, [\n redirectUrl,\n tenantId,\n knockSlackChannelId,\n knock.apiKey,\n knock.userToken,\n slackClientId,\n combinedScopes,\n ]);\n\n return {\n buildSlackAuthUrl,\n disconnectFromSlack,\n };\n}\n\nexport default useSlackAuth;\n"],"names":["SLACK_AUTHORIZE_URL","DEFAULT_SLACK_SCOPES","useSlackAuth","slackClientId","redirectUrl","additionalScopes","knock","useKnockClient","setConnectionStatus","knockSlackChannelId","tenantId","setActionLabel","useKnockSlackClient","combinedScopes","length","Array","from","Set","concat","disconnectFromSlack","useCallback","revoke","slack","revokeAccessToken","tenant","knockChannelId","buildSlackAuthUrl","rawParams","state","JSON","stringify","redirect_url","access_token_object","object_id","collection","TENANT_OBJECT_COLLECTION","channel_id","public_key","apiKey","user_token","userToken","client_id","scope","join","URLSearchParams"],"mappings":"mTAMA,MAAMA,EAAsB,uCACtBC,EAAuB,CAC3B,aACA,oBACA,gBACA,aAAa,EAQf,SAASC,EACPC,EACAC,EACAC,EACoB,CACpB,MAAMC,EAAQC,EAAAA,
|
|
1
|
+
{"version":3,"file":"useSlackAuth.js","sources":["../../../../../src/modules/slack/hooks/useSlackAuth.ts"],"sourcesContent":["import { useKnockSlackClient } from \"..\";\nimport { TENANT_OBJECT_COLLECTION } from \"@knocklabs/client\";\nimport { useCallback } from \"react\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst SLACK_AUTHORIZE_URL = \"https://slack.com/oauth/v2/authorize\";\nconst DEFAULT_SLACK_SCOPES = [\n \"chat:write\",\n \"chat:write.public\",\n \"channels:read\",\n \"groups:read\",\n];\n\ntype UseSlackAuthOutput = {\n buildSlackAuthUrl: () => string;\n disconnectFromSlack: () => void;\n};\n\nfunction useSlackAuth(\n slackClientId: string,\n redirectUrl?: string,\n additionalScopes?: string[],\n): UseSlackAuthOutput {\n const knock = useKnockClient();\n const { setConnectionStatus, knockSlackChannelId, tenantId, setActionLabel } =\n useKnockSlackClient();\n\n const combinedScopes =\n additionalScopes && additionalScopes.length > 0\n ? Array.from(new Set(DEFAULT_SLACK_SCOPES.concat(additionalScopes)))\n : DEFAULT_SLACK_SCOPES;\n\n const disconnectFromSlack = useCallback(async () => {\n setActionLabel(null);\n setConnectionStatus(\"disconnecting\");\n try {\n const revoke = await knock.slack.revokeAccessToken({\n tenant: tenantId,\n knockChannelId: knockSlackChannelId,\n });\n\n if (revoke === \"ok\") {\n setConnectionStatus(\"disconnected\");\n } else {\n setConnectionStatus(\"error\");\n }\n } catch (_error) {\n setConnectionStatus(\"error\");\n }\n }, [\n setConnectionStatus,\n knock.slack,\n tenantId,\n knockSlackChannelId,\n setActionLabel,\n ]);\n\n const buildSlackAuthUrl = useCallback(() => {\n const rawParams = {\n state: JSON.stringify({\n redirect_url: redirectUrl,\n access_token_object: {\n object_id: tenantId,\n collection: TENANT_OBJECT_COLLECTION,\n },\n channel_id: knockSlackChannelId,\n public_key: knock.apiKey,\n user_token: knock.userToken,\n }),\n client_id: slackClientId,\n scope: combinedScopes.join(\",\"),\n };\n return `${SLACK_AUTHORIZE_URL}?${new URLSearchParams(rawParams)}`;\n }, [\n redirectUrl,\n tenantId,\n knockSlackChannelId,\n knock.apiKey,\n knock.userToken,\n slackClientId,\n combinedScopes,\n ]);\n\n return {\n buildSlackAuthUrl,\n disconnectFromSlack,\n };\n}\n\nexport default useSlackAuth;\n"],"names":["SLACK_AUTHORIZE_URL","DEFAULT_SLACK_SCOPES","useSlackAuth","slackClientId","redirectUrl","additionalScopes","knock","useKnockClient","setConnectionStatus","knockSlackChannelId","tenantId","setActionLabel","useKnockSlackClient","combinedScopes","length","Array","from","Set","concat","disconnectFromSlack","useCallback","revoke","slack","revokeAccessToken","tenant","knockChannelId","buildSlackAuthUrl","rawParams","state","JSON","stringify","redirect_url","access_token_object","object_id","collection","TENANT_OBJECT_COLLECTION","channel_id","public_key","apiKey","user_token","userToken","client_id","scope","join","URLSearchParams"],"mappings":"mTAMA,MAAMA,EAAsB,uCACtBC,EAAuB,CAC3B,aACA,oBACA,gBACA,aAAa,EAQf,SAASC,EACPC,EACAC,EACAC,EACoB,CACpB,MAAMC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,oBAAAA,EAAqBC,oBAAAA,EAAqBC,SAAAA,EAAUC,eAAAA,GAC1DC,sBAAoB,EAEhBC,EACJR,GAAoBA,EAAiBS,OAAS,EAC1CC,MAAMC,KAAK,IAAIC,IAAIhB,EAAqBiB,OAAOb,CAAgB,CAAC,CAAC,EACjEJ,EAEAkB,EAAsBC,EAAAA,YAAY,SAAY,CAClDT,EAAe,IAAI,EACnBH,EAAoB,eAAe,EAC/B,GAAA,CACF,MAAMa,EAAS,MAAMf,EAAMgB,MAAMC,kBAAkB,CACjDC,OAAQd,EACRe,eAAgBhB,CAAAA,CACjB,EAGCD,EADEa,IAAW,KACO,eAEA,OAFc,OAIrB,CACfb,EAAoB,OAAO,CAAA,CAC7B,EACC,CACDA,EACAF,EAAMgB,MACNZ,EACAD,EACAE,CAAc,CACf,EA4BM,MAAA,CACLe,kBA3BwBN,EAAAA,YAAY,IAAM,CAC1C,MAAMO,EAAY,CAChBC,MAAOC,KAAKC,UAAU,CACpBC,aAAc3B,EACd4B,oBAAqB,CACnBC,UAAWvB,EACXwB,WAAYC,EAAAA,wBACd,EACAC,WAAY3B,EACZ4B,WAAY/B,EAAMgC,OAClBC,WAAYjC,EAAMkC,SAAAA,CACnB,EACDC,UAAWtC,EACXuC,MAAO7B,EAAe8B,KAAK,GAAG,CAChC,EACA,MAAO,GAAG3C,CAAmB,IAAI,IAAI4C,gBAAgBjB,CAAS,CAAC,EACjE,EAAG,CACDvB,EACAM,EACAD,EACAH,EAAMgC,OACNhC,EAAMkC,UACNrC,EACAU,CAAc,CACf,EAICM,oBAAAA,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlackChannels.js","sources":["../../../../../src/modules/slack/hooks/useSlackChannels.ts"],"sourcesContent":["import { SlackChannelQueryOptions, useKnockSlackClient } from \"..\";\nimport { GetSlackChannelsResponse, SlackChannel } from \"@knocklabs/client\";\nimport { useEffect, useMemo } from \"react\";\nimport useSWRInfinite from \"swr/infinite\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst MAX_COUNT = 1000;\nconst LIMIT_PER_PAGE = 200;\nconst CHANNEL_TYPES = \"private_channel,public_channel\";\n\nconst QUERY_KEY = \"SLACK_CHANNELS\";\n\ntype UseSlackChannelsProps = {\n queryOptions?: SlackChannelQueryOptions;\n};\n\ntype UseSlackChannelOutput = {\n data: SlackChannel[];\n isLoading: boolean;\n refetch: () => void;\n};\n\ntype QueryKey = [key: string, cursor: string] | null;\n\nfunction getQueryKey(\n pageIndex: number,\n previousPageData: GetSlackChannelsResponse,\n): QueryKey {\n // First page so just pass empty\n if (pageIndex === 0) {\n return [QUERY_KEY, \"\"];\n }\n\n // If there's no more data then return an empty next cursor\n if (previousPageData && [\"\", null].includes(previousPageData.next_cursor)) {\n return null;\n }\n\n // Next cursor exists so pass it\n return [QUERY_KEY, previousPageData.next_cursor ?? \"\"];\n}\n\nfunction useSlackChannels({\n queryOptions,\n}: UseSlackChannelsProps): UseSlackChannelOutput {\n const knock = useKnockClient();\n const { knockSlackChannelId, tenantId, connectionStatus } =\n useKnockSlackClient();\n\n const fetchChannels = (queryKey: QueryKey) => {\n return knock.slack.getChannels({\n tenant: tenantId,\n knockChannelId: knockSlackChannelId,\n queryOptions: {\n ...queryOptions,\n cursor: queryKey ? queryKey[1] : \"\",\n limit: queryOptions?.limitPerPage || LIMIT_PER_PAGE,\n types: queryOptions?.types || CHANNEL_TYPES,\n },\n });\n };\n\n const { data, error, isLoading, isValidating, size, setSize, mutate } =\n useSWRInfinite<GetSlackChannelsResponse>(getQueryKey, fetchChannels, {\n initialSize: 0,\n });\n\n const currentPage = data?.length || 0;\n\n const hasNextPage =\n currentPage === 0 ||\n (data &&\n data[currentPage]?.next_cursor &&\n data[currentPage]?.next_cursor !== \"\");\n\n const slackChannels: SlackChannel[] = useMemo(\n () =>\n (data ?? [])\n .flatMap((page) => page?.slack_channels)\n .filter((channel) => !!channel),\n [data],\n );\n\n const maxCount = queryOptions?.maxCount || MAX_COUNT;\n\n useEffect(() => {\n if (\n connectionStatus === \"connected\" &&\n !error &&\n hasNextPage &&\n !isLoading &&\n !isValidating &&\n slackChannels.length < maxCount\n ) {\n // Fetch a page at a time until we have nothing else left to fetch\n // or we've already hit the max amount of channels to fetch\n setSize(size + 1);\n }\n }, [\n slackChannels.length,\n setSize,\n size,\n hasNextPage,\n isLoading,\n isValidating,\n maxCount,\n error,\n connectionStatus,\n ]);\n\n return {\n data: slackChannels,\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useSlackChannels;\n"],"names":["MAX_COUNT","LIMIT_PER_PAGE","CHANNEL_TYPES","QUERY_KEY","getQueryKey","pageIndex","previousPageData","includes","next_cursor","useSlackChannels","queryOptions","knock","useKnockClient","knockSlackChannelId","tenantId","connectionStatus","useKnockSlackClient","fetchChannels","queryKey","slack","getChannels","tenant","knockChannelId","cursor","limit","limitPerPage","types","data","error","isLoading","isValidating","size","setSize","mutate","useSWRInfinite","initialSize","currentPage","length","hasNextPage","slackChannels","useMemo","flatMap","page","slack_channels","filter","channel","maxCount","useEffect","refetch"],"mappings":"wXAOMA,EAAY,IACZC,EAAiB,IACjBC,EAAgB,iCAEhBC,EAAY,iBAclB,SAASC,EACPC,EACAC,EACU,CAEV,OAAID,IAAc,EACT,CAACF,EAAW,EAAE,EAInBG,GAAoB,CAAC,GAAI,IAAI,EAAEC,SAASD,EAAiBE,WAAW,EAC/D,KAIF,CAACL,EAAWG,EAAiBE,aAAe,EAAE,CACvD,CAEA,SAASC,EAAiB,CACxBC,aAAAA,CACqB,EAA0B,SAC/C,MAAMC,EAAQC,EAAAA,
|
|
1
|
+
{"version":3,"file":"useSlackChannels.js","sources":["../../../../../src/modules/slack/hooks/useSlackChannels.ts"],"sourcesContent":["import { SlackChannelQueryOptions, useKnockSlackClient } from \"..\";\nimport { GetSlackChannelsResponse, SlackChannel } from \"@knocklabs/client\";\nimport { useEffect, useMemo } from \"react\";\nimport useSWRInfinite from \"swr/infinite\";\n\nimport { useKnockClient } from \"../../core\";\n\nconst MAX_COUNT = 1000;\nconst LIMIT_PER_PAGE = 200;\nconst CHANNEL_TYPES = \"private_channel,public_channel\";\n\nconst QUERY_KEY = \"SLACK_CHANNELS\";\n\ntype UseSlackChannelsProps = {\n queryOptions?: SlackChannelQueryOptions;\n};\n\ntype UseSlackChannelOutput = {\n data: SlackChannel[];\n isLoading: boolean;\n refetch: () => void;\n};\n\ntype QueryKey = [key: string, cursor: string] | null;\n\nfunction getQueryKey(\n pageIndex: number,\n previousPageData: GetSlackChannelsResponse,\n): QueryKey {\n // First page so just pass empty\n if (pageIndex === 0) {\n return [QUERY_KEY, \"\"];\n }\n\n // If there's no more data then return an empty next cursor\n if (previousPageData && [\"\", null].includes(previousPageData.next_cursor)) {\n return null;\n }\n\n // Next cursor exists so pass it\n return [QUERY_KEY, previousPageData.next_cursor ?? \"\"];\n}\n\nfunction useSlackChannels({\n queryOptions,\n}: UseSlackChannelsProps): UseSlackChannelOutput {\n const knock = useKnockClient();\n const { knockSlackChannelId, tenantId, connectionStatus } =\n useKnockSlackClient();\n\n const fetchChannels = (queryKey: QueryKey) => {\n return knock.slack.getChannels({\n tenant: tenantId,\n knockChannelId: knockSlackChannelId,\n queryOptions: {\n ...queryOptions,\n cursor: queryKey ? queryKey[1] : \"\",\n limit: queryOptions?.limitPerPage || LIMIT_PER_PAGE,\n types: queryOptions?.types || CHANNEL_TYPES,\n },\n });\n };\n\n const { data, error, isLoading, isValidating, size, setSize, mutate } =\n useSWRInfinite<GetSlackChannelsResponse>(getQueryKey, fetchChannels, {\n initialSize: 0,\n });\n\n const currentPage = data?.length || 0;\n\n const hasNextPage =\n currentPage === 0 ||\n (data &&\n data[currentPage]?.next_cursor &&\n data[currentPage]?.next_cursor !== \"\");\n\n const slackChannels: SlackChannel[] = useMemo(\n () =>\n (data ?? [])\n .flatMap((page) => page?.slack_channels)\n .filter((channel) => !!channel),\n [data],\n );\n\n const maxCount = queryOptions?.maxCount || MAX_COUNT;\n\n useEffect(() => {\n if (\n connectionStatus === \"connected\" &&\n !error &&\n hasNextPage &&\n !isLoading &&\n !isValidating &&\n slackChannels.length < maxCount\n ) {\n // Fetch a page at a time until we have nothing else left to fetch\n // or we've already hit the max amount of channels to fetch\n setSize(size + 1);\n }\n }, [\n slackChannels.length,\n setSize,\n size,\n hasNextPage,\n isLoading,\n isValidating,\n maxCount,\n error,\n connectionStatus,\n ]);\n\n return {\n data: slackChannels,\n isLoading: isLoading || isValidating,\n refetch: () => mutate(),\n };\n}\n\nexport default useSlackChannels;\n"],"names":["MAX_COUNT","LIMIT_PER_PAGE","CHANNEL_TYPES","QUERY_KEY","getQueryKey","pageIndex","previousPageData","includes","next_cursor","useSlackChannels","queryOptions","knock","useKnockClient","knockSlackChannelId","tenantId","connectionStatus","useKnockSlackClient","fetchChannels","queryKey","slack","getChannels","tenant","knockChannelId","cursor","limit","limitPerPage","types","data","error","isLoading","isValidating","size","setSize","mutate","useSWRInfinite","initialSize","currentPage","length","hasNextPage","slackChannels","useMemo","flatMap","page","slack_channels","filter","channel","maxCount","useEffect","refetch"],"mappings":"wXAOMA,EAAY,IACZC,EAAiB,IACjBC,EAAgB,iCAEhBC,EAAY,iBAclB,SAASC,EACPC,EACAC,EACU,CAEV,OAAID,IAAc,EACT,CAACF,EAAW,EAAE,EAInBG,GAAoB,CAAC,GAAI,IAAI,EAAEC,SAASD,EAAiBE,WAAW,EAC/D,KAIF,CAACL,EAAWG,EAAiBE,aAAe,EAAE,CACvD,CAEA,SAASC,EAAiB,CACxBC,aAAAA,CACqB,EAA0B,SAC/C,MAAMC,EAAQC,EAAAA,eAAe,EACvB,CAAEC,oBAAAA,EAAqBC,SAAAA,EAAUC,iBAAAA,GACrCC,sBAAoB,EAEhBC,EAAiBC,GACdP,EAAMQ,MAAMC,YAAY,CAC7BC,OAAQP,EACRQ,eAAgBT,EAChBH,aAAc,CACZ,GAAGA,EACHa,OAAQL,EAAWA,EAAS,CAAC,EAAI,GACjCM,OAAOd,GAAAA,YAAAA,EAAce,eAAgBxB,EACrCyB,OAAOhB,GAAAA,YAAAA,EAAcgB,QAASxB,CAAAA,CAChC,CACD,EAGG,CAAEyB,KAAAA,EAAMC,MAAAA,EAAOC,UAAAA,EAAWC,aAAAA,EAAcC,KAAAA,EAAMC,QAAAA,EAASC,OAAAA,CAAAA,EAC3DC,EAAyC9B,QAAAA,EAAaa,EAAe,CACnEkB,YAAa,CAAA,CACd,EAEGC,GAAcT,GAAAA,YAAAA,EAAMU,SAAU,EAE9BC,EACJF,IAAgB,GACfT,KACCA,EAAAA,EAAKS,CAAW,IAAhBT,YAAAA,EAAmBnB,gBACnBmB,EAAAA,EAAKS,CAAW,IAAhBT,YAAAA,EAAmBnB,eAAgB,GAEjC+B,EAAgCC,EAAAA,QACpC,KACGb,GAAQ,IACNc,QAAkBC,GAAAA,GAAAA,YAAAA,EAAMC,cAAc,EACtCC,UAAoB,CAAC,CAACC,CAAO,EAClC,CAAClB,CAAI,CACP,EAEMmB,GAAWpC,GAAAA,YAAAA,EAAcoC,WAAY9C,EAE3C+C,OAAAA,EAAAA,UAAU,IAAM,CAEZhC,IAAqB,aACrB,CAACa,GACDU,GACA,CAACT,GACD,CAACC,GACDS,EAAcF,OAASS,GAIvBd,EAAQD,EAAO,CAAC,CAEjB,EAAA,CACDQ,EAAcF,OACdL,EACAD,EACAO,EACAT,EACAC,EACAgB,EACAlB,EACAb,CAAgB,CACjB,EAEM,CACLY,KAAMY,EACNV,UAAWA,GAAaC,EACxBkB,QAASA,IAAMf,EAAO,CACxB,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlackConnectionStatus.js","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport { useTranslations } from \"../../i18n\";\n\nexport type ConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"error\"\n | \"disconnecting\";\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 if (!authRes.connection?.ok) {\n return setConnectionStatus(\"disconnected\");\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?.ok && authRes.connection?.error) {\n const errorLabel = formatSlackErrorMessage(authRes.connection?.error);\n setErrorLabel(errorLabel);\n setConnectionStatus(\"error\");\n return;\n }\n\n // This is for any Knock errors that would require a reconnect.\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":"gJA2BMA,EAA2BC,GAAyB,CACxD,MAAMC,EAAcD,EAAaE,UAAU,EAAG,CAAC,EAAEC,
|
|
1
|
+
{"version":3,"file":"useSlackConnectionStatus.js","sources":["../../../../../src/modules/slack/hooks/useSlackConnectionStatus.ts"],"sourcesContent":["import Knock from \"@knocklabs/client\";\nimport { useEffect, useState } from \"react\";\n\nimport { useTranslations } from \"../../i18n\";\n\nexport type ConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"error\"\n | \"disconnecting\";\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 if (!authRes.connection?.ok) {\n return setConnectionStatus(\"disconnected\");\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?.ok && authRes.connection?.error) {\n const errorLabel = formatSlackErrorMessage(authRes.connection?.error);\n setErrorLabel(errorLabel);\n setConnectionStatus(\"error\");\n return;\n }\n\n // This is for any Knock errors that would require a reconnect.\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":"gJA2BMA,EAA2BC,GAAyB,CACxD,MAAMC,EAAcD,EAAaE,UAAU,EAAG,CAAC,EAAEC,YAAY,EACvDC,EAAOJ,EAAaE,UAAU,CAAC,EACrC,OAAOD,GAAAA,YAAAA,EAAaI,OAAOD,GAAME,QAAQ,IAAK,IAChD,EAEA,SAASC,EACPC,EACAC,EACAC,EACgC,CAC1B,KAAA,CAAEC,EAAAA,GAAMC,kBAAgB,EACxB,CAACC,EAAkBC,CAAmB,EAC1CC,EAAAA,SAA2B,YAAY,EACnC,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAwB,IAAI,EAC1D,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAwB,IAAI,EAElEK,OAAAA,EAAAA,UAAU,IAAM,EACU,SAAY,mBAClC,GAAIP,IAAqB,aAErB,GAAA,CACF,MAAMQ,EAAU,MAAMb,EAAMc,MAAMC,UAAU,CAC1CC,OAAQd,EACRe,eAAgBhB,CAAAA,CACjB,EAEGY,IAAAA,EAAAA,EAAQK,aAARL,MAAAA,EAAoBM,GACtB,OAAOb,EAAoB,WAAW,EAWtCO,GARE,GAACA,EAAAA,EAAQK,aAARL,MAAAA,EAAoBM,KAQvBN,EAAQO,OAAS,qBACjBP,GAAAA,EAAAA,EAAQQ,WAARR,YAAAA,EAAkBS,OAAlBT,YAAAA,EAAwBU,WAAYpB,EAAE,wBAAwB,EAE9D,OAAOG,EAAoB,cAAc,EAI3C,GAAI,GAACO,EAAAA,EAAQK,aAARL,MAAAA,EAAoBM,OAAMN,EAAAA,EAAQK,aAARL,MAAAA,EAAoBW,OAAO,CACxD,MAAMhB,EAAajB,GAAwBsB,EAAAA,EAAQK,aAARL,YAAAA,EAAoBW,KAAK,EACpEf,EAAcD,CAAU,EACxBF,EAAoB,OAAO,EAC3B,MAAA,CAKFA,EAAoB,OAAO,OACZ,CACfA,EAAoB,OAAO,CAAA,CAE/B,GAEgB,CAAA,EACf,CAACD,EAAkBH,EAAUD,EAAqBD,EAAMc,MAAOX,CAAC,CAAC,EAE7D,CACLE,iBAAAA,EACAC,oBAAAA,EACAE,WAAAA,EACAC,cAAAA,EACAC,YAAAA,EACAC,eAAAA,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnockProvider.mjs","sources":["../../../../../src/modules/core/context/KnockProvider.tsx"],"sourcesContent":["import Knock, { AuthenticateOptions, LogLevel } from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { I18nContent, KnockI18nProvider } from \"../../i18n\";\nimport { useAuthenticatedKnockClient } from \"../hooks\";\n\nexport interface KnockProviderState {\n knock: Knock;\n}\n\nconst ProviderStateContext = React.createContext<KnockProviderState | null>(\n null,\n);\n\nexport interface KnockProviderProps {\n // Knock client props\n apiKey: string;\n host?: string;\n // Authentication props\n userId: Knock[\"userId\"];\n userToken?: Knock[\"userToken\"];\n onUserTokenExpiring?: AuthenticateOptions[\"onUserTokenExpiring\"];\n timeBeforeExpirationInMs?: AuthenticateOptions[\"timeBeforeExpirationInMs\"];\n // i18n translations\n i18n?: I18nContent;\n logLevel?: LogLevel;\n}\n\nexport const KnockProvider: React.FC<PropsWithChildren<KnockProviderProps>> = ({\n apiKey,\n host,\n logLevel,\n userId,\n userToken,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n children,\n i18n,\n}) => {\n // We memoize the options here so that we don't create a new object on every re-render\n const authenticateOptions = React.useMemo(\n () => ({\n host,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n logLevel,\n }),\n [host, onUserTokenExpiring, timeBeforeExpirationInMs, logLevel],\n );\n\n const knock = useAuthenticatedKnockClient(\n apiKey,\n userId,\n userToken,\n authenticateOptions,\n );\n\n return (\n <ProviderStateContext.Provider\n value={{\n knock,\n }}\n >\n <KnockI18nProvider i18n={i18n}>{children}</KnockI18nProvider>\n </ProviderStateContext.Provider>\n );\n};\n\nexport const useKnockClient = (): Knock => {\n const context = React.useContext(ProviderStateContext) as KnockProviderState;\n if (context === undefined) {\n throw new Error(\"useKnock must be used within a KnockProvider\");\n }\n return context.knock;\n};\n"],"names":["ProviderStateContext","React","createContext","KnockProvider","apiKey","host","logLevel","userId","userToken","onUserTokenExpiring","timeBeforeExpirationInMs","children","i18n","authenticateOptions","useMemo","knock","useAuthenticatedKnockClient","KnockI18nProvider","useKnockClient","context","useContext","undefined","Error"],"mappings":";;;;AAWA,MAAMA,IAAuBC,EAAMC,cACjC,IACF,GAgBaC,IAAiEA,CAAC;AAAA,EAC7EC,QAAAA;AAAAA,EACAC,MAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,QAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,qBAAAA;AAAAA,EACAC,0BAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,MAAAA;AACF,MAAM;AAEEC,QAAAA,IAAsBZ,EAAMa,QAChC,OAAO;AAAA,IACLT,MAAAA;AAAAA,IACAI,qBAAAA;AAAAA,IACAC,0BAAAA;AAAAA,IACAJ,UAAAA;AAAAA,
|
|
1
|
+
{"version":3,"file":"KnockProvider.mjs","sources":["../../../../../src/modules/core/context/KnockProvider.tsx"],"sourcesContent":["import Knock, { AuthenticateOptions, LogLevel } from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\n\nimport { I18nContent, KnockI18nProvider } from \"../../i18n\";\nimport { useAuthenticatedKnockClient } from \"../hooks\";\n\nexport interface KnockProviderState {\n knock: Knock;\n}\n\nconst ProviderStateContext = React.createContext<KnockProviderState | null>(\n null,\n);\n\nexport interface KnockProviderProps {\n // Knock client props\n apiKey: string;\n host?: string;\n // Authentication props\n userId: Knock[\"userId\"];\n userToken?: Knock[\"userToken\"];\n onUserTokenExpiring?: AuthenticateOptions[\"onUserTokenExpiring\"];\n timeBeforeExpirationInMs?: AuthenticateOptions[\"timeBeforeExpirationInMs\"];\n // i18n translations\n i18n?: I18nContent;\n logLevel?: LogLevel;\n}\n\nexport const KnockProvider: React.FC<PropsWithChildren<KnockProviderProps>> = ({\n apiKey,\n host,\n logLevel,\n userId,\n userToken,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n children,\n i18n,\n}) => {\n // We memoize the options here so that we don't create a new object on every re-render\n const authenticateOptions = React.useMemo(\n () => ({\n host,\n onUserTokenExpiring,\n timeBeforeExpirationInMs,\n logLevel,\n }),\n [host, onUserTokenExpiring, timeBeforeExpirationInMs, logLevel],\n );\n\n const knock = useAuthenticatedKnockClient(\n apiKey,\n userId,\n userToken,\n authenticateOptions,\n );\n\n return (\n <ProviderStateContext.Provider\n value={{\n knock,\n }}\n >\n <KnockI18nProvider i18n={i18n}>{children}</KnockI18nProvider>\n </ProviderStateContext.Provider>\n );\n};\n\nexport const useKnockClient = (): Knock => {\n const context = React.useContext(ProviderStateContext) as KnockProviderState;\n if (context === undefined) {\n throw new Error(\"useKnock must be used within a KnockProvider\");\n }\n return context.knock;\n};\n"],"names":["ProviderStateContext","React","createContext","KnockProvider","apiKey","host","logLevel","userId","userToken","onUserTokenExpiring","timeBeforeExpirationInMs","children","i18n","authenticateOptions","useMemo","knock","useAuthenticatedKnockClient","KnockI18nProvider","useKnockClient","context","useContext","undefined","Error"],"mappings":";;;;AAWA,MAAMA,IAAuBC,EAAMC,cACjC,IACF,GAgBaC,IAAiEA,CAAC;AAAA,EAC7EC,QAAAA;AAAAA,EACAC,MAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,QAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,qBAAAA;AAAAA,EACAC,0BAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,MAAAA;AACF,MAAM;AAEEC,QAAAA,IAAsBZ,EAAMa,QAChC,OAAO;AAAA,IACLT,MAAAA;AAAAA,IACAI,qBAAAA;AAAAA,IACAC,0BAAAA;AAAAA,IACAJ,UAAAA;AAAAA,MAEF,CAACD,GAAMI,GAAqBC,GAA0BJ,CAAQ,CAChE,GAEMS,IAAQC,EACZZ,GACAG,GACAC,GACAK,CACF;AAEA,SACG,gBAAAZ,EAAA,cAAAD,EAAqB,UAArB,EACC,OAAO;AAAA,IACLe,OAAAA;AAAAA,EAAAA,EAGF,GAAA,gBAAAd,EAAA,cAACgB,GAAkB,EAAA,MAAAL,EAAA,GAAaD,CAAS,CAC3C;AAEJ,GAEaO,IAAiBA,MAAa;AACnCC,QAAAA,IAAUlB,EAAMmB,WAAWpB,CAAoB;AACrD,MAAImB,MAAYE;AACR,UAAA,IAAIC,MAAM,8CAA8C;AAEhE,SAAOH,EAAQJ;AACjB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuthenticatedKnockClient.mjs","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const stableOptions = useStableOptions(options);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","stableOptions","useStableOptions","useMemo","currentKnock","current","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":";;;;;AAKA,SAASA,EACPC,GACAC,GACAC,GACAC,IAA+B,CAAA,GAC/B;AACMC,EAAAA,EAAAA,aAAaH,GAAQC,GAAW;AAAA,IACpCG,qBAAqBF,KAAAA,gBAAAA,EAASE;AAAAA,IAC9BC,0BAA0BH,KAAAA,gBAAAA,EAASG;AAAAA,EAAAA,CACpC;AACH;AAKA,SAASC,EACPC,GACAP,GACAC,GACAC,IAA2C,CAAA,GAC3C;AACMM,QAAAA,IAAWC,EAAMC,
|
|
1
|
+
{"version":3,"file":"useAuthenticatedKnockClient.mjs","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\n\nimport { useStableOptions } from \"../../core\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const stableOptions = useStableOptions(options);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","stableOptions","useStableOptions","useMemo","currentKnock","current","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":";;;;;AAKA,SAASA,EACPC,GACAC,GACAC,GACAC,IAA+B,CAAA,GAC/B;AACMC,EAAAA,EAAAA,aAAaH,GAAQC,GAAW;AAAA,IACpCG,qBAAqBF,KAAAA,gBAAAA,EAASE;AAAAA,IAC9BC,0BAA0BH,KAAAA,gBAAAA,EAASG;AAAAA,EAAAA,CACpC;AACH;AAKA,SAASC,EACPC,GACAP,GACAC,GACAC,IAA2C,CAAA,GAC3C;AACMM,QAAAA,IAAWC,EAAMC,OAA0B,GAC3CC,IAAgBC,EAAiBV,CAAO;AAEvCO,SAAAA,EAAMI,QAAQ,MAAM;AACzB,UAAMC,IAAeN,EAASO;AAI5BD,QAAAA,KACAA,EAAaE,gBAAgB,MAC5BF,EAAad,WAAWA,KAAUc,EAAab,cAAcA;AAEtCa,aAAAA,EAAAA,GAAcd,GAAQC,GAAWU,CAAa,GAC/DG;AAGT,IAAIA,KACFA,EAAaG,SAAS;AAIlBlB,UAAAA,IAAQ,IAAImB,EAAMX,GAAQ;AAAA,MAC9BY,MAAMR,EAAcQ;AAAAA,MACpBC,UAAUT,EAAcS;AAAAA,IAAAA,CACzB;AAEuBrB,WAAAA,EAAAA,GAAOC,GAAQC,GAAWU,CAAa,GAC/DH,EAASO,UAAUhB,GAEZA;AAAAA,KACN,CAACQ,GAAQP,GAAQC,GAAWU,CAAa,CAAC;AAC/C;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStableOptions.mjs","sources":["../../../../../src/modules/core/hooks/useStableOptions.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport shallow from \"zustand/shallow\";\n\nexport default function useStableOptions<T>(options: T): T {\n const optionsRef = useRef<T>();\n\n return useMemo(() => {\n const currentOptions = optionsRef.current;\n\n if (currentOptions && shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n}\n"],"names":["useStableOptions","options","optionsRef","useRef","useMemo","currentOptions","current","shallow"],"mappings":";;AAGA,SAAwBA,EAAoBC,GAAe;AACzD,QAAMC,IAAaC;
|
|
1
|
+
{"version":3,"file":"useStableOptions.mjs","sources":["../../../../../src/modules/core/hooks/useStableOptions.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { shallow } from \"zustand/shallow\";\n\nexport default function useStableOptions<T>(options: T): T {\n const optionsRef = useRef<T>();\n\n return useMemo(() => {\n const currentOptions = optionsRef.current;\n\n if (currentOptions && shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n}\n"],"names":["useStableOptions","options","optionsRef","useRef","useMemo","currentOptions","current","shallow"],"mappings":";;AAGA,SAAwBA,EAAoBC,GAAe;AACzD,QAAMC,IAAaC,EAAU;AAE7B,SAAOC,EAAQ,MAAM;AACnB,UAAMC,IAAiBH,EAAWI;AAElC,WAAID,KAAkBE,EAAQN,GAASI,CAAc,IAC5CA,KAGTH,EAAWI,UAAUL,GACdA;AAAAA,EAAAA,GACN,CAACA,CAAO,CAAC;AACd;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import Knock, { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (_e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: Knock[\"userId\"],\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockMsTeamsProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockMsTeamsChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockMsTeamsChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","tenantId","connectionStatus","errorLabel","msTeamsProviderKey","knockMsTeamsChannelId"],"mappings":";AAIO,SAASA,EAAiBC,GAAgC;AACxDA,SAAAA,IAAQ,IAAI,OAAOA;AAC5B;AAMO,SAASC,EACdC,GACAC,IAAkC,IAClC;AACI,MAAA;AACIC,UAAAA,IAAWC,EAASH,CAAE;AAKrBI,WAJWC,EAAmBH,GAAU,oBAAII,QAAQ;AAAA,MACzDC,QAAQN,EAAQM;AAAAA,IAAAA,CACjB;AAAA,UAGU;AACJP,WAAAA;AAAAA,
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import Knock, { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (_e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: Knock[\"userId\"],\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockMsTeamsProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function msTeamsProviderKey({\n knockMsTeamsChannelId,\n tenantId,\n connectionStatus,\n errorLabel,\n}: {\n knockMsTeamsChannelId: string;\n tenantId: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockMsTeamsChannelId, tenantId, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","tenantId","connectionStatus","errorLabel","msTeamsProviderKey","knockMsTeamsChannelId"],"mappings":";AAIO,SAASA,EAAiBC,GAAgC;AACxDA,SAAAA,IAAQ,IAAI,OAAOA;AAC5B;AAMO,SAASC,EACdC,GACAC,IAAkC,IAClC;AACI,MAAA;AACIC,UAAAA,IAAWC,EAASH,CAAE;AAKrBI,WAJWC,EAAmBH,GAAU,oBAAII,QAAQ;AAAA,MACzDC,QAAQN,EAAQM;AAAAA,IAAAA,CACjB;AAAA,UAGU;AACJP,WAAAA;AAAAA,EAAAA;AAEX;AAEO,SAASQ,EAAeC,GAAwB;AAC9CA,SAAAA,EAAOC,OAAO,CAAC,EAAEC,gBAAgBF,EAAOG,MAAM,CAAC;AACxD;AAEgBC,SAAAA,EAAqBC,GAAiBC,GAAqB;AAClED,SAAAA,MAASE,SAAYF,IAAOC;AACrC;AAMO,SAASE,EACdC,GACAC,GACAlB,IAA6B,CAAA,GAC7B;AACO,SAAA,CACLiB,GACAC,GACAlB,EAAQmB,QACRnB,EAAQoB,QACRpB,EAAQqB,YACRrB,EAAQsB,QAAQ,EAEfC,OAAQC,OAAMA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;AAMO,SAASC,EAAiB;AAAA,EAC/BC,qBAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,kBAAAA;AAAAA,EACAC,YAAAA;AAMF,GAAG;AACD,SAAO,CAACH,GAAqBC,GAAUC,GAAkBC,CAAU,EAChEP,OAAQC,CAAMA,MAAAA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;AAMO,SAASM,EAAmB;AAAA,EACjCC,uBAAAA;AAAAA,EACAJ,UAAAA;AAAAA,EACAC,kBAAAA;AAAAA,EACAC,YAAAA;AAMF,GAAG;AACD,SAAO,CAACE,GAAuBJ,GAAUC,GAAkBC,CAAU,EAClEP,OAAQC,CAAMA,MAAAA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;"}
|