@workos-inc/widgets 1.20.2-next.1792708307096 → 1.20.2
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 +4 -12
- package/dist/cjs/admin-portal-audit-log-streaming.client.cjs +2 -1
- package/dist/cjs/admin-portal-audit-log-streaming.client.cjs.map +1 -1
- package/dist/cjs/admin-portal-domain-verification.client.cjs +3 -2
- package/dist/cjs/admin-portal-domain-verification.client.cjs.map +1 -1
- package/dist/cjs/admin-portal-sso-connection.client.cjs +2 -1
- package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
- package/dist/cjs/api/api-provider.cjs +23 -1
- package/dist/cjs/api/api-provider.cjs.map +1 -1
- package/dist/cjs/api/api-provider.d.cts.map +1 -1
- package/dist/cjs/api/claims.cjs.map +1 -1
- package/dist/cjs/api/claims.d.cts +2 -1
- package/dist/cjs/api/claims.d.cts.map +1 -1
- package/dist/cjs/api/client-graphql/hooks.cjs +3 -20
- package/dist/cjs/api/client-graphql/hooks.cjs.map +1 -1
- package/dist/cjs/api/client-graphql/hooks.d.cts +3 -12
- package/dist/cjs/api/client-graphql/hooks.d.cts.map +1 -1
- package/dist/cjs/api/client-graphql/query-keys.cjs +25 -0
- package/dist/cjs/api/client-graphql/query-keys.cjs.map +1 -0
- package/dist/cjs/api/client-graphql/query-keys.d.cts +16 -0
- package/dist/cjs/api/client-graphql/query-keys.d.cts.map +1 -0
- package/dist/cjs/components/copy-text.cjs +1 -1
- package/dist/cjs/components/copy-text.cjs.map +1 -1
- package/dist/cjs/components/otp-input.cjs +1 -0
- package/dist/cjs/components/otp-input.cjs.map +1 -1
- package/dist/cjs/directory-sync.client.cjs +2 -1
- package/dist/cjs/directory-sync.client.cjs.map +1 -1
- package/dist/cjs/lib/api/api-key.cjs +4 -3
- package/dist/cjs/lib/api/api-key.cjs.map +1 -1
- package/dist/cjs/lib/api/me.cjs +2 -1
- package/dist/cjs/lib/api/me.cjs.map +1 -1
- package/dist/cjs/lib/api/pipes.cjs +7 -6
- package/dist/cjs/lib/api/pipes.cjs.map +1 -1
- package/dist/cjs/lib/api/user-api-key.cjs +3 -2
- package/dist/cjs/lib/api/user-api-key.cjs.map +1 -1
- package/dist/cjs/lib/use-widgets-invalidator.cjs +3 -2
- package/dist/cjs/lib/use-widgets-invalidator.cjs.map +1 -1
- package/dist/cjs/organization-switcher.client.cjs +2 -1
- package/dist/cjs/organization-switcher.client.cjs.map +1 -1
- package/dist/cjs/pipes-admin.client.cjs +2 -1
- package/dist/cjs/pipes-admin.client.cjs.map +1 -1
- package/dist/cjs/pipes.client.cjs +2 -1
- package/dist/cjs/pipes.client.cjs.map +1 -1
- package/dist/cjs/user-security.client.cjs +2 -1
- package/dist/cjs/user-security.client.cjs.map +1 -1
- package/dist/cjs/user-sessions.client.cjs +2 -1
- package/dist/cjs/user-sessions.client.cjs.map +1 -1
- package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs +9 -4
- package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs.map +1 -1
- package/dist/cjs/widgets/organization-switcher/organization-switcher.d.cts.map +1 -1
- package/dist/cjs/widgets/pipes/pipes.cjs +3 -2
- package/dist/cjs/widgets/pipes/pipes.cjs.map +1 -1
- package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs +2 -1
- package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs.map +1 -1
- package/dist/cjs/widgets/user-sessions/logout-dialog.cjs +2 -1
- package/dist/cjs/widgets/user-sessions/logout-dialog.cjs.map +1 -1
- package/dist/cjs/widgets/users-management/users-management-utils.cjs +4 -3
- package/dist/cjs/widgets/users-management/users-management-utils.cjs.map +1 -1
- package/dist/esm/admin-portal-audit-log-streaming.client.js +2 -1
- package/dist/esm/admin-portal-audit-log-streaming.client.js.map +1 -1
- package/dist/esm/admin-portal-domain-verification.client.js +2 -1
- package/dist/esm/admin-portal-domain-verification.client.js.map +1 -1
- package/dist/esm/admin-portal-sso-connection.client.js +2 -1
- package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
- package/dist/esm/api/api-provider.d.ts.map +1 -1
- package/dist/esm/api/api-provider.js +23 -1
- package/dist/esm/api/api-provider.js.map +1 -1
- package/dist/esm/api/claims.d.ts +2 -1
- package/dist/esm/api/claims.d.ts.map +1 -1
- package/dist/esm/api/claims.js.map +1 -1
- package/dist/esm/api/client-graphql/hooks.d.ts +3 -12
- package/dist/esm/api/client-graphql/hooks.d.ts.map +1 -1
- package/dist/esm/api/client-graphql/hooks.js +1 -18
- package/dist/esm/api/client-graphql/hooks.js.map +1 -1
- package/dist/esm/api/client-graphql/query-keys.d.ts +16 -0
- package/dist/esm/api/client-graphql/query-keys.d.ts.map +1 -0
- package/dist/esm/api/client-graphql/query-keys.js +23 -0
- package/dist/esm/api/client-graphql/query-keys.js.map +1 -0
- package/dist/esm/components/copy-text.js +1 -1
- package/dist/esm/components/copy-text.js.map +1 -1
- package/dist/esm/components/otp-input.js +1 -0
- package/dist/esm/components/otp-input.js.map +1 -1
- package/dist/esm/directory-sync.client.js +2 -1
- package/dist/esm/directory-sync.client.js.map +1 -1
- package/dist/esm/lib/api/api-key.js +2 -1
- package/dist/esm/lib/api/api-key.js.map +1 -1
- package/dist/esm/lib/api/me.js +2 -1
- package/dist/esm/lib/api/me.js.map +1 -1
- package/dist/esm/lib/api/pipes.js +2 -1
- package/dist/esm/lib/api/pipes.js.map +1 -1
- package/dist/esm/lib/api/user-api-key.js +2 -1
- package/dist/esm/lib/api/user-api-key.js.map +1 -1
- package/dist/esm/lib/use-widgets-invalidator.js +2 -1
- package/dist/esm/lib/use-widgets-invalidator.js.map +1 -1
- package/dist/esm/organization-switcher.client.js +2 -1
- package/dist/esm/organization-switcher.client.js.map +1 -1
- package/dist/esm/pipes-admin.client.js +2 -1
- package/dist/esm/pipes-admin.client.js.map +1 -1
- package/dist/esm/pipes.client.js +2 -1
- package/dist/esm/pipes.client.js.map +1 -1
- package/dist/esm/user-security.client.js +2 -1
- package/dist/esm/user-security.client.js.map +1 -1
- package/dist/esm/user-sessions.client.js +2 -1
- package/dist/esm/user-sessions.client.js.map +1 -1
- package/dist/esm/widgets/organization-switcher/organization-switcher.d.ts.map +1 -1
- package/dist/esm/widgets/organization-switcher/organization-switcher.js +9 -4
- package/dist/esm/widgets/organization-switcher/organization-switcher.js.map +1 -1
- package/dist/esm/widgets/pipes/pipes.js +2 -1
- package/dist/esm/widgets/pipes/pipes.js.map +1 -1
- package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js +2 -1
- package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js.map +1 -1
- package/dist/esm/widgets/user-sessions/logout-dialog.js +2 -1
- package/dist/esm/widgets/user-sessions/logout-dialog.js.map +1 -1
- package/dist/esm/widgets/users-management/users-management-utils.js +2 -1
- package/dist/esm/widgets/users-management/users-management-utils.js.map +1 -1
- package/package.json +1 -1
- package/src/api/api-provider.tsx +39 -1
- package/src/api/claims.ts +2 -1
- package/src/api/client-graphql/hooks.ts +8 -27
- package/src/api/client-graphql/query-keys.ts +29 -0
- package/src/components/copy-text.tsx +1 -1
- package/src/components/otp-input.tsx +2 -0
- package/src/widgets/organization-switcher/organization-switcher.tsx +16 -6
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Sdk } from "./generated.js";
|
|
2
|
+
import { QueryKey } from "@tanstack/react-query";
|
|
3
|
+
//#region src/api/client-graphql/query-keys.d.ts
|
|
4
|
+
export type ClientGraphqlOperation = keyof Sdk;
|
|
5
|
+
export type ClientGraphqlVariables<K extends ClientGraphqlOperation> = Parameters<Sdk[K]>[0];
|
|
6
|
+
export declare function isClientGraphqlQueryKey(queryKey: QueryKey): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* React Query key for a Client GraphQL operation. Omit `variables` to address
|
|
9
|
+
* every cached page/variant of an operation, e.g. when invalidating after a
|
|
10
|
+
* mutation:
|
|
11
|
+
*
|
|
12
|
+
* queryClient.invalidateQueries({ queryKey: clientGraphqlQueryKey("Sessions") });
|
|
13
|
+
*/
|
|
14
|
+
export declare function clientGraphqlQueryKey<K extends ClientGraphqlOperation>(operation: K, variables?: ClientGraphqlVariables<K>): QueryKey;
|
|
15
|
+
//#endregion
|
|
16
|
+
//# sourceMappingURL=query-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-keys.d.ts","names":[],"sources":["../../../../src/api/client-graphql/query-keys.ts"],"mappings":";;;YAGY,+BAA+B;YAE/B,uBAAuB,UAAU,0BAC3C,WAAW,IAAI;wBAID,wBAAwB,UAAU;;;;;;;;wBAWlC,sBAAsB,UAAU,wBAC9C,WAAW,GACX,YAAY,uBAAuB,KAClC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/api/client-graphql/query-keys.ts
|
|
2
|
+
const CLIENT_GRAPHQL_KEY_PREFIX = "client-graphql";
|
|
3
|
+
function isClientGraphqlQueryKey(queryKey) {
|
|
4
|
+
return queryKey[0] === CLIENT_GRAPHQL_KEY_PREFIX;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* React Query key for a Client GraphQL operation. Omit `variables` to address
|
|
8
|
+
* every cached page/variant of an operation, e.g. when invalidating after a
|
|
9
|
+
* mutation:
|
|
10
|
+
*
|
|
11
|
+
* queryClient.invalidateQueries({ queryKey: clientGraphqlQueryKey("Sessions") });
|
|
12
|
+
*/
|
|
13
|
+
function clientGraphqlQueryKey(operation, variables) {
|
|
14
|
+
return variables === void 0 ? [CLIENT_GRAPHQL_KEY_PREFIX, operation] : [
|
|
15
|
+
CLIENT_GRAPHQL_KEY_PREFIX,
|
|
16
|
+
operation,
|
|
17
|
+
variables
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { clientGraphqlQueryKey, isClientGraphqlQueryKey };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=query-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-keys.js","names":[],"sources":["../../../../src/api/client-graphql/query-keys.ts"],"sourcesContent":["import type { QueryKey } from \"@tanstack/react-query\";\nimport type { Sdk } from \"./generated.js\";\n\nexport type ClientGraphqlOperation = keyof Sdk;\n\nexport type ClientGraphqlVariables<K extends ClientGraphqlOperation> =\n Parameters<Sdk[K]>[0];\n\nconst CLIENT_GRAPHQL_KEY_PREFIX = \"client-graphql\";\n\nexport function isClientGraphqlQueryKey(queryKey: QueryKey): boolean {\n return queryKey[0] === CLIENT_GRAPHQL_KEY_PREFIX;\n}\n\n/**\n * React Query key for a Client GraphQL operation. Omit `variables` to address\n * every cached page/variant of an operation, e.g. when invalidating after a\n * mutation:\n *\n * queryClient.invalidateQueries({ queryKey: clientGraphqlQueryKey(\"Sessions\") });\n */\nexport function clientGraphqlQueryKey<K extends ClientGraphqlOperation>(\n operation: K,\n variables?: ClientGraphqlVariables<K>,\n): QueryKey {\n return variables === undefined\n ? [CLIENT_GRAPHQL_KEY_PREFIX, operation]\n : [CLIENT_GRAPHQL_KEY_PREFIX, operation, variables];\n}\n"],"mappings":";AAQA,MAAM,4BAA4B;AAElC,SAAgB,wBAAwB,UAA6B;CACnE,OAAO,SAAS,OAAO;AACzB;;;;;;;;AASA,SAAgB,sBACd,WACA,WACU;CACV,OAAO,cAAc,SACjB,CAAC,2BAA2B,SAAS,IACrC;EAAC;EAA2B;EAAW;CAAS;AACtD"}
|
|
@@ -46,7 +46,7 @@ const CopyText = ({ value, label }) => {
|
|
|
46
46
|
title: copyLabel,
|
|
47
47
|
variant: "ghost",
|
|
48
48
|
size: "1",
|
|
49
|
-
"aria-
|
|
49
|
+
"aria-label": copyLabel,
|
|
50
50
|
className: namespaceClassName("copy-text__copy"),
|
|
51
51
|
onClick: async (event) => {
|
|
52
52
|
const button = event.currentTarget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy-text.js","names":["IconButton"],"sources":["../../../src/components/copy-text.tsx"],"sourcesContent":["\"use client\";\nimport { CheckIcon, CopyIcon } from \"@radix-ui/react-icons\";\nimport { Flex, Text } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useTranslation } from \"../lib/i18n/use-translation.js\";\nimport { namespaceClassName } from \"../lib/widget-dom-props.js\";\nimport { IconButton } from \"./elements.js\";\n\ninterface CopyTextProps {\n value: string;\n /** Accessible label for the copy button. Defaults to a generic \"Copy\". */\n label?: string;\n}\n\n/**\n * Minimal reusable copy-on-hover text row, modeled on the dashboard's\n * `CopyText`: renders `value` on a single truncated line with a copy button\n * that reveals on hover or keyboard focus (see `copy-text.css`). The copy\n * button blurs itself shortly after a copy so it doesn't linger via\n * `:focus-within`.\n */\nconst CopyText: React.FC<CopyTextProps> = ({ value, label }) => {\n const [copied, setCopied] = React.useState(false);\n const stateTimeoutRef = React.useRef<number | undefined>(undefined);\n const blurTimeoutRef = React.useRef<number | undefined>(undefined);\n const translate = useTranslation();\n\n const copyLabel =\n label ??\n translate({\n defaultMessage: \"Copy to clipboard\",\n id: \"44uBwv\",\n description: \"Default accessible label for a copy-to-clipboard button\",\n });\n\n React.useEffect(() => {\n return () => {\n window.clearTimeout(stateTimeoutRef.current);\n window.clearTimeout(blurTimeoutRef.current);\n };\n }, []);\n\n const Icon = copied ? CheckIcon : CopyIcon;\n\n return (\n <Flex className={namespaceClassName(\"copy-text\")} gap=\"2\" align=\"center\">\n <Text\n size=\"2\"\n title={value}\n className={namespaceClassName(\"copy-text__value\")}\n >\n {value}\n </Text>\n <IconButton\n type=\"button\"\n title={copyLabel}\n variant=\"ghost\"\n size=\"1\"\n aria-
|
|
1
|
+
{"version":3,"file":"copy-text.js","names":["IconButton"],"sources":["../../../src/components/copy-text.tsx"],"sourcesContent":["\"use client\";\nimport { CheckIcon, CopyIcon } from \"@radix-ui/react-icons\";\nimport { Flex, Text } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useTranslation } from \"../lib/i18n/use-translation.js\";\nimport { namespaceClassName } from \"../lib/widget-dom-props.js\";\nimport { IconButton } from \"./elements.js\";\n\ninterface CopyTextProps {\n value: string;\n /** Accessible label for the copy button. Defaults to a generic \"Copy\". */\n label?: string;\n}\n\n/**\n * Minimal reusable copy-on-hover text row, modeled on the dashboard's\n * `CopyText`: renders `value` on a single truncated line with a copy button\n * that reveals on hover or keyboard focus (see `copy-text.css`). The copy\n * button blurs itself shortly after a copy so it doesn't linger via\n * `:focus-within`.\n */\nconst CopyText: React.FC<CopyTextProps> = ({ value, label }) => {\n const [copied, setCopied] = React.useState(false);\n const stateTimeoutRef = React.useRef<number | undefined>(undefined);\n const blurTimeoutRef = React.useRef<number | undefined>(undefined);\n const translate = useTranslation();\n\n const copyLabel =\n label ??\n translate({\n defaultMessage: \"Copy to clipboard\",\n id: \"44uBwv\",\n description: \"Default accessible label for a copy-to-clipboard button\",\n });\n\n React.useEffect(() => {\n return () => {\n window.clearTimeout(stateTimeoutRef.current);\n window.clearTimeout(blurTimeoutRef.current);\n };\n }, []);\n\n const Icon = copied ? CheckIcon : CopyIcon;\n\n return (\n <Flex className={namespaceClassName(\"copy-text\")} gap=\"2\" align=\"center\">\n <Text\n size=\"2\"\n title={value}\n className={namespaceClassName(\"copy-text__value\")}\n >\n {value}\n </Text>\n <IconButton\n type=\"button\"\n title={copyLabel}\n variant=\"ghost\"\n size=\"1\"\n aria-label={copyLabel}\n className={namespaceClassName(\"copy-text__copy\")}\n onClick={async (event) => {\n const button = event.currentTarget;\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n stateTimeoutRef.current = window.setTimeout(\n () => setCopied(false),\n 2000,\n );\n } catch {\n // clipboard unavailable; ignore\n }\n // Blur after the confirmation so the button doesn't stay revealed\n // via :focus-within once the pointer leaves.\n blurTimeoutRef.current = window.setTimeout(() => {\n if (button.isConnected) {\n button.blur();\n }\n }, 1800);\n }}\n >\n <Icon aria-hidden />\n </IconButton>\n </Flex>\n );\n};\nexport type { CopyTextProps };\nexport { CopyText };\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,MAAM,YAAqC,EAAE,OAAO,YAAY;CAC9D,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,kBAAkB,MAAM,OAA2B,MAAS;CAClE,MAAM,iBAAiB,MAAM,OAA2B,MAAS;CACjE,MAAM,YAAY,eAAe;CAEjC,MAAM,YACJ,SACA,UAAU;EACR,gBAAgB;EAChB,IAAI;EACJ,aAAa;CACf,CAAC;CAEH,MAAM,gBAAgB;EACpB,aAAa;GACX,OAAO,aAAa,gBAAgB,OAAO;GAC3C,OAAO,aAAa,eAAe,OAAO;EAC5C;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,OAAO,SAAS,YAAY;CAElC,OACE,qBAAC,MAAD;EAAM,WAAW,mBAAmB,WAAW;EAAG,KAAI;EAAI,OAAM;EAAhE,UAAA,CACE,oBAAC,MAAD;GACE,MAAK;GACL,OAAO;GACP,WAAW,mBAAmB,kBAAkB;GAE/C,UAAA;EACG,CAAA,GACN,oBAACA,cAAD;GACE,MAAK;GACL,OAAO;GACP,SAAQ;GACR,MAAK;GACL,cAAY;GACZ,WAAW,mBAAmB,iBAAiB;GAC/C,SAAS,OAAO,UAAU;IACxB,MAAM,SAAS,MAAM;IACrB,IAAI;KACF,MAAM,UAAU,UAAU,UAAU,KAAK;KACzC,UAAU,IAAI;KACd,gBAAgB,UAAU,OAAO,iBACzB,UAAU,KAAK,GACrB,GACF;IACF,QAAQ,CAER;IAGA,eAAe,UAAU,OAAO,iBAAiB;KAC/C,IAAI,OAAO,aACT,OAAO,KAAK;IAEhB,GAAG,IAAI;GACT;GAEA,UAAA,oBAAC,MAAD,EAAM,eAAA,KAAa,CAAA;EACT,CAAA,CACR;;AAEV"}
|
|
@@ -139,6 +139,7 @@ const OtpInput = React.forwardRef(function OtpInput({ style, readOnly, autoCompl
|
|
|
139
139
|
} else if (event.key === "Backspace" && char === "") focusSibling(event.currentTarget, { back: true });
|
|
140
140
|
else if (event.key === "Enter" && char !== "") otpContext.onEnterPressed();
|
|
141
141
|
},
|
|
142
|
+
"data-index": index,
|
|
142
143
|
...props
|
|
143
144
|
})
|
|
144
145
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp-input.js","names":["Form.Field","Form.Control","TextField.Root"],"sources":["../../../src/components/otp-input.tsx"],"sourcesContent":["\"use client\";\nimport { Grid } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { TextField } from \"./elements.js\";\nimport * as Form from \"./form.js\";\n\ninterface OtpContextValue {\n value: string[];\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n onEnterPressed: () => void;\n onCharChange: (char: string, index: number) => void;\n onChildAdd: (element: HTMLInputElement | null, index: number) => void;\n}\n\nconst OtpContext = React.createContext<OtpContextValue | undefined>(undefined);\nOtpContext.displayName = \"OtpContext\";\n\nconst OtpIndexContext = React.createContext<number>(-1);\nOtpIndexContext.displayName = \"OtpIndexContext\";\n\ntype OtpRootProps = React.ComponentPropsWithoutRef<typeof Grid> & {\n id?: string;\n name?: string;\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n value: string;\n onValueChange: React.Dispatch<React.SetStateAction<string>>;\n autoSubmit?: boolean;\n};\n\nconst OtpRoot = React.forwardRef<HTMLInputElement, OtpRootProps>(\n function OtpRoot(\n {\n name,\n id,\n value: valueProp,\n onValueChange,\n autoSubmit,\n children,\n readOnly,\n state,\n ...gridProps\n },\n forwardedRef,\n ) {\n const [lastCharIndex, setLastCharIndex] = React.useState<number>(0);\n const childCount = React.Children.count(children);\n\n // Internal array state is the source of truth so that empty slots between\n // filled digits are preserved. A `value` string can't encode a gap (e.g.\n // `[\"1\", \"\", \"3\"]` and `[\"1\", \"3\"]` both serialize to \"13\"), so deriving\n // state straight from the prop would shift digits whenever an inner box is\n // cleared or filled out of order.\n const [value, setValueState] = React.useState<string[]>(() =>\n getValueAsArray(valueProp, childCount),\n );\n\n const [previousValueProp, setPreviousValueProp] = React.useState(valueProp);\n if (previousValueProp !== valueProp) {\n setPreviousValueProp(valueProp);\n if (valueProp !== value.join(\"\")) {\n setValueState(getValueAsArray(valueProp, childCount));\n }\n }\n\n const setValue = React.useCallback(\n (action: React.SetStateAction<string[]>) => {\n const nextArrayValue =\n typeof action === \"function\" ? action(value) : action;\n setValueState(nextArrayValue);\n onValueChange(nextArrayValue.join(\"\"));\n },\n [value, onValueChange],\n );\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n const childrenRefs = React.useRef<(HTMLInputElement | null)[]>([]);\n\n const attemptAutoSubmit = React.useCallback(\n (enterPressed = false) => {\n if (\n autoSubmit &&\n value.length > 0 &&\n value.every((char) => char !== \"\") &&\n (enterPressed || lastCharIndex + 1 === childCount)\n ) {\n hiddenInputRef.current?.form?.requestSubmit();\n }\n },\n [value, childCount, lastCharIndex, autoSubmit],\n );\n\n const handleEnterPressed = React.useCallback(\n () => attemptAutoSubmit(true),\n [attemptAutoSubmit],\n );\n\n const handleChildAdd = React.useCallback(\n (element: HTMLInputElement | null, index: number) => {\n childrenRefs.current[index] = element;\n },\n [],\n );\n\n const handleCharChange = React.useCallback(\n (char: string, index: number) => {\n setValue((previousValue) => {\n const newValue = [...previousValue];\n newValue[index] = char;\n return newValue;\n });\n setLastCharIndex(index);\n },\n [setValue],\n );\n\n const otpContext = React.useMemo<OtpContextValue>(\n () =>\n ({\n value,\n readOnly,\n state,\n onEnterPressed: handleEnterPressed,\n onCharChange: handleCharChange,\n onChildAdd: handleChildAdd,\n }) satisfies OtpContextValue,\n [\n value,\n readOnly,\n state,\n handleEnterPressed,\n handleCharChange,\n handleChildAdd,\n ],\n );\n\n React.useEffect(attemptAutoSubmit, [attemptAutoSubmit]);\n\n return (\n <OtpContext.Provider value={otpContext}>\n <Grid\n columns={`repeat(${childCount}, 1fr)`}\n {...gridProps}\n onPaste={(event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData(\"Text\");\n const sanitizedValue = pastedValue\n .replace(/[^\\d]/g, \"\")\n .slice(0, childCount);\n const value = sanitizedValue\n .padEnd(childCount, \"#\")\n .split(\"\")\n .map((char) => (char === \"#\" ? \"\" : char));\n\n setValue(value);\n setLastCharIndex(sanitizedValue.length - 1);\n\n const index = Math.min(sanitizedValue.length, childCount - 1);\n childrenRefs.current?.[index]?.focus();\n }}\n >\n {React.Children.map(children, (child, index) => (\n <OtpIndexContext.Provider value={index}>\n {child}\n </OtpIndexContext.Provider>\n ))}\n <input\n ref={useComposedRefs(forwardedRef, hiddenInputRef)}\n defaultValue={value.join(\"\")}\n minLength={childCount}\n name={name}\n type=\"hidden\"\n />\n </Grid>\n </OtpContext.Provider>\n );\n },\n);\nOtpRoot.displayName = \"Otp.Root\";\n\ninterface OtpInputProps extends TextField.RootProps {\n autoComplete?: \"one-time-code\" | \"off\";\n}\n\nconst OtpInput = React.forwardRef<HTMLInputElement, OtpInputProps>(\n function OtpInput(\n { style, readOnly, autoComplete = \"off\", ...props },\n forwardedRef,\n ) {\n const otpContext = useOptContext();\n const { onChildAdd } = otpContext;\n const index = React.useContext(OtpIndexContext);\n const inputRef = React.useCallback(\n (input: HTMLInputElement | null) => {\n onChildAdd(input, index);\n },\n [onChildAdd, index],\n );\n const composedInputRef = useComposedRefs(forwardedRef, inputRef);\n\n const char = otpContext.value[index] ?? \"\";\n\n return (\n <Form.Field name={`otp-${index}`} asChild>\n <Form.Control asChild>\n <TextField.Root\n ref={composedInputRef}\n autoComplete={index === 0 ? autoComplete : \"off\"}\n color={otpContext.state === \"invalid\" ? \"red\" : undefined}\n inputMode=\"numeric\"\n maxLength={1}\n pattern=\"\\d{1}\"\n readOnly={readOnly ?? otpContext.readOnly}\n size=\"3\"\n value={char}\n variant={otpContext.state === \"invalid\" ? \"soft\" : undefined}\n style={{\n ...style,\n height: \"auto\",\n \"--text-field-padding\": 0,\n textAlign: \"center\",\n }}\n onChange={(event) => {\n // Update the value if it matches the input pattern (number only) or is empty (backspace)\n if (event.target.validity.valid || event.target.value === \"\") {\n const char = event.target.value;\n otpContext.onCharChange(char, index);\n focusSibling(event.currentTarget, { back: char === \"\" });\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"ArrowLeft\") {\n focusSibling(event.currentTarget, { back: true });\n event.preventDefault();\n } else if (event.key === \"ArrowRight\") {\n focusSibling(event.currentTarget);\n event.preventDefault();\n } else if (event.key === \"Backspace\" && char === \"\") {\n focusSibling(event.currentTarget, { back: true });\n } else if (event.key === \"Enter\" && char !== \"\") {\n otpContext.onEnterPressed();\n }\n }}\n {...props}\n />\n </Form.Control>\n </Form.Field>\n );\n },\n);\nOtpInput.displayName = \"Otp.Input\";\n\nconst useOptContext = () => {\n const optContext = React.useContext(OtpContext);\n if (!optContext) {\n throw new Error(\n \"OtpInput compound components cannot be rendered outside the OtpRoot component\",\n );\n }\n\n return optContext;\n};\n\nfunction focusSibling(input: HTMLInputElement, { back = false } = {}) {\n const sibling = back\n ? input.parentElement?.previousSibling\n : input.parentElement?.nextSibling;\n const siblingInput = sibling?.firstChild;\n if (siblingInput && siblingInput instanceof HTMLInputElement) {\n siblingInput?.focus();\n siblingInput?.select();\n }\n}\n\nconst getValueAsArray = (value: string | undefined, length: number) => {\n if (!value) {\n return createEmptyArray(length);\n }\n\n return createEmptyArray(length).map((_, index) => value?.[index] ?? \"\");\n};\n\nconst createEmptyArray = (length: number): string[] =>\n Array.from<string>({ length }).fill(\"\");\nexport { OtpRoot as Root, OtpInput as Input };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"otp-input.js","names":["Form.Field","Form.Control","TextField.Root"],"sources":["../../../src/components/otp-input.tsx"],"sourcesContent":["\"use client\";\nimport { Grid } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { TextField } from \"./elements.js\";\nimport * as Form from \"./form.js\";\n\ninterface OtpContextValue {\n value: string[];\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n onEnterPressed: () => void;\n onCharChange: (char: string, index: number) => void;\n onChildAdd: (element: HTMLInputElement | null, index: number) => void;\n}\n\nconst OtpContext = React.createContext<OtpContextValue | undefined>(undefined);\nOtpContext.displayName = \"OtpContext\";\n\nconst OtpIndexContext = React.createContext<number>(-1);\nOtpIndexContext.displayName = \"OtpIndexContext\";\n\ntype OtpRootProps = React.ComponentPropsWithoutRef<typeof Grid> & {\n id?: string;\n name?: string;\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n value: string;\n onValueChange: React.Dispatch<React.SetStateAction<string>>;\n autoSubmit?: boolean;\n};\n\nconst OtpRoot = React.forwardRef<HTMLInputElement, OtpRootProps>(\n function OtpRoot(\n {\n name,\n id,\n value: valueProp,\n onValueChange,\n autoSubmit,\n children,\n readOnly,\n state,\n ...gridProps\n },\n forwardedRef,\n ) {\n const [lastCharIndex, setLastCharIndex] = React.useState<number>(0);\n const childCount = React.Children.count(children);\n\n // Internal array state is the source of truth so that empty slots between\n // filled digits are preserved. A `value` string can't encode a gap (e.g.\n // `[\"1\", \"\", \"3\"]` and `[\"1\", \"3\"]` both serialize to \"13\"), so deriving\n // state straight from the prop would shift digits whenever an inner box is\n // cleared or filled out of order.\n const [value, setValueState] = React.useState<string[]>(() =>\n getValueAsArray(valueProp, childCount),\n );\n\n const [previousValueProp, setPreviousValueProp] = React.useState(valueProp);\n if (previousValueProp !== valueProp) {\n setPreviousValueProp(valueProp);\n if (valueProp !== value.join(\"\")) {\n setValueState(getValueAsArray(valueProp, childCount));\n }\n }\n\n const setValue = React.useCallback(\n (action: React.SetStateAction<string[]>) => {\n const nextArrayValue =\n typeof action === \"function\" ? action(value) : action;\n setValueState(nextArrayValue);\n onValueChange(nextArrayValue.join(\"\"));\n },\n [value, onValueChange],\n );\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n const childrenRefs = React.useRef<(HTMLInputElement | null)[]>([]);\n\n const attemptAutoSubmit = React.useCallback(\n (enterPressed = false) => {\n if (\n autoSubmit &&\n value.length > 0 &&\n value.every((char) => char !== \"\") &&\n (enterPressed || lastCharIndex + 1 === childCount)\n ) {\n hiddenInputRef.current?.form?.requestSubmit();\n }\n },\n [value, childCount, lastCharIndex, autoSubmit],\n );\n\n const handleEnterPressed = React.useCallback(\n () => attemptAutoSubmit(true),\n [attemptAutoSubmit],\n );\n\n const handleChildAdd = React.useCallback(\n (element: HTMLInputElement | null, index: number) => {\n childrenRefs.current[index] = element;\n },\n [],\n );\n\n const handleCharChange = React.useCallback(\n (char: string, index: number) => {\n setValue((previousValue) => {\n const newValue = [...previousValue];\n newValue[index] = char;\n return newValue;\n });\n setLastCharIndex(index);\n },\n [setValue],\n );\n\n const otpContext = React.useMemo<OtpContextValue>(\n () =>\n ({\n value,\n readOnly,\n state,\n onEnterPressed: handleEnterPressed,\n onCharChange: handleCharChange,\n onChildAdd: handleChildAdd,\n }) satisfies OtpContextValue,\n [\n value,\n readOnly,\n state,\n handleEnterPressed,\n handleCharChange,\n handleChildAdd,\n ],\n );\n\n React.useEffect(attemptAutoSubmit, [attemptAutoSubmit]);\n\n return (\n <OtpContext.Provider value={otpContext}>\n <Grid\n columns={`repeat(${childCount}, 1fr)`}\n {...gridProps}\n onPaste={(event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData(\"Text\");\n const sanitizedValue = pastedValue\n .replace(/[^\\d]/g, \"\")\n .slice(0, childCount);\n const value = sanitizedValue\n .padEnd(childCount, \"#\")\n .split(\"\")\n .map((char) => (char === \"#\" ? \"\" : char));\n\n setValue(value);\n setLastCharIndex(sanitizedValue.length - 1);\n\n const index = Math.min(sanitizedValue.length, childCount - 1);\n childrenRefs.current?.[index]?.focus();\n }}\n >\n {React.Children.map(children, (child, index) => (\n <OtpIndexContext.Provider value={index}>\n {child}\n </OtpIndexContext.Provider>\n ))}\n <input\n ref={useComposedRefs(forwardedRef, hiddenInputRef)}\n defaultValue={value.join(\"\")}\n minLength={childCount}\n name={name}\n type=\"hidden\"\n />\n </Grid>\n </OtpContext.Provider>\n );\n },\n);\nOtpRoot.displayName = \"Otp.Root\";\n\ninterface OtpInputProps extends TextField.RootProps {\n autoComplete?: \"one-time-code\" | \"off\";\n}\n\nconst OtpInput = React.forwardRef<HTMLInputElement, OtpInputProps>(\n function OtpInput(\n { style, readOnly, autoComplete = \"off\", ...props },\n forwardedRef,\n ) {\n const otpContext = useOptContext();\n const { onChildAdd } = otpContext;\n const index = React.useContext(OtpIndexContext);\n const inputRef = React.useCallback(\n (input: HTMLInputElement | null) => {\n onChildAdd(input, index);\n },\n [onChildAdd, index],\n );\n const composedInputRef = useComposedRefs(forwardedRef, inputRef);\n\n const char = otpContext.value[index] ?? \"\";\n\n return (\n <Form.Field name={`otp-${index}`} asChild>\n <Form.Control asChild>\n <TextField.Root\n ref={composedInputRef}\n autoComplete={index === 0 ? autoComplete : \"off\"}\n color={otpContext.state === \"invalid\" ? \"red\" : undefined}\n inputMode=\"numeric\"\n maxLength={1}\n pattern=\"\\d{1}\"\n readOnly={readOnly ?? otpContext.readOnly}\n size=\"3\"\n value={char}\n variant={otpContext.state === \"invalid\" ? \"soft\" : undefined}\n style={{\n ...style,\n height: \"auto\",\n \"--text-field-padding\": 0,\n textAlign: \"center\",\n }}\n onChange={(event) => {\n // Update the value if it matches the input pattern (number only) or is empty (backspace)\n if (event.target.validity.valid || event.target.value === \"\") {\n const char = event.target.value;\n otpContext.onCharChange(char, index);\n focusSibling(event.currentTarget, { back: char === \"\" });\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"ArrowLeft\") {\n focusSibling(event.currentTarget, { back: true });\n event.preventDefault();\n } else if (event.key === \"ArrowRight\") {\n focusSibling(event.currentTarget);\n event.preventDefault();\n } else if (event.key === \"Backspace\" && char === \"\") {\n focusSibling(event.currentTarget, { back: true });\n } else if (event.key === \"Enter\" && char !== \"\") {\n otpContext.onEnterPressed();\n }\n }}\n // TODO(v2): remove; we're no longer using it\n data-index={index}\n {...props}\n />\n </Form.Control>\n </Form.Field>\n );\n },\n);\nOtpInput.displayName = \"Otp.Input\";\n\nconst useOptContext = () => {\n const optContext = React.useContext(OtpContext);\n if (!optContext) {\n throw new Error(\n \"OtpInput compound components cannot be rendered outside the OtpRoot component\",\n );\n }\n\n return optContext;\n};\n\nfunction focusSibling(input: HTMLInputElement, { back = false } = {}) {\n const sibling = back\n ? input.parentElement?.previousSibling\n : input.parentElement?.nextSibling;\n const siblingInput = sibling?.firstChild;\n if (siblingInput && siblingInput instanceof HTMLInputElement) {\n siblingInput?.focus();\n siblingInput?.select();\n }\n}\n\nconst getValueAsArray = (value: string | undefined, length: number) => {\n if (!value) {\n return createEmptyArray(length);\n }\n\n return createEmptyArray(length).map((_, index) => value?.[index] ?? \"\");\n};\n\nconst createEmptyArray = (length: number): string[] =>\n Array.from<string>({ length }).fill(\"\");\nexport { OtpRoot as Root, OtpInput as Input };\n"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useWorkOsApiUrl } from "./lib/widgets-context.js";
|
|
3
|
+
import { clientGraphqlQueryKey } from "./api/client-graphql/query-keys.js";
|
|
3
4
|
import { ApiProvider, useApiReady } from "./api/api-provider.js";
|
|
4
|
-
import {
|
|
5
|
+
import { useClientGraphqlMutation, useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
|
|
5
6
|
import { ErrorBoundary } from "./components/error-boundary.js";
|
|
6
7
|
import { openUrlViaForm } from "./lib/utils.js";
|
|
7
8
|
import { usePermissions } from "./lib/use-permissions.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-sync.client.js","names":["DirectorySyncPresentational"],"sources":["../../src/directory-sync.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport type {\n DirectoryFieldsFragment,\n Sdk,\n} from \"./api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { usePermissions } from \"./lib/use-permissions.js\";\nimport { openUrlViaForm } from \"./lib/utils.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n DirectoryState,\n DirectorySyncError,\n DirectorySyncLoading,\n DirectorySync as DirectorySyncPresentational,\n isDirectoryState,\n} from \"./widgets/directory-sync/directory-sync.js\";\nimport type {\n DirectorySyncErrorProps,\n DirectorySyncLoadingProps,\n} from \"./widgets/directory-sync/directory-sync.js\";\n\nconst DIRECTORIES_PAGE_SIZE = 100;\n\nasync function listAllDirectoryConnections(\n sdk: Sdk,\n): Promise<DirectoryFieldsFragment[]> {\n const directories: DirectoryFieldsFragment[] = [];\n let after: string | null = null;\n do {\n const { directoryConnections } = await sdk.ListDirectoryConnections({\n after,\n limit: DIRECTORIES_PAGE_SIZE,\n });\n directories.push(...directoryConnections.data);\n after = directoryConnections.listMetadata.after ?? null;\n } while (after !== null);\n // Directories awaiting a type or mid-deletion are not usable by the\n // organization; treat them as not set up.\n return directories.filter(\n (directory) =>\n isDirectoryState(directory.state) &&\n directory.state !== DirectoryState.requires_type &&\n directory.state !== DirectoryState.deleting,\n );\n}\n\ninterface DirectorySyncProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst DirectorySync: React.FC<DirectorySyncProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError {...domProps} error={error} />\n )}\n >\n <ApiProvider\n widgetType=\"directory-sync\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <DirectorySyncImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface DirectorySyncImplProps extends WidgetRootDomProps {}\n\nconst DirectorySyncImpl: React.FC<DirectorySyncImplProps> = (props) => {\n const isApiReady = useApiReady();\n const {\n data: directories,\n isLoading,\n isError,\n error,\n } = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDirectoryConnections\"),\n queryFn: listAllDirectoryConnections,\n });\n const permissionsQuery = usePermissions(\"widgets:dsync:manage\");\n const { mutate: openAdminPortal, isPending: isOpeningAdminPortal } =\n useClientGraphqlMutation({\n mutationFn: (sdk) => sdk.CreateAdminPortalLink({ intent: \"Dsync\" }),\n onSuccess: (data) => {\n openUrlViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n if (!isApiReady || isLoading || permissionsQuery.isLoading) {\n return <DirectorySyncLoading {...props} />;\n }\n\n if (permissionsQuery.isError || isError) {\n return (\n <DirectorySyncError error={permissionsQuery.error || error} {...props} />\n );\n }\n\n const adminPortalProps = {\n onOpenAdminPortal: () => openAdminPortal(),\n isOpeningAdminPortal,\n };\n\n if (!directories?.length) {\n return (\n <DirectorySyncPresentational\n {...props}\n state={DirectoryState.unlinked}\n {...adminPortalProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError error={error} {...props} />\n )}\n >\n {directories.map((directory) => {\n const { id, state, type, metadata, lastSyncRunAt } = directory;\n const commonProps = {\n ...props,\n type,\n metadata,\n lastSyncAt: lastSyncRunAt ?? null,\n ...adminPortalProps,\n };\n\n if (!isDirectoryState(state)) {\n return null;\n }\n\n switch (state) {\n case DirectoryState.invalid_credentials:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory credentials are invalid or have expired. Please re-authenticate to resume syncing.\"\n />\n );\n case DirectoryState.linked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.validating:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.deleting:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.unlinked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.requires_type:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory requires additional configuration. Please complete setup to begin syncing.\"\n />\n );\n }\n })}\n </ErrorBoundary>\n );\n};\n\nexport type {\n DirectorySyncProps,\n DirectorySyncLoadingProps,\n DirectorySyncErrorProps,\n};\nexport { DirectorySync, DirectorySyncLoading, DirectorySyncError };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"directory-sync.client.js","names":["DirectorySyncPresentational"],"sources":["../../src/directory-sync.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport type {\n DirectoryFieldsFragment,\n Sdk,\n} from \"./api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { usePermissions } from \"./lib/use-permissions.js\";\nimport { openUrlViaForm } from \"./lib/utils.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n DirectoryState,\n DirectorySyncError,\n DirectorySyncLoading,\n DirectorySync as DirectorySyncPresentational,\n isDirectoryState,\n} from \"./widgets/directory-sync/directory-sync.js\";\nimport type {\n DirectorySyncErrorProps,\n DirectorySyncLoadingProps,\n} from \"./widgets/directory-sync/directory-sync.js\";\n\nconst DIRECTORIES_PAGE_SIZE = 100;\n\nasync function listAllDirectoryConnections(\n sdk: Sdk,\n): Promise<DirectoryFieldsFragment[]> {\n const directories: DirectoryFieldsFragment[] = [];\n let after: string | null = null;\n do {\n const { directoryConnections } = await sdk.ListDirectoryConnections({\n after,\n limit: DIRECTORIES_PAGE_SIZE,\n });\n directories.push(...directoryConnections.data);\n after = directoryConnections.listMetadata.after ?? null;\n } while (after !== null);\n // Directories awaiting a type or mid-deletion are not usable by the\n // organization; treat them as not set up.\n return directories.filter(\n (directory) =>\n isDirectoryState(directory.state) &&\n directory.state !== DirectoryState.requires_type &&\n directory.state !== DirectoryState.deleting,\n );\n}\n\ninterface DirectorySyncProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst DirectorySync: React.FC<DirectorySyncProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError {...domProps} error={error} />\n )}\n >\n <ApiProvider\n widgetType=\"directory-sync\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <DirectorySyncImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface DirectorySyncImplProps extends WidgetRootDomProps {}\n\nconst DirectorySyncImpl: React.FC<DirectorySyncImplProps> = (props) => {\n const isApiReady = useApiReady();\n const {\n data: directories,\n isLoading,\n isError,\n error,\n } = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDirectoryConnections\"),\n queryFn: listAllDirectoryConnections,\n });\n const permissionsQuery = usePermissions(\"widgets:dsync:manage\");\n const { mutate: openAdminPortal, isPending: isOpeningAdminPortal } =\n useClientGraphqlMutation({\n mutationFn: (sdk) => sdk.CreateAdminPortalLink({ intent: \"Dsync\" }),\n onSuccess: (data) => {\n openUrlViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n if (!isApiReady || isLoading || permissionsQuery.isLoading) {\n return <DirectorySyncLoading {...props} />;\n }\n\n if (permissionsQuery.isError || isError) {\n return (\n <DirectorySyncError error={permissionsQuery.error || error} {...props} />\n );\n }\n\n const adminPortalProps = {\n onOpenAdminPortal: () => openAdminPortal(),\n isOpeningAdminPortal,\n };\n\n if (!directories?.length) {\n return (\n <DirectorySyncPresentational\n {...props}\n state={DirectoryState.unlinked}\n {...adminPortalProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError error={error} {...props} />\n )}\n >\n {directories.map((directory) => {\n const { id, state, type, metadata, lastSyncRunAt } = directory;\n const commonProps = {\n ...props,\n type,\n metadata,\n lastSyncAt: lastSyncRunAt ?? null,\n ...adminPortalProps,\n };\n\n if (!isDirectoryState(state)) {\n return null;\n }\n\n switch (state) {\n case DirectoryState.invalid_credentials:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory credentials are invalid or have expired. Please re-authenticate to resume syncing.\"\n />\n );\n case DirectoryState.linked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.validating:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.deleting:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.unlinked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.requires_type:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory requires additional configuration. Please complete setup to begin syncing.\"\n />\n );\n }\n })}\n </ErrorBoundary>\n );\n};\n\nexport type {\n DirectorySyncProps,\n DirectorySyncLoadingProps,\n DirectorySyncErrorProps,\n};\nexport { DirectorySync, DirectorySyncLoading, DirectorySyncError };\n"],"mappings":";;;;;;;;;;;;AA+BA,MAAM,wBAAwB;AAE9B,eAAe,4BACb,KACoC;CACpC,MAAM,cAAyC,CAAC;CAChD,IAAI,QAAuB;CAC3B,GAAG;EACD,MAAM,EAAE,yBAAyB,MAAM,IAAI,yBAAyB;GAClE;GACA,OAAO;EACT,CAAC;EACD,YAAY,KAAK,GAAG,qBAAqB,IAAI;EAC7C,QAAQ,qBAAqB,aAAa,SAAS;CACrD,SAAS,UAAU;CAGnB,OAAO,YAAY,QAChB,cACC,iBAAiB,UAAU,KAAK,KAChC,UAAU,UAAU,eAAe,iBACnC,UAAU,UAAU,eAAe,QACvC;AACF;AAMA,MAAM,iBAA+C,EACnD,WACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAAoB,GAAI;GAAiB;EAAQ,CAAA;EAGnD,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,mBAAD,EAAmB,GAAI,SAAW,CAAA;EACvB,CAAA;CACA,CAAA;AAEnB;AAIA,MAAM,qBAAuD,UAAU;CACrE,MAAM,aAAa,YAAY;CAC/B,MAAM,EACJ,MAAM,aACN,WACA,SACA,UACE,sBAAsB;EACxB,UAAU,sBAAsB,0BAA0B;EAC1D,SAAS;CACX,CAAC;CACD,MAAM,mBAAmB,eAAe,sBAAsB;CAC9D,MAAM,EAAE,QAAQ,iBAAiB,WAAW,yBAC1C,yBAAyB;EACvB,aAAa,QAAQ,IAAI,sBAAsB,EAAE,QAAQ,QAAQ,CAAC;EAClE,YAAY,SAAS;GACnB,eAAe,KAAK,sBAAsB,MAAM;IAC9C,QAAQ;IACR,KAAK;GACP,CAAC;EACH;CACF,CAAC;CAEH,IAAI,CAAC,cAAc,aAAa,iBAAiB,WAC/C,OAAO,oBAAC,sBAAD,EAAsB,GAAI,MAAQ,CAAA;CAG3C,IAAI,iBAAiB,WAAW,SAC9B,OACE,oBAAC,oBAAD;EAAoB,OAAO,iBAAiB,SAAS;EAAO,GAAI;CAAQ,CAAA;CAI5E,MAAM,mBAAmB;EACvB,yBAAyB,gBAAgB;EACzC;CACF;CAEA,IAAI,CAAC,aAAa,QAChB,OACE,oBAACA,iBAAD;EACE,GAAI;EACJ,OAAO,eAAe;EACtB,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAA2B;GAAO,GAAI;EAAQ,CAAA;EAG/C,UAAA,YAAY,KAAK,cAAc;GAC9B,MAAM,EAAE,IAAI,OAAO,MAAM,UAAU,kBAAkB;GACrD,MAAM,cAAc;IAClB,GAAG;IACH;IACA;IACA,YAAY,iBAAiB;IAC7B,GAAG;GACL;GAEA,IAAI,CAAC,iBAAiB,KAAK,GACzB,OAAO;GAGT,QAAQ,OAAR;IACE,KAAK,eAAe,qBAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;IAEL,KAAK,eAAe,QAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,YAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,eAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;GAEP;EACF,CAAC;CACY,CAAA;AAEnB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
|
|
1
2
|
import { ApiError } from "../../api/errors.js";
|
|
2
|
-
import {
|
|
3
|
+
import { useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
|
|
3
4
|
import { useApiKeysContext } from "../../widgets/api-keys/api-keys-context.js";
|
|
4
5
|
import { keepPreviousData, useQueryClient } from "@tanstack/react-query";
|
|
5
6
|
//#region src/lib/api/api-key.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-key.js","names":[],"sources":["../../../../src/lib/api/api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ApiKeyOwnerType,\n CreateOrganizationApiKeyMutation,\n ExpireOrganizationApiKeyMutation,\n ListApiKeyPermissionsQuery,\n OrganizationApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { ApiError } from \"../../api/errors.js\";\nimport { useApiKeysContext } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type { ApiKeysContextValue } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type {\n CreateOrganizationApiKeyRequest,\n CreateOrganizationApiKeyResponse,\n ListOrganizationApiKeyPermission,\n ListOrganizationApiKeyPermissionsParams,\n ListOrganizationApiKeyPermissionsResponse,\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"./types.js\";\n\nexport const API_KEYS_PAGE_SIZE = 10;\n\ntype ApiKeyPermissionsParams = ListOrganizationApiKeyPermissionsParams;\n\nfunction toApiKeyPermissions(\n list: ListApiKeyPermissionsQuery[\"permissions\"],\n): ListOrganizationApiKeyPermissionsResponse {\n return {\n data: list.data.map((permission): ListOrganizationApiKeyPermission => ({\n id: permission.id,\n slug: permission.slug,\n name: permission.name,\n description: permission.description ?? null,\n })),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n };\n}\n\nexport const useListApiKeyPermissions = (\n apiKeyOwnerType: ApiKeyOwnerType,\n params: ApiKeyPermissionsParams = {},\n) => {\n const variables = {\n apiKeyOwnerType,\n after: params.after,\n before: params.before,\n limit: params.limit,\n search: params.search || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListApiKeyPermissions\", variables),\n queryFn: async (sdk) => {\n const { permissions } = await sdk.ListApiKeyPermissions(variables);\n return permissions;\n },\n select: toApiKeyPermissions,\n placeholderData: keepPreviousData,\n });\n};\n\nexport const useListOrganizationApiKeyPermissions = (\n params?: ApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"Organization\", params);\n\nconst organizationApiKeysQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationApiKeys\",\n);\n\nfunction toOrganizationApiKey(\n apiKey: OrganizationApiKeyFieldsFragment,\n): ListOrganizationApiKeysResponseData {\n return {\n id: apiKey.id,\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nexport function apiKeyMutationFailure(\n typename: string,\n message: string,\n): ApiError {\n return new ApiError({\n message,\n status: 400,\n queryType: \"mutation\",\n context: { typename },\n });\n}\n\nfunction unwrapCreateOrganizationApiKey(\n result: CreateOrganizationApiKeyMutation[\"createOrganizationApiKey\"],\n): CreateOrganizationApiKeyResponse {\n switch (result.__typename) {\n case \"OrganizationApiKeyCreated\":\n return {\n ...toOrganizationApiKey(result.apiKey),\n value: result.value,\n };\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireOrganizationApiKey(\n result: ExpireOrganizationApiKeyMutation[\"expireOrganizationApiKey\"],\n): ListOrganizationApiKeysResponseData {\n switch (result.__typename) {\n case \"OrganizationApiKeyExpired\":\n return toOrganizationApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useApiKeys = (context?: ApiKeysContextValue) => {\n const {\n state: { pagination, searchQuery },\n } = useApiKeysContext(context);\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListOrganizationApiKeys\", variables),\n queryFn: async (sdk) => {\n const { organizationApiKeys } =\n await sdk.ListOrganizationApiKeys(variables);\n return organizationApiKeys;\n },\n select: (list): ListOrganizationApiKeysResponse => ({\n data: list.data.map(toOrganizationApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateApiKeys = () => {\n const queryClient = useQueryClient();\n return () =>\n queryClient.invalidateQueries({ queryKey: organizationApiKeysQueryKey });\n};\n\nexport const useCreateApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { data }: { data: CreateOrganizationApiKeyRequest },\n ) => {\n const { createOrganizationApiKey: result } =\n await sdk.CreateOrganizationApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteOrganizationApiKey } = await sdk.DeleteOrganizationApiKey({\n apiKeyId,\n });\n return toOrganizationApiKey(deleteOrganizationApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireOrganizationApiKey: result } =\n await sdk.ExpireOrganizationApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"api-key.js","names":[],"sources":["../../../../src/lib/api/api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ApiKeyOwnerType,\n CreateOrganizationApiKeyMutation,\n ExpireOrganizationApiKeyMutation,\n ListApiKeyPermissionsQuery,\n OrganizationApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { ApiError } from \"../../api/errors.js\";\nimport { useApiKeysContext } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type { ApiKeysContextValue } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type {\n CreateOrganizationApiKeyRequest,\n CreateOrganizationApiKeyResponse,\n ListOrganizationApiKeyPermission,\n ListOrganizationApiKeyPermissionsParams,\n ListOrganizationApiKeyPermissionsResponse,\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"./types.js\";\n\nexport const API_KEYS_PAGE_SIZE = 10;\n\ntype ApiKeyPermissionsParams = ListOrganizationApiKeyPermissionsParams;\n\nfunction toApiKeyPermissions(\n list: ListApiKeyPermissionsQuery[\"permissions\"],\n): ListOrganizationApiKeyPermissionsResponse {\n return {\n data: list.data.map((permission): ListOrganizationApiKeyPermission => ({\n id: permission.id,\n slug: permission.slug,\n name: permission.name,\n description: permission.description ?? null,\n })),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n };\n}\n\nexport const useListApiKeyPermissions = (\n apiKeyOwnerType: ApiKeyOwnerType,\n params: ApiKeyPermissionsParams = {},\n) => {\n const variables = {\n apiKeyOwnerType,\n after: params.after,\n before: params.before,\n limit: params.limit,\n search: params.search || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListApiKeyPermissions\", variables),\n queryFn: async (sdk) => {\n const { permissions } = await sdk.ListApiKeyPermissions(variables);\n return permissions;\n },\n select: toApiKeyPermissions,\n placeholderData: keepPreviousData,\n });\n};\n\nexport const useListOrganizationApiKeyPermissions = (\n params?: ApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"Organization\", params);\n\nconst organizationApiKeysQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationApiKeys\",\n);\n\nfunction toOrganizationApiKey(\n apiKey: OrganizationApiKeyFieldsFragment,\n): ListOrganizationApiKeysResponseData {\n return {\n id: apiKey.id,\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nexport function apiKeyMutationFailure(\n typename: string,\n message: string,\n): ApiError {\n return new ApiError({\n message,\n status: 400,\n queryType: \"mutation\",\n context: { typename },\n });\n}\n\nfunction unwrapCreateOrganizationApiKey(\n result: CreateOrganizationApiKeyMutation[\"createOrganizationApiKey\"],\n): CreateOrganizationApiKeyResponse {\n switch (result.__typename) {\n case \"OrganizationApiKeyCreated\":\n return {\n ...toOrganizationApiKey(result.apiKey),\n value: result.value,\n };\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireOrganizationApiKey(\n result: ExpireOrganizationApiKeyMutation[\"expireOrganizationApiKey\"],\n): ListOrganizationApiKeysResponseData {\n switch (result.__typename) {\n case \"OrganizationApiKeyExpired\":\n return toOrganizationApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useApiKeys = (context?: ApiKeysContextValue) => {\n const {\n state: { pagination, searchQuery },\n } = useApiKeysContext(context);\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListOrganizationApiKeys\", variables),\n queryFn: async (sdk) => {\n const { organizationApiKeys } =\n await sdk.ListOrganizationApiKeys(variables);\n return organizationApiKeys;\n },\n select: (list): ListOrganizationApiKeysResponse => ({\n data: list.data.map(toOrganizationApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateApiKeys = () => {\n const queryClient = useQueryClient();\n return () =>\n queryClient.invalidateQueries({ queryKey: organizationApiKeysQueryKey });\n};\n\nexport const useCreateApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { data }: { data: CreateOrganizationApiKeyRequest },\n ) => {\n const { createOrganizationApiKey: result } =\n await sdk.CreateOrganizationApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteOrganizationApiKey } = await sdk.DeleteOrganizationApiKey({\n apiKeyId,\n });\n return toOrganizationApiKey(deleteOrganizationApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireOrganizationApiKey: result } =\n await sdk.ExpireOrganizationApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":"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"}
|
package/dist/esm/lib/api/me.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { clientGraphqlQueryKey
|
|
1
|
+
import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
|
|
2
|
+
import { useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
|
|
2
3
|
import { useQueryClient } from "@tanstack/react-query";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
//#region src/lib/api/me.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"me.js","names":[],"sources":["../../../../src/lib/api/me.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { MeQuery } from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\n\nexport type CurrentUser = MeQuery[\"me\"];\n\nconst meQueryKey = () => clientGraphqlQueryKey(\"Me\");\n\nexport function useMe() {\n return useClientGraphqlQuery({\n queryKey: meQueryKey(),\n queryFn: (sdk) => sdk.Me(),\n select: (data) => data.me,\n });\n}\n\nexport function useMeCache() {\n const client = useQueryClient();\n\n return React.useMemo(\n () => ({\n update(user: Partial<CurrentUser>) {\n client.setQueryData<MeQuery>(meQueryKey(), (old) =>\n old ? { ...old, me: { ...old.me, ...user } } : old,\n );\n },\n invalidate() {\n return client.invalidateQueries({ queryKey: meQueryKey() });\n },\n }),\n [client],\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"me.js","names":[],"sources":["../../../../src/lib/api/me.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { MeQuery } from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\n\nexport type CurrentUser = MeQuery[\"me\"];\n\nconst meQueryKey = () => clientGraphqlQueryKey(\"Me\");\n\nexport function useMe() {\n return useClientGraphqlQuery({\n queryKey: meQueryKey(),\n queryFn: (sdk) => sdk.Me(),\n select: (data) => data.me,\n });\n}\n\nexport function useMeCache() {\n const client = useQueryClient();\n\n return React.useMemo(\n () => ({\n update(user: Partial<CurrentUser>) {\n client.setQueryData<MeQuery>(meQueryKey(), (old) =>\n old ? { ...old, me: { ...old.me, ...user } } : old,\n );\n },\n invalidate() {\n return client.invalidateQueries({ queryKey: meQueryKey() });\n },\n }),\n [client],\n );\n}\n"],"mappings":";;;;;AAUA,MAAM,mBAAmB,sBAAsB,IAAI;AAEnD,SAAgB,QAAQ;CACtB,OAAO,sBAAsB;EAC3B,UAAU,WAAW;EACrB,UAAU,QAAQ,IAAI,GAAG;EACzB,SAAS,SAAS,KAAK;CACzB,CAAC;AACH;AAEA,SAAgB,aAAa;CAC3B,MAAM,SAAS,eAAe;CAE9B,OAAO,MAAM,eACJ;EACL,OAAO,MAA4B;GACjC,OAAO,aAAsB,WAAW,IAAI,QAC1C,MAAM;IAAE,GAAG;IAAK,IAAI;KAAE,GAAG,IAAI;KAAI,GAAG;IAAK;GAAE,IAAI,GACjD;EACF;EACA,aAAa;GACX,OAAO,OAAO,kBAAkB,EAAE,UAAU,WAAW,EAAE,CAAC;EAC5D;CACF,IACA,CAAC,MAAM,CACT;AACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { clientGraphqlQueryKey
|
|
1
|
+
import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
|
|
2
|
+
import { useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
|
|
2
3
|
import { useQueryClient } from "@tanstack/react-query";
|
|
3
4
|
import { useCallback } from "react";
|
|
4
5
|
//#region src/lib/api/pipes.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipes.js","names":[],"sources":["../../../../src/lib/api/pipes.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport { useCallback } from \"react\";\nimport type {\n ConfigurableDataProviderFieldsFragment,\n DataProviderConfigFieldFieldsFragment,\n DataProviderConnectionFieldsFragment,\n DataProviderFieldsFragment,\n OrganizationDataProviderFieldsFragment,\n Sdk,\n SharedDataProviderFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport type {\n DataInstallation,\n DataIntegrationConfigField,\n DataIntegrationConfiguration,\n DataIntegrationCredentials,\n DataIntegrationWithConnections,\n OrganizationDataIntegration,\n SharedConnection,\n SharedDataConnection,\n} from \"./types.js\";\n\nconst PAGE_SIZE = 100;\n\n/*\n * The widgets render the REST-shaped DTOs in `./types.ts`, which double as the\n * public shape a host's `filter` predicate sees. What the multiple-connections\n * capabilities add is carried on these local extensions instead, so the\n * public types don't change.\n */\n\ntype AuthMethod = NonNullable<\n DataIntegrationWithConnections[\"authMethods\"]\n>[number];\n\n/** Advisory repair actions on one exact organization-owned connection. */\nexport interface ConnectionCapabilities {\n canReauthorize: boolean;\n canUpdateCredentials: boolean;\n}\n\n/**\n * Whether the owner can add another connection to a provider right now, and\n * with which methods. Advisory: the server rechecks the cap when creating.\n */\nexport interface AddConnectionCapabilities {\n canAddConnection: boolean;\n /** Empty exactly when `canAddConnection` is false. */\n addConnectionMethods: AuthMethod[];\n}\n\n/**\n * A connection with its row-level capabilities: set for organization-owned\n * connections, null for a member's own (whose actions follow from its state).\n */\nexport type ConnectionWithCapabilities = DataInstallation & {\n capabilities: ConnectionCapabilities | null;\n};\n\n// The connection fields are replaced rather than intersected: an intersection\n// of two array types doesn't narrow the element type array methods see.\n\n/** A member's provider, its connections and whether they can add another. */\nexport type DataIntegrationWithCapabilities = Omit<\n DataIntegrationWithConnections,\n \"installation\" | \"connected_accounts\"\n> & {\n installation?: ConnectionWithCapabilities | null;\n connected_accounts: ConnectionWithCapabilities[];\n capabilities: AddConnectionCapabilities;\n};\n\n/** An organization-owned provider, with add and per-connection capabilities. */\nexport type OrganizationDataIntegrationWithCapabilities = Omit<\n OrganizationDataIntegration,\n \"installation\" | \"connected_accounts\" | \"capabilities\"\n> & {\n installation?: ConnectionWithCapabilities | null;\n connected_accounts: ConnectionWithCapabilities[];\n capabilities: OrganizationDataIntegration[\"capabilities\"] &\n AddConnectionCapabilities;\n};\n\n/**\n * The Pipes list queries default to `limit: 10` and the widgets render every\n * row, so each list is walked to its end before it is adapted.\n */\nasync function listAllPages<T>(\n fetchPage: (after: string | null) => Promise<{\n data: T[];\n listMetadata: { after?: string | null };\n }>,\n): Promise<T[]> {\n const rows: T[] = [];\n let after: string | null = null;\n do {\n const page = await fetchPage(after);\n rows.push(...page.data);\n after = page.listMetadata.after ?? null;\n } while (after !== null);\n return rows;\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n values: T,\n value: string,\n): value is T[number] {\n return values.includes(value);\n}\n\nconst AUTH_METHODS = [\"oauth\", \"api_key\", \"client_credentials\"] as const;\nconst CONNECTION_STATES = [\"connected\", \"needs_reauthorization\"] as const;\nconst AVAILABILITIES = [\"available\", \"needs_admin_attention\"] as const;\nconst CREDENTIALS_TYPES = [\"shared\", \"custom\", \"organization\"] as const;\nconst DISABLED_SOURCES = [\"developer\", \"organization\"] as const;\nconst CONFIG_FIELD_SCOPES = [\"integration\", \"installation\"] as const;\n\nfunction toAuthMethods(\n authMethods: readonly string[],\n): NonNullable<DataIntegrationWithConnections[\"authMethods\"]> {\n return authMethods.filter((method) => isOneOf(AUTH_METHODS, method));\n}\n\n/**\n * The GraphQL types carry these as plain strings; the REST DTOs the widgets\n * render from narrow them. Unknown values fall back to the option that\n * renders the least capable state.\n */\nfunction toCredentialsType(\n credentialsType: string,\n): DataIntegrationWithConnections[\"credentialsType\"] {\n return isOneOf(CREDENTIALS_TYPES, credentialsType)\n ? credentialsType\n : \"shared\";\n}\n\nfunction toConnectionState(state: string): DataInstallation[\"state\"] {\n return isOneOf(CONNECTION_STATES, state) ? state : \"needs_reauthorization\";\n}\n\nfunction toConfig(\n entries: readonly { name: string; value: string }[],\n): Record<string, string> {\n return Object.fromEntries(entries.map(({ name, value }) => [name, value]));\n}\n\nfunction toConfigField(\n field: DataProviderConfigFieldFieldsFragment,\n): DataIntegrationConfigField {\n return {\n key: field.key,\n label: field.label,\n required: field.required,\n scope: isOneOf(CONFIG_FIELD_SCOPES, field.scope)\n ? field.scope\n : \"integration\",\n description: field.description ?? undefined,\n example: field.example ?? undefined,\n pattern: field.pattern ?? undefined,\n patternFlags: field.patternFlags ?? undefined,\n order: field.order ?? undefined,\n secret: field.secret ?? undefined,\n default: field.default ?? undefined,\n };\n}\n\nfunction toIconFields(provider: {\n iconSlug?: string | null;\n iconUrl?: string | null;\n iconDarkUrl?: string | null;\n}): Pick<\n DataIntegrationWithConnections,\n \"iconSlug\" | \"iconUrl\" | \"iconDarkUrl\"\n> {\n return {\n iconSlug: provider.iconSlug ?? undefined,\n iconUrl: provider.iconUrl ?? undefined,\n iconDarkUrl: provider.iconDarkUrl ?? undefined,\n };\n}\n\n/**\n * Oldest first: by creation time, then id (ULIDs also sort by time). This is\n * the order the API already uses for organization connections; the member\n * list defaults to newest first, so both are sorted here rather than relying\n * on either endpoint's default.\n */\nfunction byCreation(a: DataInstallation, b: DataInstallation): number {\n return (\n Date.parse(a.created_at) - Date.parse(b.created_at) ||\n a.id.localeCompare(b.id)\n );\n}\n\nfunction toAddConnectionCapabilities(capabilities: {\n canAddConnection: boolean;\n addConnectionMethods: readonly string[];\n}): AddConnectionCapabilities {\n const addConnectionMethods = toAuthMethods(capabilities.addConnectionMethods);\n return {\n // Keep the pair consistent even if an unknown method was filtered out.\n canAddConnection:\n capabilities.canAddConnection && addConnectionMethods.length > 0,\n addConnectionMethods,\n };\n}\n\nfunction toDataInstallation(\n connection: DataProviderConnectionFieldsFragment,\n): ConnectionWithCapabilities {\n return {\n capabilities: connection.capabilities\n ? {\n canReauthorize: connection.capabilities.canReauthorize,\n canUpdateCredentials: connection.capabilities.canUpdateCredentials,\n }\n : null,\n object: \"data_installation\",\n id: connection.id,\n connection_role:\n connection.connectionRole === \"Standard\" ? \"standard\" : \"compatibility\",\n account_identifier: connection.accountIdentifier ?? null,\n account_display_name: connection.accountDisplayName ?? null,\n user_id: connection.userId ?? null,\n organization_id: connection.organizationId ?? null,\n scopes: connection.scopes,\n auth_method: isOneOf(AUTH_METHODS, connection.authMethod)\n ? connection.authMethod\n : \"oauth\",\n api_key_last_4: connection.apiKeyLast4 ?? null,\n client_id: connection.clientId ?? null,\n client_secret_last_4: connection.clientSecretLast4 ?? null,\n config: toConfig(connection.config),\n state: toConnectionState(connection.state),\n created_at: connection.createdAt,\n updated_at: connection.updatedAt,\n };\n}\n\n/**\n * Joins the member's providers with their own connections the way\n * `GET /_widgets/DataIntegrations/mine` did: every connection, oldest first,\n * in `connected_accounts`, and the compatibility connection inline as\n * `installation` — the single connection the unsectioned widget and a host's\n * `filter` see. With the compatibility slot empty, `installation` is null and\n * the provider reads as not connected there, as it does to every other\n * single-connection client.\n */\nfunction toMyDataIntegrations(\n providers: readonly DataProviderFieldsFragment[],\n connections: readonly DataProviderConnectionFieldsFragment[],\n): DataIntegrationWithCapabilities[] {\n const connectionsByProviderId = new Map<\n string,\n ConnectionWithCapabilities[]\n >();\n for (const connection of connections) {\n const installations =\n connectionsByProviderId.get(connection.dataProviderId) ?? [];\n installations.push(toDataInstallation(connection));\n connectionsByProviderId.set(connection.dataProviderId, installations);\n }\n\n return providers.map((provider) => {\n const installations = (connectionsByProviderId.get(provider.id) ?? []).sort(\n byCreation,\n );\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"userland_user\",\n credentialsType: toCredentialsType(provider.credentialsType),\n scopes: provider.scopes,\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n installation:\n installations.find(\n (installation) => installation.connection_role === \"compatibility\",\n ) ?? null,\n connected_accounts: installations,\n capabilities: toAddConnectionCapabilities(provider.capabilities),\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n };\n });\n}\n\n/**\n * Presents a shared provider the way\n * `GET /_widgets/DataIntegrations/shared-connections` did for any active\n * member: identity, presentation and the state of each shared connection,\n * without credentials or account identifiers.\n */\nfunction toSharedDataConnection(\n provider: SharedDataProviderFieldsFragment,\n): SharedDataConnection {\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n ownership: \"organization\",\n connected_accounts: provider.connectedAccounts.map(\n (connection): SharedConnection => ({\n object: \"connected_account\",\n id: connection.id,\n state: toConnectionState(connection.state),\n availability: isOneOf(AVAILABILITIES, connection.availability)\n ? connection.availability\n : \"needs_admin_attention\",\n created_at: connection.createdAt,\n updated_at: connection.updatedAt,\n }),\n ),\n ...toIconFields(provider),\n };\n}\n\n/**\n * Presents the organization's policy configuration of a member-connectable\n * provider the way `GET /_widgets/DataIntegrations/configurations` did.\n */\nfunction toDataIntegrationConfiguration(\n provider: ConfigurableDataProviderFieldsFragment,\n): DataIntegrationConfiguration {\n return {\n object: \"data_integration_configuration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"userland_user\",\n enabled: provider.enabled,\n scopes: provider.scopes,\n defaultScopes: provider.defaultScopes,\n availableScopes: provider.availableScopes,\n credentials: toCredentials(provider.credentials),\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n };\n}\n\nfunction toCredentials(\n credentials: OrganizationDataProviderFieldsFragment[\"credentials\"],\n): DataIntegrationCredentials {\n return {\n credentialsType: toCredentialsType(credentials.credentialsType),\n hasCredentials: credentials.hasCredentials,\n client_id: credentials.clientId ?? null,\n redactedClientSecret: credentials.redactedClientSecret ?? null,\n redirectUri: credentials.redirectUri,\n };\n}\n\n/**\n * Presents an organization-owned provider the way\n * `GET /_widgets/DataIntegrations/organization` did. The GraphQL type\n * resolves the organization's override into the effective `enabled` /\n * `disabledSource`, so the raw override fields are derived from those.\n */\nfunction toOrganizationDataIntegration(\n provider: OrganizationDataProviderFieldsFragment,\n): OrganizationDataIntegrationWithCapabilities {\n const disabledSource = provider.disabledSource ?? null;\n const overrideDisabled = disabledSource === \"organization\";\n // Already oldest first from the API; sorted anyway so the order doesn't\n // hinge on that, and matches the member list's.\n const connectedAccounts = provider.connectedAccounts\n .map(toDataInstallation)\n .sort(byCreation);\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"organization\",\n credentialsType: toCredentialsType(provider.credentialsType),\n scopes: provider.scopes,\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n installation: provider.connection\n ? toDataInstallation(provider.connection)\n : null,\n connected_accounts: connectedAccounts,\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n configuration: {\n hasOverride: overrideDisabled,\n rootEnabled: disabledSource !== \"developer\",\n overrideEnabled: overrideDisabled ? false : null,\n enabled: provider.enabled,\n disabledSource:\n disabledSource !== null && isOneOf(DISABLED_SOURCES, disabledSource)\n ? disabledSource\n : null,\n scopes: provider.scopes,\n defaultScopes: provider.defaultScopes,\n availableScopes: provider.availableScopes,\n credentials: toCredentials(provider.credentials),\n configured: provider.configured,\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n },\n capabilities: {\n canConfigure: provider.capabilities.canConfigure,\n canConnect: provider.capabilities.canConnect,\n canUpdateCredentials: provider.capabilities.canUpdateCredentials,\n canReauthorize: provider.capabilities.canReauthorize,\n canDisconnect: provider.capabilities.canDisconnect,\n ...toAddConnectionCapabilities(provider.capabilities),\n },\n };\n}\n\nasync function listAllDataProviders(\n sdk: Sdk,\n): Promise<DataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { dataProviders } = await sdk.ListDataProviders({\n after,\n limit: PAGE_SIZE,\n });\n return dataProviders;\n });\n}\n\nasync function listAllDataProviderConnections(\n sdk: Sdk,\n): Promise<DataProviderConnectionFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { dataProviderConnections } = await sdk.ListDataProviderConnections({\n after,\n limit: PAGE_SIZE,\n });\n return dataProviderConnections;\n });\n}\n\nasync function listAllOrganizationDataProviders(\n sdk: Sdk,\n): Promise<OrganizationDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { organizationDataProviders } =\n await sdk.ListOrganizationDataProviders({ after, limit: PAGE_SIZE });\n return organizationDataProviders;\n });\n}\n\nasync function listAllSharedDataProviders(\n sdk: Sdk,\n): Promise<SharedDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { sharedDataProviders } = await sdk.ListSharedDataProviders({\n after,\n limit: PAGE_SIZE,\n });\n return sharedDataProviders;\n });\n}\n\nasync function listAllConfigurableDataProviders(\n sdk: Sdk,\n): Promise<ConfigurableDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { configurableDataProviders } =\n await sdk.ListConfigurableDataProviders({ after, limit: PAGE_SIZE });\n return configurableDataProviders;\n });\n}\n\nexport const sharedDataConnectionsQueryKey = clientGraphqlQueryKey(\n \"ListSharedDataProviders\",\n);\n\nexport const dataIntegrationConfigurationsQueryKey = clientGraphqlQueryKey(\n \"ListConfigurableDataProviders\",\n);\n\nexport const myDataIntegrationsQueryKeys = [\n clientGraphqlQueryKey(\"ListDataProviders\"),\n clientGraphqlQueryKey(\"ListDataProviderConnections\"),\n];\n\nexport const organizationDataIntegrationsQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationDataProviders\",\n);\n\ninterface ListResult<T> {\n data: T[];\n isLoading: boolean;\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n error: Error | null;\n failureCount: number;\n refetch: () => void;\n}\n\n/** The member's connectable providers joined with their own connections. */\nexport function useMyDataIntegrations({\n enabled = true,\n}: { enabled?: boolean } = {}): ListResult<DataIntegrationWithCapabilities> {\n const providers = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDataProviders\"),\n queryFn: listAllDataProviders,\n enabled,\n });\n const connections = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDataProviderConnections\"),\n queryFn: listAllDataProviderConnections,\n enabled,\n });\n\n const isSuccess = providers.isSuccess && connections.isSuccess;\n return {\n data: isSuccess\n ? toMyDataIntegrations(providers.data, connections.data)\n : [],\n isLoading: providers.isLoading || connections.isLoading,\n isPending: providers.isPending || connections.isPending,\n isSuccess,\n isError: providers.isError || connections.isError,\n error: providers.error ?? connections.error,\n failureCount: Math.max(providers.failureCount, connections.failureCount),\n refetch: () => {\n void providers.refetch();\n void connections.refetch();\n },\n };\n}\n\n/** The organization's provider inventory with its shared connections. */\nexport function useOrganizationDataIntegrations({\n enabled = true,\n}: {\n enabled?: boolean;\n} = {}): ListResult<OrganizationDataIntegrationWithCapabilities> {\n const query = useClientGraphqlQuery({\n queryKey: organizationDataIntegrationsQueryKey,\n queryFn: listAllOrganizationDataProviders,\n select: (providers) => providers.map(toOrganizationDataIntegration),\n enabled,\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/** The organization's shared connections, readable by any active member. */\nexport function useSharedDataConnections(): ListResult<SharedDataConnection> {\n const query = useClientGraphqlQuery({\n queryKey: sharedDataConnectionsQueryKey,\n queryFn: listAllSharedDataProviders,\n select: (providers) => providers.map(toSharedDataConnection),\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/** The organization's policy configuration of each connectable provider. */\nexport function useDataIntegrationConfigurations({\n enabled = true,\n}: { enabled?: boolean } = {}): ListResult<DataIntegrationConfiguration> {\n const query = useClientGraphqlQuery({\n queryKey: dataIntegrationConfigurationsQueryKey,\n queryFn: listAllConfigurableDataProviders,\n select: (providers) => providers.map(toDataIntegrationConfiguration),\n enabled,\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/**\n * Refreshes whatever a write for `owner` changed: the member's own list, or the\n * organization's inventory plus the shared section members see.\n */\nexport function useInvalidateConnections(owner: \"user\" | \"organization\") {\n const queryClient = useQueryClient();\n return useCallback(() => {\n if (owner === \"organization\") {\n queryClient.invalidateQueries({\n queryKey: organizationDataIntegrationsQueryKey,\n });\n queryClient.invalidateQueries({\n queryKey: sharedDataConnectionsQueryKey,\n });\n } else {\n for (const queryKey of myDataIntegrationsQueryKeys) {\n queryClient.invalidateQueries({ queryKey });\n }\n }\n }, [owner, queryClient]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pipes.js","names":[],"sources":["../../../../src/lib/api/pipes.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport { useCallback } from \"react\";\nimport type {\n ConfigurableDataProviderFieldsFragment,\n DataProviderConfigFieldFieldsFragment,\n DataProviderConnectionFieldsFragment,\n DataProviderFieldsFragment,\n OrganizationDataProviderFieldsFragment,\n Sdk,\n SharedDataProviderFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport type {\n DataInstallation,\n DataIntegrationConfigField,\n DataIntegrationConfiguration,\n DataIntegrationCredentials,\n DataIntegrationWithConnections,\n OrganizationDataIntegration,\n SharedConnection,\n SharedDataConnection,\n} from \"./types.js\";\n\nconst PAGE_SIZE = 100;\n\n/*\n * The widgets render the REST-shaped DTOs in `./types.ts`, which double as the\n * public shape a host's `filter` predicate sees. What the multiple-connections\n * capabilities add is carried on these local extensions instead, so the\n * public types don't change.\n */\n\ntype AuthMethod = NonNullable<\n DataIntegrationWithConnections[\"authMethods\"]\n>[number];\n\n/** Advisory repair actions on one exact organization-owned connection. */\nexport interface ConnectionCapabilities {\n canReauthorize: boolean;\n canUpdateCredentials: boolean;\n}\n\n/**\n * Whether the owner can add another connection to a provider right now, and\n * with which methods. Advisory: the server rechecks the cap when creating.\n */\nexport interface AddConnectionCapabilities {\n canAddConnection: boolean;\n /** Empty exactly when `canAddConnection` is false. */\n addConnectionMethods: AuthMethod[];\n}\n\n/**\n * A connection with its row-level capabilities: set for organization-owned\n * connections, null for a member's own (whose actions follow from its state).\n */\nexport type ConnectionWithCapabilities = DataInstallation & {\n capabilities: ConnectionCapabilities | null;\n};\n\n// The connection fields are replaced rather than intersected: an intersection\n// of two array types doesn't narrow the element type array methods see.\n\n/** A member's provider, its connections and whether they can add another. */\nexport type DataIntegrationWithCapabilities = Omit<\n DataIntegrationWithConnections,\n \"installation\" | \"connected_accounts\"\n> & {\n installation?: ConnectionWithCapabilities | null;\n connected_accounts: ConnectionWithCapabilities[];\n capabilities: AddConnectionCapabilities;\n};\n\n/** An organization-owned provider, with add and per-connection capabilities. */\nexport type OrganizationDataIntegrationWithCapabilities = Omit<\n OrganizationDataIntegration,\n \"installation\" | \"connected_accounts\" | \"capabilities\"\n> & {\n installation?: ConnectionWithCapabilities | null;\n connected_accounts: ConnectionWithCapabilities[];\n capabilities: OrganizationDataIntegration[\"capabilities\"] &\n AddConnectionCapabilities;\n};\n\n/**\n * The Pipes list queries default to `limit: 10` and the widgets render every\n * row, so each list is walked to its end before it is adapted.\n */\nasync function listAllPages<T>(\n fetchPage: (after: string | null) => Promise<{\n data: T[];\n listMetadata: { after?: string | null };\n }>,\n): Promise<T[]> {\n const rows: T[] = [];\n let after: string | null = null;\n do {\n const page = await fetchPage(after);\n rows.push(...page.data);\n after = page.listMetadata.after ?? null;\n } while (after !== null);\n return rows;\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n values: T,\n value: string,\n): value is T[number] {\n return values.includes(value);\n}\n\nconst AUTH_METHODS = [\"oauth\", \"api_key\", \"client_credentials\"] as const;\nconst CONNECTION_STATES = [\"connected\", \"needs_reauthorization\"] as const;\nconst AVAILABILITIES = [\"available\", \"needs_admin_attention\"] as const;\nconst CREDENTIALS_TYPES = [\"shared\", \"custom\", \"organization\"] as const;\nconst DISABLED_SOURCES = [\"developer\", \"organization\"] as const;\nconst CONFIG_FIELD_SCOPES = [\"integration\", \"installation\"] as const;\n\nfunction toAuthMethods(\n authMethods: readonly string[],\n): NonNullable<DataIntegrationWithConnections[\"authMethods\"]> {\n return authMethods.filter((method) => isOneOf(AUTH_METHODS, method));\n}\n\n/**\n * The GraphQL types carry these as plain strings; the REST DTOs the widgets\n * render from narrow them. Unknown values fall back to the option that\n * renders the least capable state.\n */\nfunction toCredentialsType(\n credentialsType: string,\n): DataIntegrationWithConnections[\"credentialsType\"] {\n return isOneOf(CREDENTIALS_TYPES, credentialsType)\n ? credentialsType\n : \"shared\";\n}\n\nfunction toConnectionState(state: string): DataInstallation[\"state\"] {\n return isOneOf(CONNECTION_STATES, state) ? state : \"needs_reauthorization\";\n}\n\nfunction toConfig(\n entries: readonly { name: string; value: string }[],\n): Record<string, string> {\n return Object.fromEntries(entries.map(({ name, value }) => [name, value]));\n}\n\nfunction toConfigField(\n field: DataProviderConfigFieldFieldsFragment,\n): DataIntegrationConfigField {\n return {\n key: field.key,\n label: field.label,\n required: field.required,\n scope: isOneOf(CONFIG_FIELD_SCOPES, field.scope)\n ? field.scope\n : \"integration\",\n description: field.description ?? undefined,\n example: field.example ?? undefined,\n pattern: field.pattern ?? undefined,\n patternFlags: field.patternFlags ?? undefined,\n order: field.order ?? undefined,\n secret: field.secret ?? undefined,\n default: field.default ?? undefined,\n };\n}\n\nfunction toIconFields(provider: {\n iconSlug?: string | null;\n iconUrl?: string | null;\n iconDarkUrl?: string | null;\n}): Pick<\n DataIntegrationWithConnections,\n \"iconSlug\" | \"iconUrl\" | \"iconDarkUrl\"\n> {\n return {\n iconSlug: provider.iconSlug ?? undefined,\n iconUrl: provider.iconUrl ?? undefined,\n iconDarkUrl: provider.iconDarkUrl ?? undefined,\n };\n}\n\n/**\n * Oldest first: by creation time, then id (ULIDs also sort by time). This is\n * the order the API already uses for organization connections; the member\n * list defaults to newest first, so both are sorted here rather than relying\n * on either endpoint's default.\n */\nfunction byCreation(a: DataInstallation, b: DataInstallation): number {\n return (\n Date.parse(a.created_at) - Date.parse(b.created_at) ||\n a.id.localeCompare(b.id)\n );\n}\n\nfunction toAddConnectionCapabilities(capabilities: {\n canAddConnection: boolean;\n addConnectionMethods: readonly string[];\n}): AddConnectionCapabilities {\n const addConnectionMethods = toAuthMethods(capabilities.addConnectionMethods);\n return {\n // Keep the pair consistent even if an unknown method was filtered out.\n canAddConnection:\n capabilities.canAddConnection && addConnectionMethods.length > 0,\n addConnectionMethods,\n };\n}\n\nfunction toDataInstallation(\n connection: DataProviderConnectionFieldsFragment,\n): ConnectionWithCapabilities {\n return {\n capabilities: connection.capabilities\n ? {\n canReauthorize: connection.capabilities.canReauthorize,\n canUpdateCredentials: connection.capabilities.canUpdateCredentials,\n }\n : null,\n object: \"data_installation\",\n id: connection.id,\n connection_role:\n connection.connectionRole === \"Standard\" ? \"standard\" : \"compatibility\",\n account_identifier: connection.accountIdentifier ?? null,\n account_display_name: connection.accountDisplayName ?? null,\n user_id: connection.userId ?? null,\n organization_id: connection.organizationId ?? null,\n scopes: connection.scopes,\n auth_method: isOneOf(AUTH_METHODS, connection.authMethod)\n ? connection.authMethod\n : \"oauth\",\n api_key_last_4: connection.apiKeyLast4 ?? null,\n client_id: connection.clientId ?? null,\n client_secret_last_4: connection.clientSecretLast4 ?? null,\n config: toConfig(connection.config),\n state: toConnectionState(connection.state),\n created_at: connection.createdAt,\n updated_at: connection.updatedAt,\n };\n}\n\n/**\n * Joins the member's providers with their own connections the way\n * `GET /_widgets/DataIntegrations/mine` did: every connection, oldest first,\n * in `connected_accounts`, and the compatibility connection inline as\n * `installation` — the single connection the unsectioned widget and a host's\n * `filter` see. With the compatibility slot empty, `installation` is null and\n * the provider reads as not connected there, as it does to every other\n * single-connection client.\n */\nfunction toMyDataIntegrations(\n providers: readonly DataProviderFieldsFragment[],\n connections: readonly DataProviderConnectionFieldsFragment[],\n): DataIntegrationWithCapabilities[] {\n const connectionsByProviderId = new Map<\n string,\n ConnectionWithCapabilities[]\n >();\n for (const connection of connections) {\n const installations =\n connectionsByProviderId.get(connection.dataProviderId) ?? [];\n installations.push(toDataInstallation(connection));\n connectionsByProviderId.set(connection.dataProviderId, installations);\n }\n\n return providers.map((provider) => {\n const installations = (connectionsByProviderId.get(provider.id) ?? []).sort(\n byCreation,\n );\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"userland_user\",\n credentialsType: toCredentialsType(provider.credentialsType),\n scopes: provider.scopes,\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n installation:\n installations.find(\n (installation) => installation.connection_role === \"compatibility\",\n ) ?? null,\n connected_accounts: installations,\n capabilities: toAddConnectionCapabilities(provider.capabilities),\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n };\n });\n}\n\n/**\n * Presents a shared provider the way\n * `GET /_widgets/DataIntegrations/shared-connections` did for any active\n * member: identity, presentation and the state of each shared connection,\n * without credentials or account identifiers.\n */\nfunction toSharedDataConnection(\n provider: SharedDataProviderFieldsFragment,\n): SharedDataConnection {\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n ownership: \"organization\",\n connected_accounts: provider.connectedAccounts.map(\n (connection): SharedConnection => ({\n object: \"connected_account\",\n id: connection.id,\n state: toConnectionState(connection.state),\n availability: isOneOf(AVAILABILITIES, connection.availability)\n ? connection.availability\n : \"needs_admin_attention\",\n created_at: connection.createdAt,\n updated_at: connection.updatedAt,\n }),\n ),\n ...toIconFields(provider),\n };\n}\n\n/**\n * Presents the organization's policy configuration of a member-connectable\n * provider the way `GET /_widgets/DataIntegrations/configurations` did.\n */\nfunction toDataIntegrationConfiguration(\n provider: ConfigurableDataProviderFieldsFragment,\n): DataIntegrationConfiguration {\n return {\n object: \"data_integration_configuration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"userland_user\",\n enabled: provider.enabled,\n scopes: provider.scopes,\n defaultScopes: provider.defaultScopes,\n availableScopes: provider.availableScopes,\n credentials: toCredentials(provider.credentials),\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n };\n}\n\nfunction toCredentials(\n credentials: OrganizationDataProviderFieldsFragment[\"credentials\"],\n): DataIntegrationCredentials {\n return {\n credentialsType: toCredentialsType(credentials.credentialsType),\n hasCredentials: credentials.hasCredentials,\n client_id: credentials.clientId ?? null,\n redactedClientSecret: credentials.redactedClientSecret ?? null,\n redirectUri: credentials.redirectUri,\n };\n}\n\n/**\n * Presents an organization-owned provider the way\n * `GET /_widgets/DataIntegrations/organization` did. The GraphQL type\n * resolves the organization's override into the effective `enabled` /\n * `disabledSource`, so the raw override fields are derived from those.\n */\nfunction toOrganizationDataIntegration(\n provider: OrganizationDataProviderFieldsFragment,\n): OrganizationDataIntegrationWithCapabilities {\n const disabledSource = provider.disabledSource ?? null;\n const overrideDisabled = disabledSource === \"organization\";\n // Already oldest first from the API; sorted anyway so the order doesn't\n // hinge on that, and matches the member list's.\n const connectedAccounts = provider.connectedAccounts\n .map(toDataInstallation)\n .sort(byCreation);\n return {\n object: \"data_integration\",\n id: provider.id,\n name: provider.name,\n description: provider.description,\n slug: provider.slug,\n integrationType: provider.integrationType,\n ownership: \"organization\",\n credentialsType: toCredentialsType(provider.credentialsType),\n scopes: provider.scopes,\n authMethods: toAuthMethods(provider.authMethods),\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n installation: provider.connection\n ? toDataInstallation(provider.connection)\n : null,\n connected_accounts: connectedAccounts,\n createdAt: provider.createdAt,\n updatedAt: provider.updatedAt,\n ...toIconFields(provider),\n configuration: {\n hasOverride: overrideDisabled,\n rootEnabled: disabledSource !== \"developer\",\n overrideEnabled: overrideDisabled ? false : null,\n enabled: provider.enabled,\n disabledSource:\n disabledSource !== null && isOneOf(DISABLED_SOURCES, disabledSource)\n ? disabledSource\n : null,\n scopes: provider.scopes,\n defaultScopes: provider.defaultScopes,\n availableScopes: provider.availableScopes,\n credentials: toCredentials(provider.credentials),\n configured: provider.configured,\n configFields: provider.configFields.map(toConfigField),\n config: toConfig(provider.config),\n },\n capabilities: {\n canConfigure: provider.capabilities.canConfigure,\n canConnect: provider.capabilities.canConnect,\n canUpdateCredentials: provider.capabilities.canUpdateCredentials,\n canReauthorize: provider.capabilities.canReauthorize,\n canDisconnect: provider.capabilities.canDisconnect,\n ...toAddConnectionCapabilities(provider.capabilities),\n },\n };\n}\n\nasync function listAllDataProviders(\n sdk: Sdk,\n): Promise<DataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { dataProviders } = await sdk.ListDataProviders({\n after,\n limit: PAGE_SIZE,\n });\n return dataProviders;\n });\n}\n\nasync function listAllDataProviderConnections(\n sdk: Sdk,\n): Promise<DataProviderConnectionFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { dataProviderConnections } = await sdk.ListDataProviderConnections({\n after,\n limit: PAGE_SIZE,\n });\n return dataProviderConnections;\n });\n}\n\nasync function listAllOrganizationDataProviders(\n sdk: Sdk,\n): Promise<OrganizationDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { organizationDataProviders } =\n await sdk.ListOrganizationDataProviders({ after, limit: PAGE_SIZE });\n return organizationDataProviders;\n });\n}\n\nasync function listAllSharedDataProviders(\n sdk: Sdk,\n): Promise<SharedDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { sharedDataProviders } = await sdk.ListSharedDataProviders({\n after,\n limit: PAGE_SIZE,\n });\n return sharedDataProviders;\n });\n}\n\nasync function listAllConfigurableDataProviders(\n sdk: Sdk,\n): Promise<ConfigurableDataProviderFieldsFragment[]> {\n return listAllPages(async (after) => {\n const { configurableDataProviders } =\n await sdk.ListConfigurableDataProviders({ after, limit: PAGE_SIZE });\n return configurableDataProviders;\n });\n}\n\nexport const sharedDataConnectionsQueryKey = clientGraphqlQueryKey(\n \"ListSharedDataProviders\",\n);\n\nexport const dataIntegrationConfigurationsQueryKey = clientGraphqlQueryKey(\n \"ListConfigurableDataProviders\",\n);\n\nexport const myDataIntegrationsQueryKeys = [\n clientGraphqlQueryKey(\"ListDataProviders\"),\n clientGraphqlQueryKey(\"ListDataProviderConnections\"),\n];\n\nexport const organizationDataIntegrationsQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationDataProviders\",\n);\n\ninterface ListResult<T> {\n data: T[];\n isLoading: boolean;\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n error: Error | null;\n failureCount: number;\n refetch: () => void;\n}\n\n/** The member's connectable providers joined with their own connections. */\nexport function useMyDataIntegrations({\n enabled = true,\n}: { enabled?: boolean } = {}): ListResult<DataIntegrationWithCapabilities> {\n const providers = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDataProviders\"),\n queryFn: listAllDataProviders,\n enabled,\n });\n const connections = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDataProviderConnections\"),\n queryFn: listAllDataProviderConnections,\n enabled,\n });\n\n const isSuccess = providers.isSuccess && connections.isSuccess;\n return {\n data: isSuccess\n ? toMyDataIntegrations(providers.data, connections.data)\n : [],\n isLoading: providers.isLoading || connections.isLoading,\n isPending: providers.isPending || connections.isPending,\n isSuccess,\n isError: providers.isError || connections.isError,\n error: providers.error ?? connections.error,\n failureCount: Math.max(providers.failureCount, connections.failureCount),\n refetch: () => {\n void providers.refetch();\n void connections.refetch();\n },\n };\n}\n\n/** The organization's provider inventory with its shared connections. */\nexport function useOrganizationDataIntegrations({\n enabled = true,\n}: {\n enabled?: boolean;\n} = {}): ListResult<OrganizationDataIntegrationWithCapabilities> {\n const query = useClientGraphqlQuery({\n queryKey: organizationDataIntegrationsQueryKey,\n queryFn: listAllOrganizationDataProviders,\n select: (providers) => providers.map(toOrganizationDataIntegration),\n enabled,\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/** The organization's shared connections, readable by any active member. */\nexport function useSharedDataConnections(): ListResult<SharedDataConnection> {\n const query = useClientGraphqlQuery({\n queryKey: sharedDataConnectionsQueryKey,\n queryFn: listAllSharedDataProviders,\n select: (providers) => providers.map(toSharedDataConnection),\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/** The organization's policy configuration of each connectable provider. */\nexport function useDataIntegrationConfigurations({\n enabled = true,\n}: { enabled?: boolean } = {}): ListResult<DataIntegrationConfiguration> {\n const query = useClientGraphqlQuery({\n queryKey: dataIntegrationConfigurationsQueryKey,\n queryFn: listAllConfigurableDataProviders,\n select: (providers) => providers.map(toDataIntegrationConfiguration),\n enabled,\n });\n return {\n data: query.data ?? [],\n isLoading: query.isLoading,\n isPending: query.isPending,\n isSuccess: query.isSuccess,\n isError: query.isError,\n error: query.error,\n failureCount: query.failureCount,\n refetch: () => {\n void query.refetch();\n },\n };\n}\n\n/**\n * Refreshes whatever a write for `owner` changed: the member's own list, or the\n * organization's inventory plus the shared section members see.\n */\nexport function useInvalidateConnections(owner: \"user\" | \"organization\") {\n const queryClient = useQueryClient();\n return useCallback(() => {\n if (owner === \"organization\") {\n queryClient.invalidateQueries({\n queryKey: organizationDataIntegrationsQueryKey,\n });\n queryClient.invalidateQueries({\n queryKey: sharedDataConnectionsQueryKey,\n });\n } else {\n for (const queryKey of myDataIntegrationsQueryKeys) {\n queryClient.invalidateQueries({ queryKey });\n }\n }\n }, [owner, queryClient]);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { clientGraphqlQueryKey
|
|
1
|
+
import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
|
|
2
|
+
import { useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
|
|
2
3
|
import { apiKeyMutationFailure, useListApiKeyPermissions } from "./api-key.js";
|
|
3
4
|
import { useUserApiKeysContext } from "../../widgets/api-keys/user-api-keys-context.js";
|
|
4
5
|
import { keepPreviousData, useQueryClient } from "@tanstack/react-query";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-api-key.js","names":[],"sources":["../../../../src/lib/api/user-api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n CreateUserApiKeyMutation,\n ExpireUserApiKeyMutation,\n UserApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { useUserApiKeysContext } from \"../../widgets/api-keys/user-api-keys-context.js\";\nimport {\n API_KEYS_PAGE_SIZE,\n apiKeyMutationFailure,\n useListApiKeyPermissions,\n} from \"./api-key.js\";\nimport type {\n CreateUserApiKeyRequest,\n CreateUserApiKeyResponse,\n ListUserApiKeyPermissionsParams,\n ListUserApiKeysResponse,\n ListUserApiKeysResponseData,\n} from \"./types.js\";\n\nexport type {\n CreateUserApiKeyResponse,\n ListUserApiKeyPermission,\n ListUserApiKeysResponse,\n ListUserApiKeysResponseData,\n} from \"./types.js\";\n\nexport const useListUserApiKeyPermissions = (\n params?: ListUserApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"User\", params);\n\nconst userApiKeysQueryKey = clientGraphqlQueryKey(\"ListUserApiKeys\");\n\nfunction toUserApiKey(\n apiKey: UserApiKeyFieldsFragment,\n): ListUserApiKeysResponseData {\n return {\n id: apiKey.id,\n owner: {\n type: \"user\",\n id: apiKey.owner.id,\n email: apiKey.owner.email,\n firstName: apiKey.owner.firstName ?? null,\n lastName: apiKey.owner.lastName ?? null,\n displayName: apiKey.owner.displayName,\n },\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nfunction unwrapCreateUserApiKey(\n result: CreateUserApiKeyMutation[\"createUserApiKey\"],\n): CreateUserApiKeyResponse {\n switch (result.__typename) {\n case \"UserApiKeyCreated\": {\n const { owner: _owner, ...apiKey } = toUserApiKey(result.apiKey);\n return { ...apiKey, value: result.value };\n }\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireUserApiKey(\n result: ExpireUserApiKeyMutation[\"expireUserApiKey\"],\n): ListUserApiKeysResponseData {\n switch (result.__typename) {\n case \"UserApiKeyExpired\":\n return toUserApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useUserApiKeys = () => {\n const {\n state: { pagination, searchQuery },\n } = useUserApiKeysContext();\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserApiKeys\", variables),\n queryFn: async (sdk) => {\n const { userApiKeys } = await sdk.ListUserApiKeys(variables);\n return userApiKeys;\n },\n select: (list): ListUserApiKeysResponse => ({\n data: list.data.map(toUserApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateUserApiKeys = () => {\n const queryClient = useQueryClient();\n return () => queryClient.invalidateQueries({ queryKey: userApiKeysQueryKey });\n};\n\nexport const useCreateUserApiKeyWithInvalidation = () => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { data }: { data: CreateUserApiKeyRequest }) => {\n const { createUserApiKey: result } = await sdk.CreateUserApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateUserApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteUserApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteUserApiKey } = await sdk.DeleteUserApiKey({ apiKeyId });\n return toUserApiKey(deleteUserApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireUserApiKey = () => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireUserApiKey: result } = await sdk.ExpireUserApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireUserApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-api-key.js","names":[],"sources":["../../../../src/lib/api/user-api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n CreateUserApiKeyMutation,\n ExpireUserApiKeyMutation,\n UserApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { useUserApiKeysContext } from \"../../widgets/api-keys/user-api-keys-context.js\";\nimport {\n API_KEYS_PAGE_SIZE,\n apiKeyMutationFailure,\n useListApiKeyPermissions,\n} from \"./api-key.js\";\nimport type {\n CreateUserApiKeyRequest,\n CreateUserApiKeyResponse,\n ListUserApiKeyPermissionsParams,\n ListUserApiKeysResponse,\n ListUserApiKeysResponseData,\n} from \"./types.js\";\n\nexport type {\n CreateUserApiKeyResponse,\n ListUserApiKeyPermission,\n ListUserApiKeysResponse,\n ListUserApiKeysResponseData,\n} from \"./types.js\";\n\nexport const useListUserApiKeyPermissions = (\n params?: ListUserApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"User\", params);\n\nconst userApiKeysQueryKey = clientGraphqlQueryKey(\"ListUserApiKeys\");\n\nfunction toUserApiKey(\n apiKey: UserApiKeyFieldsFragment,\n): ListUserApiKeysResponseData {\n return {\n id: apiKey.id,\n owner: {\n type: \"user\",\n id: apiKey.owner.id,\n email: apiKey.owner.email,\n firstName: apiKey.owner.firstName ?? null,\n lastName: apiKey.owner.lastName ?? null,\n displayName: apiKey.owner.displayName,\n },\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nfunction unwrapCreateUserApiKey(\n result: CreateUserApiKeyMutation[\"createUserApiKey\"],\n): CreateUserApiKeyResponse {\n switch (result.__typename) {\n case \"UserApiKeyCreated\": {\n const { owner: _owner, ...apiKey } = toUserApiKey(result.apiKey);\n return { ...apiKey, value: result.value };\n }\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireUserApiKey(\n result: ExpireUserApiKeyMutation[\"expireUserApiKey\"],\n): ListUserApiKeysResponseData {\n switch (result.__typename) {\n case \"UserApiKeyExpired\":\n return toUserApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useUserApiKeys = () => {\n const {\n state: { pagination, searchQuery },\n } = useUserApiKeysContext();\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserApiKeys\", variables),\n queryFn: async (sdk) => {\n const { userApiKeys } = await sdk.ListUserApiKeys(variables);\n return userApiKeys;\n },\n select: (list): ListUserApiKeysResponse => ({\n data: list.data.map(toUserApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateUserApiKeys = () => {\n const queryClient = useQueryClient();\n return () => queryClient.invalidateQueries({ queryKey: userApiKeysQueryKey });\n};\n\nexport const useCreateUserApiKeyWithInvalidation = () => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { data }: { data: CreateUserApiKeyRequest }) => {\n const { createUserApiKey: result } = await sdk.CreateUserApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateUserApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteUserApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteUserApiKey } = await sdk.DeleteUserApiKey({ apiKeyId });\n return toUserApiKey(deleteUserApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireUserApiKey = () => {\n const invalidate = useInvalidateUserApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireUserApiKey: result } = await sdk.ExpireUserApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireUserApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":";;;;;;AAgCA,MAAa,gCACX,WACG,yBAAyB,QAAQ,MAAM;AAE5C,MAAM,sBAAsB,sBAAsB,iBAAiB;AAEnE,SAAS,aACP,QAC6B;CAC7B,OAAO;EACL,IAAI,OAAO;EACX,OAAO;GACL,MAAM;GACN,IAAI,OAAO,MAAM;GACjB,OAAO,OAAO,MAAM;GACpB,WAAW,OAAO,MAAM,aAAa;GACrC,UAAU,OAAO,MAAM,YAAY;GACnC,aAAa,OAAO,MAAM;EAC5B;EACA,MAAM,OAAO;EACb,iBAAiB,OAAO;EACxB,WAAW,OAAO;EAClB,YAAY,OAAO,cAAc;EACjC,WAAW,OAAO,aAAa;EAC/B,aAAa,OAAO;CACtB;AACF;AAEA,SAAS,uBACP,QAC0B;CAC1B,QAAQ,OAAO,YAAf;EACE,KAAK,qBAAqB;GACxB,MAAM,EAAE,OAAO,QAAQ,GAAG,WAAW,aAAa,OAAO,MAAM;GAC/D,OAAO;IAAE,GAAG;IAAQ,OAAO,OAAO;GAAM;EAC1C;EACA,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,4BACH,MAAM,sBAAsB,OAAO,YAAY,OAAO,OAAO;CACjE;AACF;AAEA,SAAS,uBACP,QAC6B;CAC7B,QAAQ,OAAO,YAAf;EACE,KAAK,qBACH,OAAO,aAAa,OAAO,MAAM;EACnC,KAAK,wBACH,MAAM,sBACJ,OAAO,YACP,4BACF;CACJ;AACF;AAEA,MAAa,uBAAuB;CAClC,MAAM,EACJ,OAAO,EAAE,YAAY,kBACnB,sBAAsB;CAC1B,MAAM,EAAE,QAAQ,UAAU,cAAc,CAAC;CACzC,MAAM,YAAY;EAChB,OAAO,SAAS;EAChB,QAAQ,UAAU;EAClB,OAAA;EACA,QAAQ,eAAe;CACzB;CAEA,OAAO,sBAAsB;EAC3B,UAAU,sBAAsB,mBAAmB,SAAS;EAC5D,SAAS,OAAO,QAAQ;GACtB,MAAM,EAAE,gBAAgB,MAAM,IAAI,gBAAgB,SAAS;GAC3D,OAAO;EACT;EACA,SAAS,UAAmC;GAC1C,MAAM,KAAK,KAAK,IAAI,YAAY;GAChC,eAAe;IACb,OAAO,KAAK,aAAa,SAAS;IAClC,QAAQ,KAAK,aAAa,UAAU;GACtC;EACF;EACA,iBAAiB;CACnB,CAAC;AACH;AAEA,MAAM,iCAAiC;CACrC,MAAM,cAAc,eAAe;CACnC,aAAa,YAAY,kBAAkB,EAAE,UAAU,oBAAoB,CAAC;AAC9E;AAEA,MAAa,4CAA4C;CACvD,MAAM,aAAa,yBAAyB;CAE5C,OAAO,yBAAyB;EAC9B,YAAY,OAAO,KAAK,EAAE,WAA8C;GACtE,MAAM,EAAE,kBAAkB,WAAW,MAAM,IAAI,iBAAiB,EAC9D,OAAO;IACL,MAAM,KAAK;IACX,aAAa,KAAK;IAClB,WAAW,KAAK,aAAa;GAC/B,EACF,CAAC;GACD,OAAO,uBAAuB,MAAM;EACtC;EACA,WAAW;CACb,CAAC;AACH;AAEA,MAAa,uBAAuB,EAClC,cAC8B,CAAC,MAAM;CACrC,MAAM,aAAa,yBAAyB;CAE5C,OAAO,yBAAyB;EAC9B,YAAY,OAAO,KAAK,EAAE,eAAqC;GAC7D,MAAM,EAAE,qBAAqB,MAAM,IAAI,iBAAiB,EAAE,SAAS,CAAC;GACpE,OAAO,aAAa,gBAAgB;EACtC;EACA,iBAAiB;GACf,AAAK,WAAW;GAChB,YAAY;EACd;CACF,CAAC;AACH;AAEA,MAAa,4BAA4B;CACvC,MAAM,aAAa,yBAAyB;CAE5C,OAAO,yBAAyB;EAC9B,YAAY,OACV,KACA,EAAE,UAAU,gBACT;GACH,MAAM,EAAE,kBAAkB,WAAW,MAAM,IAAI,iBAAiB,EAC9D,OAAO;IAAE;IAAU;GAAU,EAC/B,CAAC;GACD,OAAO,uBAAuB,MAAM;EACtC;EACA,WAAW;CACb,CAAC;AACH"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { isClientGraphqlQueryKey } from "../api/client-graphql/
|
|
1
|
+
import { isClientGraphqlQueryKey } from "../api/client-graphql/query-keys.js";
|
|
2
|
+
import "../api/client-graphql/hooks.js";
|
|
2
3
|
import { useQueryClient } from "@tanstack/react-query";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
//#region src/lib/use-widgets-invalidator.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-widgets-invalidator.js","names":[],"sources":["../../../src/lib/use-widgets-invalidator.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { isClientGraphqlQueryKey } from \"../api/client-graphql/hooks.js\";\n\nfunction useWidgetsInvalidatorImpl() {\n const queryClient = useQueryClient();\n\n return React.useCallback(async () => {\n await queryClient.invalidateQueries({ queryKey: [\"authToken\"] });\n return queryClient.invalidateQueries({\n predicate: (query) => isClientGraphqlQueryKey(query.queryKey),\n });\n }, [queryClient]);\n}\n\nfunction useWidgetsInvalidator() {\n try {\n // oxlint-disable-next-line react-hooks/rules-of-hooks\n return useWidgetsInvalidatorImpl();\n } catch {\n throw Error(\n \"useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component\",\n );\n }\n}\n\nexport { useWidgetsInvalidator };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-widgets-invalidator.js","names":[],"sources":["../../../src/lib/use-widgets-invalidator.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { isClientGraphqlQueryKey } from \"../api/client-graphql/hooks.js\";\n\nfunction useWidgetsInvalidatorImpl() {\n const queryClient = useQueryClient();\n\n return React.useCallback(async () => {\n await queryClient.invalidateQueries({ queryKey: [\"authToken\"] });\n return queryClient.invalidateQueries({\n predicate: (query) => isClientGraphqlQueryKey(query.queryKey),\n });\n }, [queryClient]);\n}\n\nfunction useWidgetsInvalidator() {\n try {\n // oxlint-disable-next-line react-hooks/rules-of-hooks\n return useWidgetsInvalidatorImpl();\n } catch {\n throw Error(\n \"useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component\",\n );\n }\n}\n\nexport { useWidgetsInvalidator };\n"],"mappings":";;;;;AAIA,SAAS,4BAA4B;CACnC,MAAM,cAAc,eAAe;CAEnC,OAAO,MAAM,YAAY,YAAY;EACnC,MAAM,YAAY,kBAAkB,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC;EAC/D,OAAO,YAAY,kBAAkB,EACnC,YAAY,UAAU,wBAAwB,MAAM,QAAQ,EAC9D,CAAC;CACH,GAAG,CAAC,WAAW,CAAC;AAClB;AAEA,SAAS,wBAAwB;CAC/B,IAAI;EAEF,OAAO,0BAA0B;CACnC,QAAQ;EACN,MAAM,MACJ,mFACF;CACF;AACF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useWorkOsApiUrl } from "./lib/widgets-context.js";
|
|
3
|
+
import { clientGraphqlQueryKey } from "./api/client-graphql/query-keys.js";
|
|
3
4
|
import { ApiProvider, useApiReady } from "./api/api-provider.js";
|
|
4
|
-
import {
|
|
5
|
+
import { useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
|
|
5
6
|
import { ErrorBoundary } from "./components/error-boundary.js";
|
|
6
7
|
import { OrganizationSwitcher as OrganizationSwitcher$1, OrganizationSwitcherError, OrganizationSwitcherLoading } from "./widgets/organization-switcher/organization-switcher.js";
|
|
7
8
|
import { keepPreviousData } from "@tanstack/react-query";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organization-switcher.client.js","names":["OrganizationSwitcherPresentational"],"sources":["../../src/organization-switcher.client.tsx"],"sourcesContent":["\"use client\";\n\nimport { keepPreviousData } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport type {\n OrganizationSwitcherErrorProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherPassthroughProps,\n UserOrganization,\n} from \"./widgets/organization-switcher/organization-switcher.js\";\nimport {\n OrganizationSwitcherError,\n OrganizationSwitcherLoading,\n OrganizationSwitcher as OrganizationSwitcherPresentational,\n} from \"./widgets/organization-switcher/organization-switcher.js\";\n\ninterface OrganizationSwitcherProps extends OrganizationSwitcherPassthroughProps {\n authToken: AuthToken;\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n authToken,\n organizationLabel,\n switchToOrganization,\n truncateBehavior,\n variant,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <OrganizationSwitcherError\n error={error}\n variant={variant}\n {...domProps}\n />\n )}\n >\n <ApiProvider\n widgetType=\"organization-switcher\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <OrganizationSwitcherImpl\n switchToOrganization={switchToOrganization}\n organizationLabel={organizationLabel}\n truncateBehavior={truncateBehavior}\n variant={variant}\n {...domProps}\n />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\n// Constant reference to avoid unnecessary prop changes\nconst emptyOrganizations: UserOrganization[] = [];\n\ninterface OrganizationSwitcherImplProps extends OrganizationSwitcherPassthroughProps {}\n\nconst OrganizationSwitcherImpl: React.FC<OrganizationSwitcherImplProps> = ({\n variant,\n switchToOrganization,\n organizationLabel,\n truncateBehavior,\n children,\n ...domProps\n}) => {\n const isApiReady = useApiReady();\n const organizationsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserOrganizations\"),\n queryFn: (sdk) => sdk.ListUserOrganizations(),\n select: (data) => data.organizations,\n placeholderData: keepPreviousData,\n });\n\n const organizations = organizationsQuery.data ?? emptyOrganizations;\n\n if (organizationsQuery.isLoading || !isApiReady) {\n return <OrganizationSwitcherLoading variant={variant} {...domProps} />;\n }\n\n if (organizationsQuery.isError) {\n return (\n <OrganizationSwitcherError\n error={organizationsQuery.error}\n variant={variant}\n {...domProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <OrganizationSwitcherError\n error={error}\n variant={variant}\n {...domProps}\n />\n )}\n >\n <OrganizationSwitcherPresentational\n organizations={organizations}\n switchToOrganization={switchToOrganization}\n variant={variant}\n organizationLabel={organizationLabel}\n truncateBehavior={truncateBehavior}\n {...domProps}\n >\n {children}\n </OrganizationSwitcherPresentational>\n </ErrorBoundary>\n );\n};\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"organization-switcher.client.js","names":["OrganizationSwitcherPresentational"],"sources":["../../src/organization-switcher.client.tsx"],"sourcesContent":["\"use client\";\n\nimport { keepPreviousData } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport type {\n OrganizationSwitcherErrorProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherPassthroughProps,\n UserOrganization,\n} from \"./widgets/organization-switcher/organization-switcher.js\";\nimport {\n OrganizationSwitcherError,\n OrganizationSwitcherLoading,\n OrganizationSwitcher as OrganizationSwitcherPresentational,\n} from \"./widgets/organization-switcher/organization-switcher.js\";\n\ninterface OrganizationSwitcherProps extends OrganizationSwitcherPassthroughProps {\n authToken: AuthToken;\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n authToken,\n organizationLabel,\n switchToOrganization,\n truncateBehavior,\n variant,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <OrganizationSwitcherError\n error={error}\n variant={variant}\n {...domProps}\n />\n )}\n >\n <ApiProvider\n widgetType=\"organization-switcher\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <OrganizationSwitcherImpl\n switchToOrganization={switchToOrganization}\n organizationLabel={organizationLabel}\n truncateBehavior={truncateBehavior}\n variant={variant}\n {...domProps}\n />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\n// Constant reference to avoid unnecessary prop changes\nconst emptyOrganizations: UserOrganization[] = [];\n\ninterface OrganizationSwitcherImplProps extends OrganizationSwitcherPassthroughProps {}\n\nconst OrganizationSwitcherImpl: React.FC<OrganizationSwitcherImplProps> = ({\n variant,\n switchToOrganization,\n organizationLabel,\n truncateBehavior,\n children,\n ...domProps\n}) => {\n const isApiReady = useApiReady();\n const organizationsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserOrganizations\"),\n queryFn: (sdk) => sdk.ListUserOrganizations(),\n select: (data) => data.organizations,\n placeholderData: keepPreviousData,\n });\n\n const organizations = organizationsQuery.data ?? emptyOrganizations;\n\n if (organizationsQuery.isLoading || !isApiReady) {\n return <OrganizationSwitcherLoading variant={variant} {...domProps} />;\n }\n\n if (organizationsQuery.isError) {\n return (\n <OrganizationSwitcherError\n error={organizationsQuery.error}\n variant={variant}\n {...domProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <OrganizationSwitcherError\n error={error}\n variant={variant}\n {...domProps}\n />\n )}\n >\n <OrganizationSwitcherPresentational\n organizations={organizations}\n switchToOrganization={switchToOrganization}\n variant={variant}\n organizationLabel={organizationLabel}\n truncateBehavior={truncateBehavior}\n {...domProps}\n >\n {children}\n </OrganizationSwitcherPresentational>\n </ErrorBoundary>\n );\n};\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":";;;;;;;;;;;AA4BA,MAAM,wBAA6D,EACjE,WACA,mBACA,sBACA,kBACA,SACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,2BAAD;GACS;GACE;GACT,GAAI;EACL,CAAA;EAGH,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,0BAAD;IACwB;IACH;IACD;IACT;IACT,GAAI;GACL,CAAA;EACU,CAAA;CACA,CAAA;AAEnB;AAGA,MAAM,qBAAyC,CAAC;AAIhD,MAAM,4BAAqE,EACzE,SACA,sBACA,mBACA,kBACA,UACA,GAAG,eACC;CACJ,MAAM,aAAa,YAAY;CAC/B,MAAM,qBAAqB,sBAAsB;EAC/C,UAAU,sBAAsB,uBAAuB;EACvD,UAAU,QAAQ,IAAI,sBAAsB;EAC5C,SAAS,SAAS,KAAK;EACvB,iBAAiB;CACnB,CAAC;CAED,MAAM,gBAAgB,mBAAmB,QAAQ;CAEjD,IAAI,mBAAmB,aAAa,CAAC,YACnC,OAAO,oBAAC,6BAAD;EAAsC;EAAS,GAAI;CAAW,CAAA;CAGvE,IAAI,mBAAmB,SACrB,OACE,oBAAC,2BAAD;EACE,OAAO,mBAAmB;EACjB;EACT,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,2BAAD;GACS;GACE;GACT,GAAI;EACL,CAAA;EAGH,UAAA,oBAACA,wBAAD;GACiB;GACO;GACb;GACU;GACD;GAClB,GAAI;GAEH;EACiC,CAAA;CACvB,CAAA;AAEnB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useWorkOsApiUrl } from "./lib/widgets-context.js";
|
|
3
3
|
import { useIsHydrated } from "./lib/use-is-hydrated.js";
|
|
4
|
+
import { clientGraphqlQueryKey } from "./api/client-graphql/query-keys.js";
|
|
4
5
|
import { ApiProvider } from "./api/api-provider.js";
|
|
5
|
-
import {
|
|
6
|
+
import { useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
|
|
6
7
|
import { ErrorBoundary } from "./components/error-boundary.js";
|
|
7
8
|
import { PipesCredentialUserIdContext } from "./widgets/pipes/pipes-credential-attribution.js";
|
|
8
9
|
import { PipesAdmin as PipesAdmin$1, PipesAdminError, PipesAdminLoading, PipesAdminSections, useManageableIntegrations, useOrganizationOwnedIntegrations } from "./widgets/pipes-admin/pipes-admin.js";
|