@burdenoff/microfe-auth 2026.510.127
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/README.md +12 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/auth/AuthRoot.d.ts +30 -0
- package/dist/auth/AuthRoot.d.ts.map +1 -0
- package/dist/auth/AuthRoot.js +82 -0
- package/dist/auth/AuthRoot.js.map +1 -0
- package/dist/auth/AuthRoutes.d.ts +29 -0
- package/dist/auth/AuthRoutes.d.ts.map +1 -0
- package/dist/auth/AuthRoutes.js +271 -0
- package/dist/auth/AuthRoutes.js.map +1 -0
- package/dist/auth/components/AuthIcons.d.ts +17 -0
- package/dist/auth/components/AuthIcons.d.ts.map +1 -0
- package/dist/auth/components/AuthIcons.js +197 -0
- package/dist/auth/components/AuthIcons.js.map +1 -0
- package/dist/auth/components/AuthLayout.d.ts +17 -0
- package/dist/auth/components/AuthLayout.d.ts.map +1 -0
- package/dist/auth/components/AuthLayout.js +237 -0
- package/dist/auth/components/AuthLayout.js.map +1 -0
- package/dist/auth/components/CaptchaV2.d.ts +16 -0
- package/dist/auth/components/CaptchaV2.d.ts.map +1 -0
- package/dist/auth/components/CaptchaV2.js +47 -0
- package/dist/auth/components/CaptchaV2.js.map +1 -0
- package/dist/auth/components/ConfirmActionDialog.d.ts +16 -0
- package/dist/auth/components/ConfirmActionDialog.d.ts.map +1 -0
- package/dist/auth/components/ConfirmActionDialog.js +68 -0
- package/dist/auth/components/ConfirmActionDialog.js.map +1 -0
- package/dist/auth/components/index.d.ts +4 -0
- package/dist/auth/components/index.d.ts.map +1 -0
- package/dist/auth/components/profile/UserProfileMenu.d.ts +42 -0
- package/dist/auth/components/profile/UserProfileMenu.d.ts.map +1 -0
- package/dist/auth/components/profile/UserProfileMenu.js +91 -0
- package/dist/auth/components/profile/UserProfileMenu.js.map +1 -0
- package/dist/auth/components/workspace/WorkspaceSelector.d.ts +76 -0
- package/dist/auth/components/workspace/WorkspaceSelector.d.ts.map +1 -0
- package/dist/auth/components/workspace/WorkspaceSelector.js +240 -0
- package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -0
- package/dist/auth/constants/permissions.d.ts +30 -0
- package/dist/auth/constants/permissions.d.ts.map +1 -0
- package/dist/auth/constants/permissions.js +18 -0
- package/dist/auth/constants/permissions.js.map +1 -0
- package/dist/auth/constants/sessionKeys.d.ts +18 -0
- package/dist/auth/constants/sessionKeys.d.ts.map +1 -0
- package/dist/auth/constants/sessionKeys.js +6 -0
- package/dist/auth/constants/sessionKeys.js.map +1 -0
- package/dist/auth/hooks/index.d.ts +18 -0
- package/dist/auth/hooks/index.d.ts.map +1 -0
- package/dist/auth/hooks/index.js +16 -0
- package/dist/auth/hooks/useAccountOperations.d.ts +19 -0
- package/dist/auth/hooks/useAccountOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAccountOperations.js +52 -0
- package/dist/auth/hooks/useAccountOperations.js.map +1 -0
- package/dist/auth/hooks/useApiKeyOperations.d.ts +22 -0
- package/dist/auth/hooks/useApiKeyOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useApiKeyOperations.js +4 -0
- package/dist/auth/hooks/useAppOperations.d.ts +26 -0
- package/dist/auth/hooks/useAppOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAppOperations.js +4 -0
- package/dist/auth/hooks/useAuthOperations.d.ts +57 -0
- package/dist/auth/hooks/useAuthOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAuthOperations.js +236 -0
- package/dist/auth/hooks/useAuthOperations.js.map +1 -0
- package/dist/auth/hooks/useAuthPermissions.d.ts +20 -0
- package/dist/auth/hooks/useAuthPermissions.d.ts.map +1 -0
- package/dist/auth/hooks/useAuthPermissions.js +22 -0
- package/dist/auth/hooks/useAuthPermissions.js.map +1 -0
- package/dist/auth/hooks/useCaptchaV3.d.ts +13 -0
- package/dist/auth/hooks/useCaptchaV3.d.ts.map +1 -0
- package/dist/auth/hooks/useCaptchaV3.js +19 -0
- package/dist/auth/hooks/useCaptchaV3.js.map +1 -0
- package/dist/auth/hooks/useContextSwitcherData.d.ts +106 -0
- package/dist/auth/hooks/useContextSwitcherData.d.ts.map +1 -0
- package/dist/auth/hooks/useContextSwitcherData.js +466 -0
- package/dist/auth/hooks/useContextSwitcherData.js.map +1 -0
- package/dist/auth/hooks/useDelegationOperations.d.ts +25 -0
- package/dist/auth/hooks/useDelegationOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useDelegationOperations.js +4 -0
- package/dist/auth/hooks/useMfaOperations.d.ts +18 -0
- package/dist/auth/hooks/useMfaOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useMfaOperations.js +103 -0
- package/dist/auth/hooks/useMfaOperations.js.map +1 -0
- package/dist/auth/hooks/useMyWorkspaces.d.ts +45 -0
- package/dist/auth/hooks/useMyWorkspaces.d.ts.map +1 -0
- package/dist/auth/hooks/useMyWorkspaces.js +140 -0
- package/dist/auth/hooks/useMyWorkspaces.js.map +1 -0
- package/dist/auth/hooks/useOAuthOperations.d.ts +19 -0
- package/dist/auth/hooks/useOAuthOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useOAuthOperations.js +103 -0
- package/dist/auth/hooks/useOAuthOperations.js.map +1 -0
- package/dist/auth/hooks/usePasswordOperations.d.ts +13 -0
- package/dist/auth/hooks/usePasswordOperations.d.ts.map +1 -0
- package/dist/auth/hooks/usePasswordOperations.js +56 -0
- package/dist/auth/hooks/usePasswordOperations.js.map +1 -0
- package/dist/auth/hooks/useSessionOperations.d.ts +41 -0
- package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useSessionOperations.js +59 -0
- package/dist/auth/hooks/useSessionOperations.js.map +1 -0
- package/dist/auth/hooks/useSsoOperations.d.ts +65 -0
- package/dist/auth/hooks/useSsoOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useSsoOperations.js +236 -0
- package/dist/auth/hooks/useSsoOperations.js.map +1 -0
- package/dist/auth/hooks/useTokenRefresh.d.ts +56 -0
- package/dist/auth/hooks/useTokenRefresh.d.ts.map +1 -0
- package/dist/auth/hooks/useTokenRefresh.js +53 -0
- package/dist/auth/hooks/useTokenRefresh.js.map +1 -0
- package/dist/auth/hooks/useUserOperations.d.ts +32 -0
- package/dist/auth/hooks/useUserOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useUserOperations.js +100 -0
- package/dist/auth/hooks/useUserOperations.js.map +1 -0
- package/dist/auth/hooks/useWorkspaceOperations.d.ts +35 -0
- package/dist/auth/hooks/useWorkspaceOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useWorkspaceOperations.js +35 -0
- package/dist/auth/hooks/useWorkspaceOperations.js.map +1 -0
- package/dist/auth/hooks/useWorkspaceToken.d.ts +56 -0
- package/dist/auth/hooks/useWorkspaceToken.d.ts.map +1 -0
- package/dist/auth/hooks/useWorkspaceToken.js +94 -0
- package/dist/auth/hooks/useWorkspaceToken.js.map +1 -0
- package/dist/auth/index.d.ts +63 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +18 -0
- package/dist/auth/pages/ApiKeysPage.d.ts +5 -0
- package/dist/auth/pages/ApiKeysPage.d.ts.map +1 -0
- package/dist/auth/pages/AppsPage.d.ts +5 -0
- package/dist/auth/pages/AppsPage.d.ts.map +1 -0
- package/dist/auth/pages/AuditLogPage.d.ts +5 -0
- package/dist/auth/pages/AuditLogPage.d.ts.map +1 -0
- package/dist/auth/pages/AuditLogPage.js +129 -0
- package/dist/auth/pages/AuditLogPage.js.map +1 -0
- package/dist/auth/pages/DelegationsPage.d.ts +5 -0
- package/dist/auth/pages/DelegationsPage.d.ts.map +1 -0
- package/dist/auth/pages/EmailVerifyPage.d.ts +5 -0
- package/dist/auth/pages/EmailVerifyPage.d.ts.map +1 -0
- package/dist/auth/pages/EmailVerifyPage.js +166 -0
- package/dist/auth/pages/EmailVerifyPage.js.map +1 -0
- package/dist/auth/pages/LoginPage.d.ts +6 -0
- package/dist/auth/pages/LoginPage.d.ts.map +1 -0
- package/dist/auth/pages/LoginPage.js +575 -0
- package/dist/auth/pages/LoginPage.js.map +1 -0
- package/dist/auth/pages/MagicLinkPage.d.ts +6 -0
- package/dist/auth/pages/MagicLinkPage.d.ts.map +1 -0
- package/dist/auth/pages/MagicLinkPage.js +219 -0
- package/dist/auth/pages/MagicLinkPage.js.map +1 -0
- package/dist/auth/pages/MfaSetupPage.d.ts +5 -0
- package/dist/auth/pages/MfaSetupPage.d.ts.map +1 -0
- package/dist/auth/pages/MfaSetupPage.js +341 -0
- package/dist/auth/pages/MfaSetupPage.js.map +1 -0
- package/dist/auth/pages/MfaVerifyPage.d.ts +7 -0
- package/dist/auth/pages/MfaVerifyPage.d.ts.map +1 -0
- package/dist/auth/pages/MfaVerifyPage.js +189 -0
- package/dist/auth/pages/MfaVerifyPage.js.map +1 -0
- package/dist/auth/pages/OAuthCallbackPage.d.ts +7 -0
- package/dist/auth/pages/OAuthCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/OAuthCallbackPage.js +100 -0
- package/dist/auth/pages/OAuthCallbackPage.js.map +1 -0
- package/dist/auth/pages/PasswordResetPage.d.ts +6 -0
- package/dist/auth/pages/PasswordResetPage.d.ts.map +1 -0
- package/dist/auth/pages/PasswordResetPage.js +352 -0
- package/dist/auth/pages/PasswordResetPage.js.map +1 -0
- package/dist/auth/pages/ReactivatePage.d.ts +6 -0
- package/dist/auth/pages/ReactivatePage.d.ts.map +1 -0
- package/dist/auth/pages/ReactivatePage.js +217 -0
- package/dist/auth/pages/ReactivatePage.js.map +1 -0
- package/dist/auth/pages/RegisterPage.d.ts +5 -0
- package/dist/auth/pages/RegisterPage.d.ts.map +1 -0
- package/dist/auth/pages/RegisterPage.js +439 -0
- package/dist/auth/pages/RegisterPage.js.map +1 -0
- package/dist/auth/pages/SSORelayCallbackPage.d.ts +8 -0
- package/dist/auth/pages/SSORelayCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/SSORelayCallbackPage.js +48 -0
- package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -0
- package/dist/auth/pages/SSORelayPage.d.ts +18 -0
- package/dist/auth/pages/SSORelayPage.d.ts.map +1 -0
- package/dist/auth/pages/SSORelayPage.js +134 -0
- package/dist/auth/pages/SSORelayPage.js.map +1 -0
- package/dist/auth/pages/SecurityPage.d.ts +5 -0
- package/dist/auth/pages/SecurityPage.d.ts.map +1 -0
- package/dist/auth/pages/SecurityPage.js +587 -0
- package/dist/auth/pages/SecurityPage.js.map +1 -0
- package/dist/auth/pages/SessionBridgePage.d.ts +14 -0
- package/dist/auth/pages/SessionBridgePage.d.ts.map +1 -0
- package/dist/auth/pages/SessionBridgePage.js +231 -0
- package/dist/auth/pages/SessionBridgePage.js.map +1 -0
- package/dist/auth/pages/SessionsPage.d.ts +5 -0
- package/dist/auth/pages/SessionsPage.d.ts.map +1 -0
- package/dist/auth/pages/SessionsPage.js +258 -0
- package/dist/auth/pages/SessionsPage.js.map +1 -0
- package/dist/auth/pages/SsoCallbackPage.d.ts +8 -0
- package/dist/auth/pages/SsoCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoCallbackPage.js +188 -0
- package/dist/auth/pages/SsoCallbackPage.js.map +1 -0
- package/dist/auth/pages/SsoConfigPage.d.ts +6 -0
- package/dist/auth/pages/SsoConfigPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoConfigPage.js +1144 -0
- package/dist/auth/pages/SsoConfigPage.js.map +1 -0
- package/dist/auth/pages/SsoLoginPage.d.ts +7 -0
- package/dist/auth/pages/SsoLoginPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoLoginPage.js +236 -0
- package/dist/auth/pages/SsoLoginPage.js.map +1 -0
- package/dist/auth/pages/UserDetailsPage.d.ts +11 -0
- package/dist/auth/pages/UserDetailsPage.d.ts.map +1 -0
- package/dist/auth/pages/UserDetailsPage.js +338 -0
- package/dist/auth/pages/UserDetailsPage.js.map +1 -0
- package/dist/auth/pages/UserProfilePage.d.ts +5 -0
- package/dist/auth/pages/UserProfilePage.d.ts.map +1 -0
- package/dist/auth/pages/UserProfilePage.js +445 -0
- package/dist/auth/pages/UserProfilePage.js.map +1 -0
- package/dist/auth/pages/UsersPage.d.ts +5 -0
- package/dist/auth/pages/UsersPage.d.ts.map +1 -0
- package/dist/auth/pages/UsersPage.js +899 -0
- package/dist/auth/pages/UsersPage.js.map +1 -0
- package/dist/auth/providers/AuthProvider.d.ts +18 -0
- package/dist/auth/providers/AuthProvider.d.ts.map +1 -0
- package/dist/auth/providers/AuthProvider.js +36 -0
- package/dist/auth/providers/AuthProvider.js.map +1 -0
- package/dist/auth/providers/CaptchaProvider.d.ts +13 -0
- package/dist/auth/providers/CaptchaProvider.d.ts.map +1 -0
- package/dist/auth/providers/CaptchaProvider.js +21 -0
- package/dist/auth/providers/CaptchaProvider.js.map +1 -0
- package/dist/auth/store/authStore.d.ts +91 -0
- package/dist/auth/store/authStore.d.ts.map +1 -0
- package/dist/auth/store/authStore.js +314 -0
- package/dist/auth/store/authStore.js.map +1 -0
- package/dist/auth/types/index.d.ts +636 -0
- package/dist/auth/types/index.d.ts.map +1 -0
- package/dist/auth/utils/captchaConfig.d.ts +4 -0
- package/dist/auth/utils/captchaConfig.d.ts.map +1 -0
- package/dist/auth/utils/captchaConfig.js +13 -0
- package/dist/auth/utils/captchaConfig.js.map +1 -0
- package/dist/auth/utils/formatters.d.ts +37 -0
- package/dist/auth/utils/formatters.d.ts.map +1 -0
- package/dist/auth/utils/formatters.js +48 -0
- package/dist/auth/utils/formatters.js.map +1 -0
- package/dist/auth/utils/gatewayBaseUrls.d.ts +6 -0
- package/dist/auth/utils/gatewayBaseUrls.d.ts.map +1 -0
- package/dist/auth/utils/gatewayBaseUrls.js +18 -0
- package/dist/auth/utils/gatewayBaseUrls.js.map +1 -0
- package/dist/auth/utils/index.d.ts +3 -0
- package/dist/auth/utils/index.d.ts.map +1 -0
- package/dist/auth/utils/validation.d.ts +30 -0
- package/dist/auth/utils/validation.d.ts.map +1 -0
- package/dist/auth/utils/validation.js +15 -0
- package/dist/auth/utils/validation.js.map +1 -0
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2978 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-operations.js +944 -0
- package/dist/generated/global-operations.js.map +1 -0
- package/dist/generated/global-types.d.ts +21253 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +55214 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/microfe-auth.css +3 -0
- package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +70 -0
- package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
- package/dist/node_modules/object-assign/index.js +41 -0
- package/dist/node_modules/object-assign/index.js.map +1 -0
- package/dist/node_modules/prop-types/checkPropTypes.js +46 -0
- package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -0
- package/dist/node_modules/prop-types/factoryWithThrowingShims.js +49 -0
- package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -0
- package/dist/node_modules/prop-types/factoryWithTypeCheckers.js +272 -0
- package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -0
- package/dist/node_modules/prop-types/index.js +16 -0
- package/dist/node_modules/prop-types/index.js.map +1 -0
- package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js +10 -0
- package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -0
- package/dist/node_modules/prop-types/lib/has.js +10 -0
- package/dist/node_modules/prop-types/lib/has.js.map +1 -0
- package/dist/node_modules/qrcode.react/lib/esm/index.js +959 -0
- package/dist/node_modules/qrcode.react/lib/esm/index.js.map +1 -0
- package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js +114 -0
- package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/index.js +8 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/index.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js +20 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js +148 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js +445 -0
- package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js.map +1 -0
- package/dist/node_modules/react-is/cjs/react-is.development.js +84 -0
- package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -0
- package/dist/node_modules/react-is/cjs/react-is.production.min.js +64 -0
- package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
- package/dist/node_modules/react-is/index.js +12 -0
- package/dist/node_modules/react-is/index.js.map +1 -0
- package/dist/shared/hooks/index.d.ts +7 -0
- package/dist/shared/hooks/index.d.ts.map +1 -0
- package/dist/shared/index.d.ts +6 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/types/index.d.ts +109 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/utils/nativeBridge.d.ts +3 -0
- package/dist/utils/nativeBridge.d.ts.map +1 -0
- package/dist/utils/nativeBridge.js +2 -0
- package/package.json +114 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContextSwitcherData.js","names":[],"sources":["../../../src/auth/hooks/useContextSwitcherData.ts"],"sourcesContent":["import { useCallback, useState, useEffect, useRef } from \"react\";\nimport {\n graphqlFetch,\n getStoredAuthToken,\n} from \"@burdenoff/fe-libs/shared/graphql\";\nimport { useActiveContext } from \"@burdenoff/fe-libs/shared/providers/shell/ActiveContextProvider\";\nimport { useAuthStore } from \"../store/authStore\";\nimport type { Organization, Workspace, Project } from \"../types\";\nimport { resolveGatewayBaseUrls } from \"../utils/gatewayBaseUrls\";\n\n// =============================================================================\n// Hook Options\n// =============================================================================\n\nexport interface UseContextSwitcherDataOptions {\n /**\n * Optional Global API Gateway base URL override.\n * If not provided, uses GATEWAYS config from fe-libs.\n */\n globalBaseUrl?: string;\n /**\n * Optional Workspaces API Gateway base URL override.\n * If not provided, uses GATEWAYS config from fe-libs.\n */\n workspaceBaseUrl?: string;\n /** Disable initial organization/workspace bootstrap fetches */\n disableBootstrap?: boolean;\n /** Disable the workspace sync effect */\n disableWorkspaceSync?: boolean;\n /** Disable the project sync effect */\n disableProjectSync?: boolean;\n /** Only hydrate the workspace token; do not eagerly fetch projects */\n skipProjectFetch?: boolean;\n}\n\n// =============================================================================\n// GraphQL Response Types\n// =============================================================================\n\ninterface MyOrganizationsResponse {\n myOrganizations: {\n total: number;\n items: Organization[];\n };\n}\n\ninterface WorkspacesByOrgResponse {\n workspaces: {\n total: number;\n items: Workspace[];\n };\n}\n\ninterface IssueWorkspaceTokenResult {\n success: boolean;\n token: string | null;\n expiresAt: string | null;\n organizationId: string | null;\n workspaceId: string | null;\n projectId: string | null;\n scopes: string[] | null;\n error: {\n code: string;\n message: string;\n } | null;\n}\n\ninterface ProjectsResponse {\n projects: {\n total: number;\n items: Project[];\n };\n}\n\ninterface CreateProjectResponse {\n createProject: Project;\n}\n\n// =============================================================================\n// GraphQL Query/Mutation Strings\n// =============================================================================\n\nconst MY_ORGANIZATIONS_QUERY = `\n query MyOrganizations {\n myOrganizations {\n total\n items {\n id\n name\n slug\n tenantId\n description\n logo\n website\n status\n type\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nconst WORKSPACES_BY_ORG_QUERY = `\n query WorkspacesByOrg($filter: WorkspaceFilterInput) {\n workspaces(filter: $filter) {\n total\n items {\n id\n name\n slug\n tenantId\n organizationId\n type\n status\n region\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nconst CONTEXT_SWITCHER_BOOTSTRAP_QUERY = `\n query ContextSwitcherBootstrap($filter: WorkspaceFilterInput) {\n myOrganizations {\n total\n items {\n id\n name\n slug\n tenantId\n description\n logo\n website\n status\n type\n createdAt\n updatedAt\n }\n }\n workspaces(filter: $filter) {\n total\n items {\n id\n name\n slug\n tenantId\n organizationId\n type\n status\n region\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nconst ISSUE_WORKSPACE_TOKEN_MUTATION = `\n mutation IssueWorkspaceToken($input: IssueWorkspaceTokenInput!) {\n issueWorkspaceToken(input: $input) {\n success\n token\n expiresAt\n organizationId\n workspaceId\n projectId\n scopes\n error {\n code\n message\n }\n }\n }\n`;\n\nconst PROJECTS_QUERY = `\n query Projects($filter: ProjectFilterInput) {\n projects(filter: $filter) {\n total\n items {\n id\n name\n key\n workspaceId\n status\n archived\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nconst CREATE_DEFAULT_PROJECT_MUTATION = `\n mutation CreateDefaultProject($input: CreateProjectInput!) {\n createProject(input: $input) {\n id\n name\n key\n workspaceId\n status\n archived\n createdAt\n updatedAt\n }\n }\n`;\n\nasync function createDefaultProject({\n authToken,\n workspaceBaseUrl,\n workspaceToken,\n}: {\n authToken: string;\n workspaceBaseUrl: string;\n workspaceToken: string;\n}): Promise<Project | null> {\n const result = await graphqlFetch<CreateProjectResponse>({\n gateway: \"workspace\",\n query: CREATE_DEFAULT_PROJECT_MUTATION,\n variables: {\n input: {\n name: \"Default Project\",\n },\n },\n authToken,\n workspaceToken,\n baseUrl: workspaceBaseUrl,\n });\n\n if (result.errors?.length) {\n console.warn(\"Failed to create default project:\", result.errors);\n return null;\n }\n\n return result.data?.createProject ?? null;\n}\n\n// =============================================================================\n// Auth Helpers\n// =============================================================================\n\n/**\n * Check whether a JWT is expired (or within bufferMs of expiry).\n * Returns true if the token is expired, close to expiry, or malformed.\n */\nfunction isTokenExpired(token: string, bufferMs = 30_000): boolean {\n try {\n const payload = JSON.parse(atob(token.split(\".\")[1]));\n if (!payload.exp) return false;\n return payload.exp * 1000 < Date.now() + bufferMs;\n } catch {\n return true;\n }\n}\n\nfunction getWorkspaceTokenPayload(token: string): {\n workspaceId?: string;\n organizationId?: string;\n exp?: number;\n} | null {\n try {\n const payload = JSON.parse(atob(token.split(\".\")[1]));\n return {\n workspaceId:\n typeof payload.workspaceId === \"string\"\n ? payload.workspaceId\n : undefined,\n organizationId:\n typeof payload.organizationId === \"string\"\n ? payload.organizationId\n : undefined,\n exp: typeof payload.exp === \"number\" ? payload.exp : undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction isWorkspaceTokenValidForContext(\n token: string | null | undefined,\n expected: { workspaceId?: string | null; organizationId?: string | null },\n): token is string {\n if (!token || isTokenExpired(token)) {\n return false;\n }\n\n const payload = getWorkspaceTokenPayload(token);\n if (!payload) {\n return false;\n }\n\n if (expected.workspaceId && payload.workspaceId !== expected.workspaceId) {\n return false;\n }\n\n if (\n expected.organizationId &&\n payload.organizationId !== expected.organizationId\n ) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Custom error class for auth-related failures (expired token, unauthorized, etc.).\n * Used to distinguish auth errors in outer catch blocks so they can be\n * suppressed from console.error — they are expected during token refresh cycles\n * and do not indicate application bugs.\n */\nclass AuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/**\n * Detect whether a set of GraphQL errors are authentication-related.\n */\nfunction isAuthGraphQLError(\n errors: Array<{ message?: string; extensions?: { code?: string } }>,\n): boolean {\n return errors.some(\n (e) =>\n e.extensions?.code === \"UNAUTHENTICATED\" ||\n e.message?.toLowerCase().includes(\"unauthorized\") ||\n e.message?.toLowerCase().includes(\"not authenticated\"),\n );\n}\n\n/**\n * Resolve the best available access token:\n * 1. Try the zustand store token\n * 2. If expired, fall back to profile storage (may have been refreshed)\n * 3. Return null if no valid token is available\n */\nfunction resolveAccessToken(): string | null {\n const storeToken = useAuthStore.getState().accessToken;\n\n // If store token is valid (or has no exp claim), use it\n if (storeToken && !isTokenExpired(storeToken)) {\n return storeToken;\n }\n\n // Store token is expired or missing — try profile storage (may be fresher)\n const profileToken = getStoredAuthToken();\n if (profileToken && !isTokenExpired(profileToken)) {\n return profileToken;\n }\n\n // Both expired or missing — if store token exists at all, return it as a last\n // resort (the gateway will reject it and the useEffect will re-trigger after\n // token refresh). Returning null would silently swallow the first load.\n return storeToken;\n}\n\nfunction buildFallbackOrganizations(workspaces: Workspace[]): Organization[] {\n const uniqueOrgIds = Array.from(\n new Set(\n workspaces.map((workspace) => workspace.organizationId).filter(Boolean),\n ),\n );\n\n return uniqueOrgIds.map((organizationId, index) => ({\n id: organizationId,\n name:\n workspaces.find(\n (workspace) => workspace.organizationId === organizationId,\n )?.name || `Organization ${index + 1}`,\n slug: organizationId,\n tenantId:\n workspaces.find(\n (workspace) => workspace.organizationId === organizationId,\n )?.tenantId || \"\",\n }));\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Hook for managing the context switcher data (organizations, workspaces, projects)\n *\n * Data flow:\n * 1. fetchOrganizations() - Get all orgs user has access to (Global Gateway)\n * 2. selectOrganization(org) - Set current org & fetch workspaces for that org\n * 3. selectWorkspace(ws) - Issue workspace token & fetch projects\n * 4. selectProject(proj) - Set current project\n *\n * All GraphQL calls go through graphqlFetch from fe-libs which automatically\n * resolves gateway URLs and injects auth + locale headers.\n *\n * @param options - Optional configuration (gateway base URL overrides)\n */\nexport function useContextSwitcherData(\n options?: UseContextSwitcherDataOptions,\n) {\n const {\n organizationId: activeOrganizationId,\n workspaceId: activeWorkspaceId,\n projectId: activeProjectId,\n setContext: setActiveContext,\n } = useActiveContext();\n\n // Use selectors for reactive state\n const organizations = useAuthStore((state) => state.organizations);\n const currentOrganizationId = useAuthStore(\n (state) => state.currentOrganizationId,\n );\n const isLoadingOrganizations = useAuthStore(\n (state) => state.isLoadingOrganizations,\n );\n\n const workspaces = useAuthStore((state) => state.workspaces);\n const currentWorkspaceId = useAuthStore((state) => state.currentWorkspaceId);\n const workspaceToken = useAuthStore((state) => state.workspaceToken);\n const isLoadingWorkspaces = useAuthStore(\n (state) => state.isLoadingWorkspaces,\n );\n\n const projects = useAuthStore((state) => state.projects);\n const currentProjectId = useAuthStore((state) => state.currentProjectId);\n const isLoadingProjects = useAuthStore((state) => state.isLoadingProjects);\n\n // Local error state\n const [error, setError] = useState<string | null>(null);\n\n // Deduplication refs to prevent duplicate GraphQL calls\n const fetchOrganizationsPromiseRef = useRef<Promise<Organization[]> | null>(\n null,\n );\n const fetchWorkspacesPromisesRef = useRef<Map<string, Promise<Workspace[]>>>(\n new Map(),\n );\n\n // Stable refs for latest context values — avoids stale closures in callbacks\n // without adding them to useCallback dep arrays (which would recreate callbacks\n // on every context change and trigger spurious fetch re-runs).\n const activeWorkspaceIdRef = useRef(activeWorkspaceId);\n const activeOrganizationIdRef = useRef(activeOrganizationId);\n useEffect(() => {\n activeWorkspaceIdRef.current = activeWorkspaceId;\n activeOrganizationIdRef.current = activeOrganizationId;\n });\n\n const resolvedBaseUrls = resolveGatewayBaseUrls();\n const globalBaseUrl =\n options?.globalBaseUrl ?? resolvedBaseUrls.globalBaseUrl;\n const workspaceBaseUrl =\n options?.workspaceBaseUrl ?? resolvedBaseUrls.workspaceBaseUrl;\n\n useEffect(() => {\n const store = useAuthStore.getState();\n\n if (\n activeOrganizationId &&\n activeOrganizationId !== store.currentOrganizationId\n ) {\n store.setCurrentOrganizationId(activeOrganizationId);\n if (\n store.workspaces.length > 0 &&\n !store.workspaces.some(\n (workspace) => workspace.organizationId === activeOrganizationId,\n )\n ) {\n store.setWorkspaces([]);\n }\n }\n\n if (activeWorkspaceId && activeWorkspaceId !== store.currentWorkspaceId) {\n store.setCurrentWorkspaceId(activeWorkspaceId);\n if (\n store.projects.length > 0 &&\n !store.projects.some(\n (project) => project.workspaceId === activeWorkspaceId,\n )\n ) {\n store.setProjects([]);\n store.setCurrentProjectId(null);\n }\n }\n\n if (activeProjectId && activeProjectId !== store.currentProjectId) {\n store.setCurrentProjectId(activeProjectId);\n }\n\n if (\n store.workspaceToken &&\n !isWorkspaceTokenValidForContext(store.workspaceToken, {\n workspaceId: activeWorkspaceId,\n organizationId: activeOrganizationId,\n })\n ) {\n store.setWorkspaceToken(null);\n }\n }, [activeOrganizationId, activeWorkspaceId, activeProjectId]);\n\n // ===========================================================================\n // Fetch Organizations (Global Gateway)\n // ===========================================================================\n\n const fetchOrganizations = useCallback(async (): Promise<Organization[]> => {\n // Deduplicate: if a fetch is already in progress, return the same promise\n if (fetchOrganizationsPromiseRef.current) {\n return fetchOrganizationsPromiseRef.current;\n }\n\n const store = useAuthStore.getState();\n const token = resolveAccessToken();\n\n if (!token) {\n // Not an error — user may not be authenticated yet (e.g., page load before login).\n // The useEffect in Header.tsx will re-trigger when accessToken becomes available.\n return [];\n }\n\n // If the token is clearly expired and no fresh fallback was found, skip the\n // doomed request. The useEffect in Header.tsx re-triggers when the auth\n // provider refreshes the token and updates accessToken in the store.\n if (isTokenExpired(token)) {\n return [];\n }\n\n store.setLoadingOrganizations(true);\n setError(null);\n\n // Store the promise for deduplication before starting\n fetchOrganizationsPromiseRef.current = (async () => {\n try {\n const initialTargetOrgId =\n activeOrganizationIdRef.current ?? store.currentOrganizationId;\n let result = await graphqlFetch<\n MyOrganizationsResponse & Partial<WorkspacesByOrgResponse>\n >({\n gateway: \"global\",\n query: initialTargetOrgId\n ? CONTEXT_SWITCHER_BOOTSTRAP_QUERY\n : MY_ORGANIZATIONS_QUERY,\n variables: initialTargetOrgId\n ? { filter: { organizationId: initialTargetOrgId } }\n : undefined,\n authToken: token,\n baseUrl: globalBaseUrl,\n });\n\n // Self-heal stale-URL case: bootstrap query embeds\n // workspaces(filter: {organizationId: <urlOrg>}) — when the user\n // isn't a member of that org (URL was bookmarked from a different\n // tenant, org was deleted, etc.), the workspaces resolver throws\n // FORBIDDEN which blanks the entire data block, masking\n // myOrganizations as the visible error. Retry with the simpler\n // MY_ORGANIZATIONS_QUERY so the operator sees their actual orgs\n // and the URL params get corrected on next render.\n if (\n initialTargetOrgId &&\n result.errors?.length &&\n result.errors.some(\n (e) =>\n e?.extensions?.code === \"FORBIDDEN\" ||\n /not a member of this organization/i.test(e?.message ?? \"\") ||\n // Public gateway often drops the underlying FORBIDDEN error\n // and replaces it with the schema-level non-null violation\n // (\"Cannot return null for non-nullable field Query.myOrganizations\").\n // That happens when ANY field in the query throws — workspaces\n // here — and data:null cascades up. Treat that pattern as a\n // signal to retry without the workspaces filter.\n /Cannot return null for non-nullable field Query\\.myOrganizations/i.test(\n e?.message ?? \"\",\n ),\n )\n ) {\n // Fetch myOrganizations + ALL workspaces (no filter) so the\n // downstream auto-pick logic still has a workspace list to seed\n // context from. If we only refetched myOrganizations, the page\n // would render but every workspace-scoped query would fail with\n // \"Select a workspace…\".\n result = await graphqlFetch<\n MyOrganizationsResponse & Partial<WorkspacesByOrgResponse>\n >({\n gateway: \"global\",\n query: `\n query ContextSwitcherRecover {\n myOrganizations {\n total\n items { id name slug tenantId description logo website status type createdAt updatedAt }\n }\n workspaces {\n total\n items { id name slug tenantId organizationId type status region createdAt updatedAt }\n }\n }\n `,\n authToken: token,\n baseUrl: globalBaseUrl,\n });\n }\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n if (isAuthGraphQLError(result.errors)) {\n // Auth errors are expected during token refresh cycles — throw AuthError\n // so the outer catch can suppress console.error.\n throw new AuthError(errorMessage);\n }\n if (store.workspaces.length === 0) {\n console.error(\"Failed to fetch organizations:\", result.errors);\n }\n throw new Error(errorMessage);\n }\n\n let orgs: Organization[] = result.data?.myOrganizations?.items ?? [];\n\n // Stale-context recovery: bootstrap query was filtered by\n // initialTargetOrgId, so when the URL/persisted org doesn't belong to\n // this user the response is empty. Re-fetch the unfiltered list of\n // *all* orgs the user can access so the guard below can pick a real\n // default. Skip the recovery when no target was set (already\n // unfiltered) or when workspaces are already in the store (the\n // existing fallback path covers that case).\n if (\n initialTargetOrgId &&\n orgs.length === 0 &&\n store.workspaces.length === 0\n ) {\n const recovery = await graphqlFetch<MyOrganizationsResponse>({\n gateway: \"global\",\n query: MY_ORGANIZATIONS_QUERY,\n authToken: token,\n baseUrl: globalBaseUrl,\n });\n if (!recovery.errors?.length) {\n orgs = recovery.data?.myOrganizations?.items ?? [];\n // discard the filtered workspaces payload — it was for the\n // ghost org and would only mislead the workspace selector below.\n result = {\n ...recovery,\n data: {\n myOrganizations: recovery.data?.myOrganizations ?? {\n items: [],\n total: 0,\n },\n },\n };\n } else {\n // Surface the failure so a user reporting \"blank org list\" has\n // something to grep for in the console. We still fall through —\n // the guard below either picks from a fallback (workspaces in\n // store) or no-ops, leaving the existing error path in place.\n console.warn(\n \"[ContextSwitcher] Stale-context recovery failed:\",\n recovery.errors,\n );\n }\n }\n\n const fallbackOrganizations =\n orgs.length === 0 && store.workspaces.length > 0\n ? buildFallbackOrganizations(store.workspaces)\n : [];\n const effectiveOrganizations =\n fallbackOrganizations.length > 0 ? fallbackOrganizations : orgs;\n\n store.setOrganizations(effectiveOrganizations);\n\n // Determine which organization to use for workspace fetching\n let targetOrgId = initialTargetOrgId;\n\n // Stale-context guard: if the persisted/URL org isn't in the user's\n // accessible orgs, fall back to the first available one and clear the\n // stale workspace/project so they get re-derived. Without this, URL\n // params like ?org=<ghost-id> from a prior session leak into the new\n // user's request headers and cause \"Authentication required\" /\n // \"not a member\" errors at every subgraph.\n //\n // Check against `orgs` (freshly returned from the API in this same\n // closure) rather than `effectiveOrganizations`, which can fall back\n // to ids derived from `store.workspaces` — that fallback path could\n // contain stale ghost orgIds and mask the guard.\n const targetOrgIsAccessible =\n targetOrgId && orgs.some((org) => org.id === targetOrgId);\n if (targetOrgId && !targetOrgIsAccessible && orgs.length > 0) {\n targetOrgId = orgs[0].id;\n setActiveContext({\n organizationId: targetOrgId,\n workspaceId: null,\n projectId: null,\n });\n store.setWorkspaces([]);\n store.setProjects([]);\n store.setCurrentWorkspaceId(null);\n store.setCurrentProjectId(null);\n store.setWorkspaceToken(null);\n }\n\n if (targetOrgId && targetOrgId !== store.currentOrganizationId) {\n store.setCurrentOrganizationId(targetOrgId);\n }\n\n // Auto-select first organization if none is selected\n if (effectiveOrganizations.length > 0 && !targetOrgId) {\n store.setCurrentOrganizationId(effectiveOrganizations[0].id);\n targetOrgId = effectiveOrganizations[0].id;\n }\n\n // Fetch workspaces for the selected/auto-selected org if:\n // 1. We have a target org (either auto-selected or persisted from localStorage)\n // 2. AND workspaces array is empty (not persisted, or cleared)\n // This handles both initial login AND page refresh scenarios.\n // Read from useAuthStore.getState() rather than the captured `store`\n // snapshot so we see the post-guard cleared value when the org guard\n // above fired (the local `store.workspaces` ref is stale after\n // setWorkspaces([])).\n if (targetOrgId && useAuthStore.getState().workspaces.length === 0) {\n store.setLoadingWorkspaces(true);\n try {\n const bootstrappedWorkspaces =\n initialTargetOrgId === targetOrgId\n ? result.data?.workspaces?.items\n : undefined;\n const ws = bootstrappedWorkspaces\n ? (bootstrappedWorkspaces as Workspace[])\n : await graphqlFetch<WorkspacesByOrgResponse>({\n gateway: \"global\",\n query: WORKSPACES_BY_ORG_QUERY,\n variables: { filter: { organizationId: targetOrgId } },\n authToken: token,\n baseUrl: globalBaseUrl,\n }).then((wsResult) =>\n wsResult.errors?.length\n ? null\n : (wsResult.data?.workspaces?.items ?? []),\n );\n\n if (ws) {\n store.setWorkspaces(ws);\n const persistedWorkspace = activeWorkspaceIdRef.current\n ? ws.find(\n (workspace) =>\n workspace.id === activeWorkspaceIdRef.current,\n )\n : null;\n\n if (persistedWorkspace) {\n store.setCurrentWorkspaceId(persistedWorkspace.id);\n } else if (activeWorkspaceIdRef.current && ws.length > 0) {\n // Stale-context guard: URL/persisted workspace ID is not in\n // the user's accessible workspaces for the active org. Fall\n // back to the first workspace and clear the stale URL param\n // so subsequent requests don't carry the ghost ID.\n store.setCurrentWorkspaceId(ws[0].id);\n store.setWorkspaceToken(null);\n setActiveContext({ workspaceId: ws[0].id, projectId: null });\n } else if (ws.length > 0 && !store.currentWorkspaceId) {\n // Auto-select first workspace only if none is currently selected\n // (preserves selection from completeAuthFlow or persistence if applicable)\n store.setCurrentWorkspaceId(ws[0].id);\n }\n }\n } catch {\n // Non-critical — user can still select workspace manually\n } finally {\n store.setLoadingWorkspaces(false);\n }\n }\n\n return effectiveOrganizations;\n } catch (err) {\n // Auth errors are expected during token refresh / page load cycles.\n // Suppress from console.error — the useEffect will re-trigger when the\n // auth provider refreshes the token.\n if (err instanceof AuthError) {\n return [];\n }\n const message =\n err instanceof Error ? err.message : \"Failed to fetch organizations\";\n if (store.workspaces.length === 0) {\n console.error(\"Failed to fetch organizations:\", err);\n }\n setError(message);\n\n if (store.workspaces.length > 0) {\n const fallbackOrganizations = buildFallbackOrganizations(\n store.workspaces,\n );\n if (fallbackOrganizations.length > 0) {\n store.setOrganizations(fallbackOrganizations);\n if (!store.currentOrganizationId) {\n store.setCurrentOrganizationId(fallbackOrganizations[0].id);\n }\n return fallbackOrganizations;\n }\n }\n\n return [];\n } finally {\n store.setLoadingOrganizations(false);\n fetchOrganizationsPromiseRef.current = null;\n }\n })();\n\n return fetchOrganizationsPromiseRef.current;\n }, [globalBaseUrl, setActiveContext]);\n\n // ===========================================================================\n // Fetch Workspaces for Organization (Global Gateway)\n // ===========================================================================\n\n const fetchWorkspacesForOrg = useCallback(\n async (organizationId: string): Promise<Workspace[]> => {\n // Deduplicate: if a fetch for this org is already in progress, return the same promise\n const existingPromise =\n fetchWorkspacesPromisesRef.current.get(organizationId);\n if (existingPromise) {\n return existingPromise;\n }\n\n const store = useAuthStore.getState();\n const token = resolveAccessToken();\n\n if (!token || isTokenExpired(token)) {\n return [];\n }\n\n store.setLoadingWorkspaces(true);\n setError(null);\n\n // Store the promise for deduplication before starting\n const fetchPromise = (async () => {\n try {\n const result = await graphqlFetch<WorkspacesByOrgResponse>({\n gateway: \"global\",\n query: WORKSPACES_BY_ORG_QUERY,\n variables: { filter: { organizationId } },\n authToken: token,\n baseUrl: globalBaseUrl,\n });\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n if (isAuthGraphQLError(result.errors)) {\n throw new AuthError(errorMessage);\n }\n console.error(\"Failed to fetch workspaces:\", result.errors);\n throw new Error(errorMessage);\n }\n\n const ws: Workspace[] = result.data?.workspaces?.items ?? [];\n store.setWorkspaces(ws);\n return ws;\n } catch (err) {\n if (err instanceof AuthError) {\n return [];\n }\n const message =\n err instanceof Error ? err.message : \"Failed to fetch workspaces\";\n console.error(\"Failed to fetch workspaces:\", err);\n setError(message);\n return [];\n } finally {\n store.setLoadingWorkspaces(false);\n fetchWorkspacesPromisesRef.current.delete(organizationId);\n }\n })();\n\n fetchWorkspacesPromisesRef.current.set(organizationId, fetchPromise);\n return fetchPromise;\n },\n [globalBaseUrl],\n );\n\n // ===========================================================================\n // Issue Workspace Token (Workspace Gateway - wspace-auth-svc)\n // ===========================================================================\n\n const issueWorkspaceToken = useCallback(\n async (\n organizationId: string,\n workspaceId?: string,\n ): Promise<{\n success: boolean;\n token?: string;\n resolvedWorkspaceId?: string;\n error?: string;\n }> => {\n const store = useAuthStore.getState();\n const authToken = resolveAccessToken();\n\n if (!authToken || isTokenExpired(authToken)) {\n return { success: false, error: \"No valid access token available\" };\n }\n\n setError(null);\n\n try {\n const result = await graphqlFetch<{\n issueWorkspaceToken: IssueWorkspaceTokenResult;\n }>({\n gateway: \"workspace\",\n query: ISSUE_WORKSPACE_TOKEN_MUTATION,\n variables: {\n input: {\n organizationId,\n ...(workspaceId && { workspaceId }),\n },\n },\n authToken,\n baseUrl: workspaceBaseUrl,\n });\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n if (!isAuthGraphQLError(result.errors)) {\n console.error(\"Failed to issue workspace token:\", result.errors);\n }\n return { success: false, error: errorMessage };\n }\n\n const tokenResult = result.data?.issueWorkspaceToken;\n\n if (tokenResult?.success && tokenResult.token) {\n const resolvedWsId = tokenResult.workspaceId || workspaceId;\n if (resolvedWsId) {\n store.setCurrentWorkspaceId(resolvedWsId);\n }\n store.setWorkspaceToken(tokenResult.token);\n return {\n success: true,\n token: tokenResult.token,\n resolvedWorkspaceId: resolvedWsId || undefined,\n };\n }\n\n return {\n success: false,\n error:\n tokenResult?.error?.message ?? \"Failed to issue workspace token\",\n };\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : \"Failed to issue workspace token\";\n console.error(\"Failed to issue workspace token:\", err);\n setError(message);\n return { success: false, error: message };\n }\n },\n [workspaceBaseUrl],\n );\n\n // ===========================================================================\n // Fetch Projects (Workspace Gateway - requires workspace token)\n // ===========================================================================\n\n const fetchProjects = useCallback(async (): Promise<Project[]> => {\n const store = useAuthStore.getState();\n const authToken = resolveAccessToken();\n const wsToken = store.workspaceToken;\n const workspaceId = store.currentWorkspaceId;\n\n if (!authToken || isTokenExpired(authToken)) {\n return [];\n }\n\n if (!wsToken) {\n return [];\n }\n\n if (!workspaceId) {\n return [];\n }\n\n store.setLoadingProjects(true);\n setError(null);\n\n try {\n const result = await graphqlFetch<ProjectsResponse>({\n gateway: \"workspace\",\n query: PROJECTS_QUERY,\n variables: { filter: { workspaceId } },\n authToken,\n workspaceToken: wsToken,\n baseUrl: workspaceBaseUrl,\n });\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n if (isAuthGraphQLError(result.errors)) {\n throw new AuthError(errorMessage);\n }\n console.error(\"Failed to fetch projects:\", result.errors);\n throw new Error(errorMessage);\n }\n\n const projs: Project[] = result.data?.projects?.items ?? [];\n store.setProjects(projs);\n return projs;\n } catch (err) {\n if (err instanceof AuthError) {\n return [];\n }\n const message =\n err instanceof Error ? err.message : \"Failed to fetch projects\";\n console.error(\"Failed to fetch projects:\", err);\n setError(message);\n return [];\n } finally {\n store.setLoadingProjects(false);\n }\n }, [workspaceBaseUrl]);\n\n // ===========================================================================\n // High-Level Selection Actions\n // ===========================================================================\n\n const selectOrganization = useCallback(\n async (org: Organization): Promise<Workspace[]> => {\n const store = useAuthStore.getState();\n\n store.setCurrentWorkspaceId(null);\n store.setWorkspaceToken(null);\n store.setProjects([]);\n store.setCurrentProjectId(null);\n store.setCurrentOrganizationId(org.id);\n\n const ws = await fetchWorkspacesForOrg(org.id);\n return ws;\n },\n [fetchWorkspacesForOrg],\n );\n\n const selectWorkspace = useCallback(\n async (\n workspace: Workspace,\n ): Promise<{\n success: boolean;\n projects?: Project[];\n error?: string;\n }> => {\n const store = useAuthStore.getState();\n\n store.setCurrentProjectId(null);\n store.setProjects([]);\n\n if (!workspace.organizationId) {\n console.error(\"Workspace missing organizationId:\", workspace);\n return {\n success: false,\n error: \"Workspace is missing organizationId\",\n };\n }\n\n const tokenResult = await issueWorkspaceToken(\n workspace.organizationId,\n workspace.id,\n );\n\n if (!tokenResult.success) {\n return { success: false, error: tokenResult.error };\n }\n\n let projs = await fetchProjects();\n if (projs.length === 0) {\n const authToken = resolveAccessToken();\n const workspaceToken = useAuthStore.getState().workspaceToken;\n if (authToken && workspaceToken) {\n const defaultProject = await createDefaultProject({\n authToken,\n workspaceBaseUrl,\n workspaceToken,\n });\n if (defaultProject) {\n projs = [defaultProject];\n store.setProjects(projs);\n }\n }\n }\n\n if (projs.length > 0) {\n store.setCurrentProjectId(projs[0]!.id);\n }\n\n return { success: true, projects: projs };\n },\n [issueWorkspaceToken, fetchProjects, workspaceBaseUrl],\n );\n\n const selectProject = useCallback((project: Project): void => {\n const store = useAuthStore.getState();\n store.setCurrentProjectId(project.id);\n }, []);\n\n // ===========================================================================\n // Get Current Items\n // ===========================================================================\n\n const currentOrganization = organizations.find(\n (org) => org.id === currentOrganizationId,\n );\n const currentWorkspace = workspaces.find(\n (ws) => ws.id === currentWorkspaceId,\n );\n const currentProject = projects.find((proj) => proj.id === currentProjectId);\n\n // ===========================================================================\n // Return Hook API\n // ===========================================================================\n\n return {\n organizations,\n workspaces,\n projects,\n\n currentOrganizationId,\n currentWorkspaceId,\n currentProjectId,\n\n currentOrganization,\n currentWorkspace,\n currentProject,\n\n workspaceToken,\n\n isLoadingOrganizations,\n isLoadingWorkspaces,\n isLoadingProjects,\n isLoading:\n isLoadingOrganizations || isLoadingWorkspaces || isLoadingProjects,\n\n error,\n\n fetchOrganizations,\n fetchWorkspacesForOrg,\n issueWorkspaceToken,\n fetchProjects,\n\n selectOrganization,\n selectWorkspace,\n selectProject,\n };\n}\n\n/**\n * Hook to reactively ensure workspaces are synced with the current organization.\n *\n * This handles edge cases where the organization changes but workspaces\n * from a different org are still in the store (e.g., stale data, race conditions).\n *\n * Usage:\n * ```tsx\n * import { useWorkspaceSyncEffect } from '@burdenoff/microfe-auth';\n *\n * function MyComponent() {\n * useWorkspaceSyncEffect(); // Ensures workspaces stay in sync\n * // ...\n * }\n * ```\n */\nexport function useWorkspaceSyncEffect(\n options?: UseContextSwitcherDataOptions,\n) {\n const currentOrganizationId = useAuthStore(\n (state) => state.currentOrganizationId,\n );\n const workspaces = useAuthStore((state) => state.workspaces);\n const accessToken = useAuthStore((state) => state.accessToken);\n const isLoadingWorkspaces = useAuthStore(\n (state) => state.isLoadingWorkspaces,\n );\n const resolvedBaseUrls = resolveGatewayBaseUrls();\n const globalBaseUrl =\n options?.globalBaseUrl ?? resolvedBaseUrls.globalBaseUrl;\n const disableWorkspaceSync = options?.disableWorkspaceSync ?? false;\n\n useEffect(() => {\n if (disableWorkspaceSync) return;\n // Skip if no org selected, no token, or already loading\n if (!currentOrganizationId || !accessToken || isLoadingWorkspaces) return;\n\n // Check if any workspace matches the current org\n const hasMatchingWorkspaces = workspaces.some(\n (ws) => ws.organizationId === currentOrganizationId,\n );\n\n // If workspaces exist but none match current org, we need to refetch\n // This can happen in edge cases with stale data or race conditions\n if (workspaces.length > 0 && !hasMatchingWorkspaces) {\n const store = useAuthStore.getState();\n store.setLoadingWorkspaces(true);\n\n // Inline fetch to avoid circular dependency with useContextSwitcherData\n graphqlFetch<WorkspacesByOrgResponse>({\n gateway: \"global\",\n query: WORKSPACES_BY_ORG_QUERY,\n variables: { filter: { organizationId: currentOrganizationId } },\n authToken: accessToken,\n baseUrl: globalBaseUrl,\n })\n .then((result) => {\n if (!result.errors?.length) {\n const ws: Workspace[] = result.data?.workspaces?.items ?? [];\n store.setWorkspaces(ws);\n }\n })\n .catch(() => {\n // Silent fail - user can manually refresh or select org again\n })\n .finally(() => {\n store.setLoadingWorkspaces(false);\n });\n }\n }, [\n currentOrganizationId,\n workspaces,\n accessToken,\n isLoadingWorkspaces,\n globalBaseUrl,\n disableWorkspaceSync,\n ]);\n}\n\n/**\n * Hook to reactively ensure projects are loaded when a workspace is selected.\n *\n * This handles the case where a workspace is auto-selected (from URL/localStorage)\n * but projects haven't been fetched yet. It will:\n * 1. Issue a workspace token if not present\n * 2. Fetch projects for the selected workspace\n *\n * Usage:\n * ```tsx\n * import { useProjectSyncEffect } from '@burdenoff/microfe-auth';\n *\n * function MyComponent() {\n * useProjectSyncEffect(); // Ensures projects are loaded for selected workspace\n * // ...\n * }\n * ```\n */\nexport function useProjectSyncEffect(options?: UseContextSwitcherDataOptions) {\n const currentWorkspaceId = useAuthStore((state) => state.currentWorkspaceId);\n const currentOrganizationId = useAuthStore(\n (state) => state.currentOrganizationId,\n );\n const workspaces = useAuthStore((state) => state.workspaces);\n const projects = useAuthStore((state) => state.projects);\n const workspaceToken = useAuthStore((state) => state.workspaceToken);\n const accessToken = useAuthStore((state) => state.accessToken);\n const resolvedBaseUrls = resolveGatewayBaseUrls();\n const workspaceBaseUrl =\n options?.workspaceBaseUrl ?? resolvedBaseUrls.workspaceBaseUrl;\n const disableProjectSync = options?.disableProjectSync ?? false;\n const skipProjectFetch = options?.skipProjectFetch ?? false;\n\n // Use refs to prevent the infinite loop caused by including loading/failure\n // state in the dependency array. Without these, the cycle is:\n // setLoadingProjects(true) -> dep change -> effect re-runs (guarded) ->\n // async completes -> setLoadingProjects(false) -> dep change ->\n // effect re-runs -> starts again -> INFINITE LOOP\n const syncInProgressRef = useRef(false);\n // Pending retry timer per workspace, so transient failures (e.g. RBAC lag\n // right after workspace creation) get an automatic second chance even if no\n // dependency change re-triggers the effect.\n const retryTimerRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(\n new Map(),\n );\n // Per-workspace failure tracker — caps retry attempts when project bootstrap\n // (token issue, list, or default-create) fails. Without this, a persistent\n // backend failure (e.g. cross-layer workspace not yet synced) causes the\n // effect to re-fire every render: list returns empty → create-default fails\n // → setProjects([]) → new array reference → effect re-runs → loop.\n //\n // We track both count AND lastFailureAt so we can honour a \"cool-down\" window:\n // after PROJECT_SYNC_FAILURE_COOLDOWN_MS has elapsed since the last failure,\n // the counter is treated as cleared so transient backend hiccups (e.g. RBAC\n // role propagation lag right after signup) don't permanently lock a workspace\n // out of the context dropdown — the original cause of marqueue §729.\n const projectSyncFailuresRef = useRef<\n Map<string, { count: number; lastFailureAt: number }>\n >(new Map());\n const PROJECT_SYNC_MAX_FAILURES = 8;\n const PROJECT_SYNC_FAILURE_COOLDOWN_MS = 30_000;\n useEffect(() => {\n if (disableProjectSync) return;\n // Skip if no workspace selected or no access token\n if (!currentWorkspaceId || !accessToken) return;\n\n // Skip if a sync is already in progress (ref-based guard avoids dep loop)\n if (syncInProgressRef.current) return;\n\n // Stop retrying once this workspace has failed too many times in a row.\n // Counter is reset on success, on workspace switch (different key), by\n // an explicit user retry path (e.g. selectWorkspace), or after the\n // cool-down window has elapsed since the last failure (so transient\n // backend issues don't permanently wedge the dropdown).\n const failureEntry = projectSyncFailuresRef.current.get(currentWorkspaceId);\n if (\n failureEntry &&\n failureEntry.count >= PROJECT_SYNC_MAX_FAILURES &&\n Date.now() - failureEntry.lastFailureAt < PROJECT_SYNC_FAILURE_COOLDOWN_MS\n ) {\n return;\n }\n if (\n failureEntry &&\n Date.now() - failureEntry.lastFailureAt >=\n PROJECT_SYNC_FAILURE_COOLDOWN_MS\n ) {\n // Cool-down elapsed — clear the counter so we get a fresh budget.\n projectSyncFailuresRef.current.delete(currentWorkspaceId);\n }\n\n // Resolve organizationId: prefer the workspace object (if loaded), fall\n // back to the persisted currentOrganizationId. The workspaces array is\n // NOT persisted by zustand, so on page reload it is empty until\n // fetchOrganizations() completes. Using the persisted org ID lets us\n // issue the workspace token immediately instead of waiting.\n const currentWorkspace = workspaces.find(\n (ws) => ws.id === currentWorkspaceId,\n );\n\n // Guard: transient (newOrg, oldWs) divergence during org switches — token issuance always fails.\n if (\n currentWorkspace &&\n currentOrganizationId &&\n currentWorkspace.organizationId !== currentOrganizationId\n ) {\n return;\n }\n\n const organizationId =\n currentWorkspace?.organizationId ?? currentOrganizationId;\n if (!organizationId) return;\n\n const store = useAuthStore.getState();\n\n // If we don't have a workspace token or it's expired, issue one first\n const needsToken =\n !workspaceToken ||\n isTokenExpired(workspaceToken) ||\n !isWorkspaceTokenValidForContext(workspaceToken, {\n workspaceId: currentWorkspaceId,\n organizationId: currentOrganizationId,\n });\n\n // Skip if projects are already loaded for this workspace AND token is valid\n const hasProjectsForWorkspace = projects.some(\n (p) => p.workspaceId === currentWorkspaceId,\n );\n if (hasProjectsForWorkspace && !needsToken) {\n if (!store.currentProjectId) {\n const firstProject = projects.find(\n (project) => project.workspaceId === currentWorkspaceId,\n );\n if (firstProject) {\n store.setCurrentProjectId(firstProject.id);\n }\n }\n return;\n }\n\n const syncProjects = async () => {\n syncInProgressRef.current = true;\n store.setLoadingProjects(true);\n let succeeded = false;\n\n try {\n let wsToken = workspaceToken;\n\n // Issue workspace token if needed\n if (needsToken) {\n const tokenResult = await graphqlFetch<{\n issueWorkspaceToken: IssueWorkspaceTokenResult;\n }>({\n gateway: \"workspace\",\n query: ISSUE_WORKSPACE_TOKEN_MUTATION,\n variables: {\n input: {\n organizationId,\n workspaceId: currentWorkspaceId,\n },\n },\n authToken: accessToken,\n baseUrl: workspaceBaseUrl,\n });\n\n if (\n tokenResult.data?.issueWorkspaceToken?.success &&\n tokenResult.data.issueWorkspaceToken.token\n ) {\n wsToken = tokenResult.data.issueWorkspaceToken.token;\n store.setWorkspaceToken(wsToken);\n } else {\n return;\n }\n }\n\n // Fetch projects (skip if already loaded or token-only sync requested)\n if (wsToken && !hasProjectsForWorkspace && !skipProjectFetch) {\n const projectsResult = await graphqlFetch<ProjectsResponse>({\n gateway: \"workspace\",\n query: PROJECTS_QUERY,\n variables: { filter: { workspaceId: currentWorkspaceId } },\n authToken: accessToken,\n workspaceToken: wsToken,\n baseUrl: workspaceBaseUrl,\n });\n\n if (projectsResult.errors?.length) {\n return;\n }\n\n let projs: Project[] = projectsResult.data?.projects?.items ?? [];\n if (projs.length === 0) {\n const defaultProject = await createDefaultProject({\n authToken: accessToken,\n workspaceBaseUrl,\n workspaceToken: wsToken,\n });\n if (defaultProject) {\n projs = [defaultProject];\n } else {\n // Default-project creation failed (e.g. workspace not yet\n // propagated to the workspace layer). Do NOT write [] back —\n // that would change the projects reference and re-trigger\n // this effect on the next render.\n return;\n }\n }\n\n store.setProjects(projs);\n\n // Auto-select first project if none selected and projects exist\n if (projs.length > 0 && !store.currentProjectId) {\n store.setCurrentProjectId(projs[0].id);\n }\n }\n\n succeeded = true;\n } catch {\n // A later auth/context update should be able to retry.\n } finally {\n store.setLoadingProjects(false);\n syncInProgressRef.current = false;\n const failures = projectSyncFailuresRef.current;\n if (succeeded) {\n failures.delete(currentWorkspaceId);\n const pending = retryTimerRef.current.get(currentWorkspaceId);\n if (pending) {\n clearTimeout(pending);\n retryTimerRef.current.delete(currentWorkspaceId);\n }\n } else {\n const existing = failures.get(currentWorkspaceId);\n const nextCount = (existing?.count ?? 0) + 1;\n failures.set(currentWorkspaceId, {\n count: nextCount,\n lastFailureAt: Date.now(),\n });\n // Schedule a backoff retry for transient backend lag (e.g. RBAC\n // role propagation right after signup → first projects() call hits\n // permission-denied). Without this, the effect would only re-run on\n // dep change and the user would be stuck staring at an empty\n // project dropdown until something else triggered a re-render.\n if (nextCount < PROJECT_SYNC_MAX_FAILURES) {\n const existingTimer = retryTimerRef.current.get(currentWorkspaceId);\n if (existingTimer) clearTimeout(existingTimer);\n const backoffMs = Math.min(1000 * 2 ** (nextCount - 1), 8000);\n const timer = setTimeout(() => {\n retryTimerRef.current.delete(currentWorkspaceId);\n // Only re-run if the workspace context is still the same and\n // a project hasn't been loaded for it in the meantime.\n const latest = useAuthStore.getState();\n if (\n latest.currentWorkspaceId === currentWorkspaceId &&\n !latest.projects.some(\n (p) => p.workspaceId === currentWorkspaceId,\n ) &&\n !syncInProgressRef.current\n ) {\n // Bump a render by clearing then resetting workspaceToken\n // when valid, OR by re-issuing projects fetch directly. The\n // simplest robust trigger is to clear the in-progress guard\n // and call syncProjects() again with current closure values.\n void syncProjects();\n }\n }, backoffMs);\n retryTimerRef.current.set(currentWorkspaceId, timer);\n }\n }\n }\n };\n\n syncProjects();\n }, [\n currentWorkspaceId,\n currentOrganizationId,\n workspaces,\n projects,\n workspaceToken,\n accessToken,\n workspaceBaseUrl,\n disableProjectSync,\n skipProjectFetch,\n ]);\n\n // Cleanup any pending retry timers on unmount so we don't leak stray\n // setTimeout callbacks running against stale closures.\n useEffect(() => {\n const timers = retryTimerRef.current;\n return () => {\n timers.forEach((timer) => clearTimeout(timer));\n timers.clear();\n };\n }, []);\n}\n// hmr-bust-1778064429\n"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AppUserDelegation, GrantDelegationInput } from '../types';
|
|
2
|
+
|
|
3
|
+
interface CurrentUserDelegationsResponse {
|
|
4
|
+
currentUserDelegations: AppUserDelegation[];
|
|
5
|
+
}
|
|
6
|
+
interface CurrentUserGrantedDelegationsResponse {
|
|
7
|
+
currentUserGrantedDelegations: AppUserDelegation[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook for app-user delegation operations
|
|
11
|
+
*/
|
|
12
|
+
export declare function useDelegationOperations(): {
|
|
13
|
+
grantDelegation: (input: GrantDelegationInput) => Promise<AppUserDelegation>;
|
|
14
|
+
revokeDelegation: (id: string, reason?: string) => Promise<boolean>;
|
|
15
|
+
getDelegationsForApp: (appId: string) => AppUserDelegation[];
|
|
16
|
+
hasWorkspaceDelegation: (appId: string, workspaceId: string) => boolean;
|
|
17
|
+
refetchDelegations: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<import("@apollo/client").ApolloClient.QueryResult<CurrentUserDelegationsResponse>>;
|
|
18
|
+
refetchGrantedDelegations: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<import("@apollo/client").ApolloClient.QueryResult<CurrentUserGrantedDelegationsResponse>>;
|
|
19
|
+
delegations: AppUserDelegation[];
|
|
20
|
+
grantedDelegations: AppUserDelegation[];
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
error: string | null;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=useDelegationOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDelegationOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useDelegationOperations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAYxE,UAAU,8BAA8B;IACtC,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;CAC7C;AAED,UAAU,qCAAqC;IAC7C,6BAA6B,EAAE,iBAAiB,EAAE,CAAC;CACpD;AAuBD;;GAEG;AACH,wBAAgB,uBAAuB;6BAsF5B,oBAAoB,KAC1B,OAAO,CAAC,iBAAiB,CAAC;2BA0BvB,MAAM,WACD,MAAM,KACd,OAAO,CAAC,OAAO,CAAC;kCAsBkB,MAAM,KAAG,iBAAiB,EAAE;oCAUxD,MAAM,eACA,MAAM,KAClB,OAAO;;;;;;;EAgCX"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MFAMethod, MFASetupResult, MFAVerifyInput, AuthResult } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook for MFA operations
|
|
5
|
+
*/
|
|
6
|
+
export declare function useMfaOperations(): {
|
|
7
|
+
setupMFA: (method: MFAMethod) => Promise<MFASetupResult>;
|
|
8
|
+
enableMFA: (code: string) => Promise<boolean>;
|
|
9
|
+
verifyMFA: (input: MFAVerifyInput) => Promise<AuthResult>;
|
|
10
|
+
disableMFA: () => Promise<boolean>;
|
|
11
|
+
enableMfa: (code: string) => Promise<boolean>;
|
|
12
|
+
verifyMfa: (input: MFAVerifyInput) => Promise<AuthResult>;
|
|
13
|
+
disableMfa: () => Promise<boolean>;
|
|
14
|
+
mfaRequired: boolean;
|
|
15
|
+
mfaChallengeId: string | null;
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=useMfaOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMfaOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useMfaOperations.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,cAAc,EACd,UAAU,EAEX,MAAM,UAAU,CAAC;AA2DlB;;GAEG;AACH,wBAAgB,gBAAgB;uBAqBE,SAAS,KAAG,OAAO,CAAC,cAAc,CAAC;sBAsBpC,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;uBA0BxB,cAAc,KAAG,OAAO,CAAC,UAAU,CAAC;sBAgEvC,OAAO,CAAC,OAAO,CAAC;sBA1Fd,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;uBA0BxB,cAAc,KAAG,OAAO,CAAC,UAAU,CAAC;sBAgEvC,OAAO,CAAC,OAAO,CAAC;;;;EAwC9C"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useAuth as e } from "../providers/AuthProvider.js";
|
|
2
|
+
import { useAuthStore as t } from "../store/authStore.js";
|
|
3
|
+
import { DisableMfaDocument as n, EnableMfaDocument as r, SetupMfaDocument as i, VerifyMfaDocument as a } from "../../generated/global-operations.js";
|
|
4
|
+
import { loginProfile as o } from "@burdenoff/fe-libs/shared/providers/shell/ProfileStorageManager";
|
|
5
|
+
import { useMutation as s } from "@apollo/client/react";
|
|
6
|
+
import { useEventBus as c } from "@burdenoff/fe-libs/shared/events";
|
|
7
|
+
//#region src/auth/hooks/useMfaOperations.ts
|
|
8
|
+
function l(e) {
|
|
9
|
+
return { ...e };
|
|
10
|
+
}
|
|
11
|
+
function u(e) {
|
|
12
|
+
try {
|
|
13
|
+
let t = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, n = t ? `; domain=${t}` : "", r = window.location.protocol === "https:" ? "; secure" : "", i = JSON.stringify({
|
|
14
|
+
id: e,
|
|
15
|
+
origin: window.location.origin
|
|
16
|
+
});
|
|
17
|
+
document.cookie = `bf-sso=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`, document.cookie = `bf-sso-profile=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`;
|
|
18
|
+
} catch {}
|
|
19
|
+
}
|
|
20
|
+
function d() {
|
|
21
|
+
let d = t(), f = e(), p = c(), [m] = s(i), [h] = s(r), [g] = s(a), [_] = s(n), v = async (e) => {
|
|
22
|
+
try {
|
|
23
|
+
d.setLoading(!0);
|
|
24
|
+
let { data: t } = await m({ variables: { method: e } });
|
|
25
|
+
return t.setupMFA;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
throw e;
|
|
28
|
+
} finally {
|
|
29
|
+
d.setLoading(!1);
|
|
30
|
+
}
|
|
31
|
+
}, y = async (e) => {
|
|
32
|
+
try {
|
|
33
|
+
d.setLoading(!0);
|
|
34
|
+
let { data: t } = await h({ variables: { code: e } });
|
|
35
|
+
return t.enableMFA && d.user && d.setUser({
|
|
36
|
+
...d.user,
|
|
37
|
+
mfaEnabled: !0
|
|
38
|
+
}), t.enableMFA;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw e;
|
|
41
|
+
} finally {
|
|
42
|
+
d.setLoading(!1);
|
|
43
|
+
}
|
|
44
|
+
}, b = async (e) => {
|
|
45
|
+
try {
|
|
46
|
+
d.setLoading(!0);
|
|
47
|
+
let { data: t } = await g({ variables: { input: e } }), n = t.verifyMFA;
|
|
48
|
+
if (n.success && n.user && n.token) {
|
|
49
|
+
d.setUser(n.user), d.setAuthTokens(n.token, n.refreshToken || ""), d.setAuthenticated(!0), d.setMfaRequired(!1);
|
|
50
|
+
let e = n.expiresIn ? Date.now() + n.expiresIn * 1e3 : void 0;
|
|
51
|
+
o(l(n.user), {
|
|
52
|
+
accessToken: n.token,
|
|
53
|
+
refreshToken: n.refreshToken || "",
|
|
54
|
+
expiresAt: e
|
|
55
|
+
}), u(n.user.id), p.emit("auth.signed_in", {
|
|
56
|
+
userId: n.user.id,
|
|
57
|
+
tenantId: n.user.tenantId,
|
|
58
|
+
workspaceId: n.user.defaultWorkspaceId,
|
|
59
|
+
mfaEnabled: n.user.mfaEnabled,
|
|
60
|
+
emailVerified: n.user.emailVerified
|
|
61
|
+
}, { component: "useMfaOperations" }), f.onAuthSuccess?.(n.user, n.token, n.refreshToken);
|
|
62
|
+
} else console.warn("[useMfaOperations] NOT saving tokens - condition failed:", {
|
|
63
|
+
success: n.success,
|
|
64
|
+
hasUser: !!n.user,
|
|
65
|
+
hasToken: !!n.token
|
|
66
|
+
});
|
|
67
|
+
return n;
|
|
68
|
+
} catch (e) {
|
|
69
|
+
throw e;
|
|
70
|
+
} finally {
|
|
71
|
+
d.setLoading(!1);
|
|
72
|
+
}
|
|
73
|
+
}, x = async () => {
|
|
74
|
+
try {
|
|
75
|
+
d.setLoading(!0);
|
|
76
|
+
let { data: e } = await _();
|
|
77
|
+
return e.disableMFA && d.user && d.setUser({
|
|
78
|
+
...d.user,
|
|
79
|
+
mfaEnabled: !1
|
|
80
|
+
}), e.disableMFA;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
throw e;
|
|
83
|
+
} finally {
|
|
84
|
+
d.setLoading(!1);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
setupMFA: v,
|
|
89
|
+
enableMFA: y,
|
|
90
|
+
verifyMFA: b,
|
|
91
|
+
disableMFA: x,
|
|
92
|
+
enableMfa: y,
|
|
93
|
+
verifyMfa: b,
|
|
94
|
+
disableMfa: x,
|
|
95
|
+
mfaRequired: d.mfaRequired,
|
|
96
|
+
mfaChallengeId: d.mfaChallengeId,
|
|
97
|
+
isLoading: d.isLoading
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { d as useMfaOperations };
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=useMfaOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMfaOperations.js","names":[],"sources":["../../../src/auth/hooks/useMfaOperations.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\nimport { useEventBus } from \"@burdenoff/fe-libs/shared/events\";\nimport {\n loginProfile,\n type ProfileUser,\n} from \"@burdenoff/fe-libs/shared/providers/shell/ProfileStorageManager\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { useAuth } from \"../providers/AuthProvider\";\nimport {\n SetupMfaDocument,\n EnableMfaDocument,\n VerifyMfaDocument,\n DisableMfaDocument,\n} from \"../../generated/global-operations\";\nimport type {\n MFAMethod,\n MFASetupResult,\n MFAVerifyInput,\n AuthResult,\n User,\n} from \"../types\";\n\nfunction toProfileUser(user: User): ProfileUser {\n return { ...user };\n}\n\nfunction setShellSsoCookie(userId: string): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n const domainPart = domain ? `; domain=${domain}` : \"\";\n const securePart = window.location.protocol === \"https:\" ? \"; secure\" : \"\";\n const ssoValue = JSON.stringify({\n id: userId,\n origin: window.location.origin,\n });\n document.cookie = `bf-sso=${encodeURIComponent(ssoValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n document.cookie = `bf-sso-profile=${encodeURIComponent(ssoValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n } catch {\n // Best effort only.\n }\n}\n\n// =============================================================================\n// GRAPHQL RESPONSE INTERFACES\n// =============================================================================\n\ninterface SetupMFAResponse {\n setupMFA: MFASetupResult;\n}\n\ninterface SetupMFAVariables {\n method: MFAMethod;\n}\n\ninterface EnableMFAResponse {\n enableMFA: boolean;\n}\n\ninterface EnableMFAVariables {\n code: string;\n}\n\ninterface VerifyMFAResponse {\n verifyMFA: AuthResult;\n}\n\ninterface VerifyMFAVariables {\n input: MFAVerifyInput;\n}\n\ninterface DisableMFAResponse {\n disableMFA: boolean;\n}\n\n// GraphQL Operations\n\n/**\n * Hook for MFA operations\n */\nexport function useMfaOperations() {\n const store = useAuthStore();\n const context = useAuth();\n const eventBus = useEventBus();\n const [setupMfaMutation] = useMutation<SetupMFAResponse, SetupMFAVariables>(\n SetupMfaDocument,\n );\n const [enableMfaMutation] = useMutation<\n EnableMFAResponse,\n EnableMFAVariables\n >(EnableMfaDocument);\n const [verifyMfaMutation] = useMutation<\n VerifyMFAResponse,\n VerifyMFAVariables\n >(VerifyMfaDocument);\n const [disableMfaMutation] =\n useMutation<DisableMFAResponse>(DisableMfaDocument);\n\n /**\n * Setup MFA for the user\n */\n const setupMFA = async (method: MFAMethod): Promise<MFASetupResult> => {\n try {\n store.setLoading(true);\n\n const { data } = await setupMfaMutation({\n variables: { method },\n });\n\n return data!.setupMFA;\n } catch (error) {\n if (import.meta.env.DEV) {\n console.error(\"MFA setup failed:\", error);\n }\n throw error;\n } finally {\n store.setLoading(false);\n }\n };\n\n /**\n * Enable MFA after setup with verification code\n */\n const enableMFA = async (code: string): Promise<boolean> => {\n try {\n store.setLoading(true);\n\n const { data } = await enableMfaMutation({\n variables: { code },\n });\n\n if (data!.enableMFA && store.user) {\n store.setUser({ ...store.user, mfaEnabled: true });\n }\n\n return data!.enableMFA;\n } catch (error) {\n if (import.meta.env.DEV) {\n console.error(\"Failed to enable MFA:\", error);\n }\n throw error;\n } finally {\n store.setLoading(false);\n }\n };\n\n /**\n * Verify MFA code during login\n */\n const verifyMFA = async (input: MFAVerifyInput): Promise<AuthResult> => {\n try {\n store.setLoading(true);\n\n const { data } = await verifyMfaMutation({\n variables: { input },\n });\n\n const result = data!.verifyMFA;\n\n if (result.success && result.user && result.token) {\n store.setUser(result.user);\n store.setAuthTokens(result.token, result.refreshToken || \"\");\n store.setAuthenticated(true);\n store.setMfaRequired(false);\n\n const expiresAt = result.expiresIn\n ? Date.now() + result.expiresIn * 1000\n : undefined;\n loginProfile(toProfileUser(result.user), {\n accessToken: result.token,\n refreshToken: result.refreshToken || \"\",\n expiresAt,\n });\n setShellSsoCookie(result.user.id);\n\n eventBus.emit(\n \"auth.signed_in\",\n {\n userId: result.user.id,\n tenantId: result.user.tenantId,\n workspaceId: result.user.defaultWorkspaceId,\n mfaEnabled: result.user.mfaEnabled,\n emailVerified: result.user.emailVerified,\n },\n { component: \"useMfaOperations\" },\n );\n\n context.onAuthSuccess?.(result.user, result.token, result.refreshToken);\n } else {\n console.warn(\n \"[useMfaOperations] NOT saving tokens - condition failed:\",\n {\n success: result.success,\n hasUser: !!result.user,\n hasToken: !!result.token,\n },\n );\n }\n\n return result;\n } catch (error) {\n if (import.meta.env.DEV) {\n console.error(\"MFA verification failed:\", error);\n }\n throw error;\n } finally {\n store.setLoading(false);\n }\n };\n\n /**\n * Disable MFA\n */\n const disableMFA = async (): Promise<boolean> => {\n try {\n store.setLoading(true);\n\n const { data } = await disableMfaMutation();\n\n if (data!.disableMFA && store.user) {\n store.setUser({ ...store.user, mfaEnabled: false });\n }\n\n return data!.disableMFA;\n } catch (error) {\n if (import.meta.env.DEV) {\n console.error(\"Failed to disable MFA:\", error);\n }\n throw error;\n } finally {\n store.setLoading(false);\n }\n };\n\n // Legacy aliases\n const enableMfa = enableMFA;\n const verifyMfa = verifyMFA;\n const disableMfa = disableMFA;\n\n return {\n setupMFA,\n enableMFA,\n verifyMFA,\n disableMFA,\n // Legacy aliases\n enableMfa,\n verifyMfa,\n disableMfa,\n // State\n mfaRequired: store.mfaRequired,\n mfaChallengeId: store.mfaChallengeId,\n isLoading: store.isLoading,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Workspace } from '../types';
|
|
2
|
+
|
|
3
|
+
interface MyWorkspacesResponse {
|
|
4
|
+
myWorkspaces: {
|
|
5
|
+
total: number;
|
|
6
|
+
items: Workspace[];
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook for fetching user's workspaces and issuing workspace tokens
|
|
11
|
+
*
|
|
12
|
+
* This hook provides:
|
|
13
|
+
* - Fetch workspaces: Query to get all workspaces the user has access to
|
|
14
|
+
* - Issue workspace token: Get a workspace-scoped token for API access
|
|
15
|
+
* - Complete auth flow: Fetch workspaces + auto-select + issue token
|
|
16
|
+
*
|
|
17
|
+
* Uses the shell's Apollo client (via GatewayRoute) for useQuery, and
|
|
18
|
+
* graphqlFetch from fe-libs for imperative calls that need explicit tokens.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useMyWorkspaces(): {
|
|
21
|
+
workspaces: Workspace[];
|
|
22
|
+
totalWorkspaces: number;
|
|
23
|
+
currentWorkspaceId: string | null;
|
|
24
|
+
workspaceToken: string | null;
|
|
25
|
+
isLoading: boolean;
|
|
26
|
+
error: string | null;
|
|
27
|
+
fetchWorkspaces: (accessToken?: string) => Promise<Workspace[]>;
|
|
28
|
+
issueWorkspaceToken: (workspaceId: string, organizationId: string, accessToken?: string) => Promise<{
|
|
29
|
+
success: boolean;
|
|
30
|
+
token?: string;
|
|
31
|
+
error?: string;
|
|
32
|
+
}>;
|
|
33
|
+
selectWorkspace: (workspace: Workspace) => Promise<{
|
|
34
|
+
success: boolean;
|
|
35
|
+
error?: string;
|
|
36
|
+
}>;
|
|
37
|
+
completeAuthFlow: (accessToken?: string) => Promise<{
|
|
38
|
+
success: boolean;
|
|
39
|
+
workspace?: Workspace;
|
|
40
|
+
error?: string;
|
|
41
|
+
}>;
|
|
42
|
+
refetch: (variables?: Partial<import('@apollo/client').OperationVariables> | undefined) => Promise<import("@apollo/client").ApolloClient.QueryResult<MyWorkspacesResponse>>;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=useMyWorkspaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMyWorkspaces.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useMyWorkspaces.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAM1C,UAAU,oBAAoB;IAC5B,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,SAAS,EAAE,CAAC;KACpB,CAAC;CACH;AAoDD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe;;;;;;;oCAoEN,MAAM,KAAG,OAAO,CAAC,SAAS,EAAE,CAAC;uCA8CnC,MAAM,kBACH,MAAM,gBACR,MAAM,KACnB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;iCAkEnD,SAAS,KACnB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;qCAchC,MAAM,KACnB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;;EAoGL"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { useAuthStore as e } from "../store/authStore.js";
|
|
2
|
+
import { MyWorkspacesDocument as t } from "../../generated/global-operations.js";
|
|
3
|
+
import { resolveGatewayBaseUrls as n } from "../utils/gatewayBaseUrls.js";
|
|
4
|
+
import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
|
|
5
|
+
import { useQuery as c } from "@apollo/client/react";
|
|
6
|
+
import { graphqlFetch as l } from "@burdenoff/fe-libs/shared/graphql";
|
|
7
|
+
//#region src/auth/hooks/useMyWorkspaces.ts
|
|
8
|
+
var u = "\n query MyWorkspaces {\n myWorkspaces {\n total\n items {\n id\n name\n slug\n tenantId\n organizationId\n }\n }\n }\n", d = "\n mutation IssueWorkspaceToken($input: IssueWorkspaceTokenInput!) {\n issueWorkspaceToken(input: $input) {\n success\n token\n workspaceId\n organizationId\n expiresAt\n scopes\n error {\n code\n message\n }\n }\n }\n";
|
|
9
|
+
function f() {
|
|
10
|
+
let f = e(), [p, m] = s(!1), [h, g] = s(!1), { globalBaseUrl: _, workspaceBaseUrl: v } = a(n, []), y = o(!1), b = f.accessToken, x = a(() => b ? { headers: { authorization: `Bearer ${b}` } } : void 0, [b]), { data: S, loading: C, error: w, refetch: T } = c(t, {
|
|
11
|
+
skip: !f.isAuthenticated || !f.accessToken || y.current,
|
|
12
|
+
fetchPolicy: "cache-and-network",
|
|
13
|
+
context: x
|
|
14
|
+
});
|
|
15
|
+
i(() => {
|
|
16
|
+
S?.myWorkspaces?.items && !y.current && e.getState().setWorkspaces(S.myWorkspaces.items);
|
|
17
|
+
}, [S]), i(() => {
|
|
18
|
+
w && (w.message?.toLowerCase().includes("unauthenticated") || w.message?.toLowerCase().includes("unauthorized") || w.message?.toLowerCase().includes("not authenticated") || console.error("Failed to fetch workspaces:", w));
|
|
19
|
+
}, [w]);
|
|
20
|
+
let E = r(async (t) => {
|
|
21
|
+
let n = t || e.getState().accessToken;
|
|
22
|
+
if (!n) return console.error("Cannot fetch workspaces: No access token available"), [];
|
|
23
|
+
f.setLoadingWorkspaces(!0), g(!0);
|
|
24
|
+
try {
|
|
25
|
+
let e = await l({
|
|
26
|
+
gateway: "global",
|
|
27
|
+
query: u,
|
|
28
|
+
authToken: n,
|
|
29
|
+
baseUrl: _
|
|
30
|
+
});
|
|
31
|
+
if (e.errors?.length) {
|
|
32
|
+
let t = e.errors[0]?.message ?? "GraphQL error";
|
|
33
|
+
throw console.error("Failed to fetch workspaces:", e.errors), Error(t);
|
|
34
|
+
}
|
|
35
|
+
let t = e.data?.myWorkspaces?.items ?? [];
|
|
36
|
+
return f.setWorkspaces(t), t;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
return console.error("Failed to fetch workspaces:", e), [];
|
|
39
|
+
} finally {
|
|
40
|
+
f.setLoadingWorkspaces(!1), g(!1);
|
|
41
|
+
}
|
|
42
|
+
}, [f, _]), D = r(async (t, n, r) => {
|
|
43
|
+
let i = r || e.getState().accessToken || void 0;
|
|
44
|
+
if (!i) return {
|
|
45
|
+
success: !1,
|
|
46
|
+
error: "No access token available"
|
|
47
|
+
};
|
|
48
|
+
m(!0);
|
|
49
|
+
try {
|
|
50
|
+
let e = await l({
|
|
51
|
+
gateway: "workspace",
|
|
52
|
+
query: d,
|
|
53
|
+
variables: { input: {
|
|
54
|
+
organizationId: n,
|
|
55
|
+
workspaceId: t
|
|
56
|
+
} },
|
|
57
|
+
authToken: i,
|
|
58
|
+
workspaceToken: !1,
|
|
59
|
+
baseUrl: v,
|
|
60
|
+
workspaceId: t,
|
|
61
|
+
organizationId: n
|
|
62
|
+
});
|
|
63
|
+
if (e.errors?.length) {
|
|
64
|
+
let t = e.errors[0]?.message ?? "GraphQL error";
|
|
65
|
+
return console.error("GraphQL errors:", e.errors), {
|
|
66
|
+
success: !1,
|
|
67
|
+
error: t
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
let r = e.data?.issueWorkspaceToken;
|
|
71
|
+
return r?.success && r.token ? (f.setCurrentWorkspaceId(t), f.setWorkspaceToken(r.token), {
|
|
72
|
+
success: !0,
|
|
73
|
+
token: r.token
|
|
74
|
+
}) : {
|
|
75
|
+
success: !1,
|
|
76
|
+
error: r?.error?.message ?? "Failed to issue workspace token"
|
|
77
|
+
};
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return console.error("Failed to issue workspace token:", e), {
|
|
80
|
+
success: !1,
|
|
81
|
+
error: e instanceof Error ? e.message : "Unknown error occurred"
|
|
82
|
+
};
|
|
83
|
+
} finally {
|
|
84
|
+
m(!1);
|
|
85
|
+
}
|
|
86
|
+
}, [f, v]), O = r(async (e) => D(e.id, e.organizationId), [D]), k = r(async (e) => {
|
|
87
|
+
y.current = !0, f.setLoadingWorkspaces(!0);
|
|
88
|
+
try {
|
|
89
|
+
let t = await E(e);
|
|
90
|
+
if (t.length === 0) return {
|
|
91
|
+
success: !1,
|
|
92
|
+
error: "No workspaces found. Please create a workspace first."
|
|
93
|
+
};
|
|
94
|
+
let n = f.user, r;
|
|
95
|
+
if (n?.defaultWorkspaceId && (r = t.find((e) => e.id === n.defaultWorkspaceId)), r ||= t[0], !r) return {
|
|
96
|
+
success: !1,
|
|
97
|
+
error: "Could not select a workspace"
|
|
98
|
+
};
|
|
99
|
+
let i = await D(r.id, r.organizationId, e);
|
|
100
|
+
return i.success ? (f.setCurrentWorkspaceId(r.id), f.setCurrentOrganizationId(r.organizationId), {
|
|
101
|
+
success: !0,
|
|
102
|
+
workspace: r
|
|
103
|
+
}) : (console.warn("Workspace selected but token issue failed:", i.error), {
|
|
104
|
+
success: !0,
|
|
105
|
+
workspace: r,
|
|
106
|
+
error: `Workspace selected but token issue failed: ${i.error}`
|
|
107
|
+
});
|
|
108
|
+
} catch (e) {
|
|
109
|
+
return console.error("Failed to complete auth flow:", e), {
|
|
110
|
+
success: !1,
|
|
111
|
+
error: e instanceof Error ? e.message : "Unknown error"
|
|
112
|
+
};
|
|
113
|
+
} finally {
|
|
114
|
+
f.setLoadingWorkspaces(!1), setTimeout(() => {
|
|
115
|
+
y.current = !1;
|
|
116
|
+
}, 500);
|
|
117
|
+
}
|
|
118
|
+
}, [
|
|
119
|
+
f,
|
|
120
|
+
E,
|
|
121
|
+
D
|
|
122
|
+
]);
|
|
123
|
+
return {
|
|
124
|
+
workspaces: S?.myWorkspaces?.items ?? f.workspaces,
|
|
125
|
+
totalWorkspaces: S?.myWorkspaces?.total ?? f.workspaces.length,
|
|
126
|
+
currentWorkspaceId: f.currentWorkspaceId,
|
|
127
|
+
workspaceToken: f.workspaceToken,
|
|
128
|
+
isLoading: C || p || h || f.isLoadingWorkspaces,
|
|
129
|
+
error: w?.message ?? null,
|
|
130
|
+
fetchWorkspaces: E,
|
|
131
|
+
issueWorkspaceToken: D,
|
|
132
|
+
selectWorkspace: O,
|
|
133
|
+
completeAuthFlow: k,
|
|
134
|
+
refetch: T
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
export { f as useMyWorkspaces };
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=useMyWorkspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMyWorkspaces.js","names":[],"sources":["../../../src/auth/hooks/useMyWorkspaces.ts"],"sourcesContent":["import { useCallback, useState, useEffect, useRef, useMemo } from \"react\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { useAuthStore } from \"../store/authStore\";\nimport type { Workspace } from \"../types\";\nimport { resolveGatewayBaseUrls } from \"../utils/gatewayBaseUrls\";\n\nimport { MyWorkspacesDocument } from \"../../generated/global-operations\";\n\n// GraphQL Response Types\ninterface MyWorkspacesResponse {\n myWorkspaces: {\n total: number;\n items: Workspace[];\n };\n}\n\ninterface IssueTokenError {\n code: string;\n message: string;\n}\n\ninterface IssueWorkspaceTokenResult {\n success: boolean;\n token: string | null;\n workspaceId: string | null;\n organizationId: string | null;\n expiresAt: string | null;\n scopes: string[];\n error: IssueTokenError | null;\n}\n\n// GraphQL Operations\n\n// String versions for graphqlFetch\nconst MY_WORKSPACES_QUERY_STRING = `\n query MyWorkspaces {\n myWorkspaces {\n total\n items {\n id\n name\n slug\n tenantId\n organizationId\n }\n }\n }\n`;\n\nconst ISSUE_WORKSPACE_TOKEN_MUTATION_STRING = `\n mutation IssueWorkspaceToken($input: IssueWorkspaceTokenInput!) {\n issueWorkspaceToken(input: $input) {\n success\n token\n workspaceId\n organizationId\n expiresAt\n scopes\n error {\n code\n message\n }\n }\n }\n`;\n\n/**\n * Hook for fetching user's workspaces and issuing workspace tokens\n *\n * This hook provides:\n * - Fetch workspaces: Query to get all workspaces the user has access to\n * - Issue workspace token: Get a workspace-scoped token for API access\n * - Complete auth flow: Fetch workspaces + auto-select + issue token\n *\n * Uses the shell's Apollo client (via GatewayRoute) for useQuery, and\n * graphqlFetch from fe-libs for imperative calls that need explicit tokens.\n */\nexport function useMyWorkspaces() {\n const store = useAuthStore();\n const [tokenLoading, setTokenLoading] = useState(false);\n const [workspacesLoading, setWorkspacesLoading] = useState(false);\n const { globalBaseUrl, workspaceBaseUrl } = useMemo(\n resolveGatewayBaseUrls,\n [],\n );\n\n // Track whether completeAuthFlow is in progress to prevent the automatic\n // useQuery from racing with the imperative fetchWorkspaces call inside it.\n const authFlowInProgressRef = useRef(false);\n\n // Memoize Apollo context to prevent unstable object references from\n // causing Apollo to re-execute the query on every render.\n const accessToken = store.accessToken;\n const queryContext = useMemo(\n () =>\n accessToken\n ? { headers: { authorization: `Bearer ${accessToken}` } }\n : undefined,\n [accessToken],\n );\n\n // Query for fetching workspaces (uses shell's global Apollo client via GatewayRoute)\n // Skip during completeAuthFlow — it handles fetching imperatively via fetchWorkspaces().\n // This query is only for subsequent page loads or manual refetches.\n const {\n data,\n loading: queryLoading,\n error: queryError,\n refetch,\n } = useQuery<MyWorkspacesResponse>(MyWorkspacesDocument, {\n skip:\n !store.isAuthenticated ||\n !store.accessToken ||\n authFlowInProgressRef.current,\n fetchPolicy: \"cache-and-network\",\n context: queryContext,\n });\n\n // Handle workspaces data updates — only sync to store when we have data\n // and auth flow is NOT in progress (to avoid competing writes).\n useEffect(() => {\n if (data?.myWorkspaces?.items && !authFlowInProgressRef.current) {\n useAuthStore.getState().setWorkspaces(data.myWorkspaces.items);\n }\n }, [data]);\n\n // Handle workspaces fetch error (suppress auth errors during login transition)\n useEffect(() => {\n if (queryError) {\n const isAuthError =\n queryError.message?.toLowerCase().includes(\"unauthenticated\") ||\n queryError.message?.toLowerCase().includes(\"unauthorized\") ||\n queryError.message?.toLowerCase().includes(\"not authenticated\");\n if (!isAuthError) {\n console.error(\"Failed to fetch workspaces:\", queryError);\n }\n }\n }, [queryError]);\n\n /**\n * Manually fetch workspaces using graphqlFetch with explicit Authorization header.\n * Used when the token is freshly obtained (e.g. right after login) and may not\n * yet be in profile storage.\n */\n const fetchWorkspaces = useCallback(\n async (accessToken?: string): Promise<Workspace[]> => {\n const token = accessToken || useAuthStore.getState().accessToken;\n\n if (!token) {\n console.error(\"Cannot fetch workspaces: No access token available\");\n return [];\n }\n\n store.setLoadingWorkspaces(true);\n setWorkspacesLoading(true);\n try {\n const result = await graphqlFetch<{\n myWorkspaces: { items: Workspace[] };\n }>({\n gateway: \"global\",\n query: MY_WORKSPACES_QUERY_STRING,\n authToken: token,\n baseUrl: globalBaseUrl,\n });\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n console.error(\"Failed to fetch workspaces:\", result.errors);\n throw new Error(errorMessage);\n }\n\n const workspaces: Workspace[] = result.data?.myWorkspaces?.items ?? [];\n store.setWorkspaces(workspaces);\n return workspaces;\n } catch (error) {\n console.error(\"Failed to fetch workspaces:\", error);\n return [];\n } finally {\n store.setLoadingWorkspaces(false);\n setWorkspacesLoading(false);\n }\n },\n [store, globalBaseUrl],\n );\n\n /**\n * Issue workspace token for a specific workspace.\n * Uses graphqlFetch to call the workspace gateway.\n */\n const issueWorkspaceToken = useCallback(\n async (\n workspaceId: string,\n organizationId: string,\n accessToken?: string,\n ): Promise<{ success: boolean; token?: string; error?: string }> => {\n const authToken =\n accessToken || useAuthStore.getState().accessToken || undefined;\n\n if (!authToken) {\n return { success: false, error: \"No access token available\" };\n }\n\n setTokenLoading(true);\n try {\n const result = await graphqlFetch<{\n issueWorkspaceToken: IssueWorkspaceTokenResult;\n }>({\n gateway: \"workspace\",\n query: ISSUE_WORKSPACE_TOKEN_MUTATION_STRING,\n variables: {\n input: {\n organizationId,\n workspaceId,\n },\n },\n authToken,\n workspaceToken: false,\n baseUrl: workspaceBaseUrl,\n workspaceId,\n organizationId,\n });\n\n if (result.errors?.length) {\n const errorMessage = result.errors[0]?.message ?? \"GraphQL error\";\n console.error(\"GraphQL errors:\", result.errors);\n return { success: false, error: errorMessage };\n }\n\n const tokenResult = result.data?.issueWorkspaceToken;\n\n if (tokenResult?.success && tokenResult.token) {\n store.setCurrentWorkspaceId(workspaceId);\n store.setWorkspaceToken(tokenResult.token);\n return { success: true, token: tokenResult.token };\n }\n\n return {\n success: false,\n error:\n tokenResult?.error?.message ?? \"Failed to issue workspace token\",\n };\n } catch (error) {\n console.error(\"Failed to issue workspace token:\", error);\n return {\n success: false,\n error:\n error instanceof Error ? error.message : \"Unknown error occurred\",\n };\n } finally {\n setTokenLoading(false);\n }\n },\n [store, workspaceBaseUrl],\n );\n\n /**\n * Select a workspace and issue token for it\n */\n const selectWorkspace = useCallback(\n async (\n workspace: Workspace,\n ): Promise<{ success: boolean; error?: string }> => {\n return issueWorkspaceToken(workspace.id, workspace.organizationId);\n },\n [issueWorkspaceToken],\n );\n\n /**\n * Complete the post-login auth flow:\n * 1. Fetch user's workspaces\n * 2. Auto-select default workspace (user's defaultWorkspaceId or first workspace)\n * 3. Issue workspace token\n */\n const completeAuthFlow = useCallback(\n async (\n accessToken?: string,\n ): Promise<{\n success: boolean;\n workspace?: Workspace;\n error?: string;\n }> => {\n // Signal that the auth flow is handling workspace fetching imperatively.\n // This prevents the useQuery from firing a duplicate request.\n authFlowInProgressRef.current = true;\n store.setLoadingWorkspaces(true);\n try {\n const workspaces = await fetchWorkspaces(accessToken);\n\n if (workspaces.length === 0) {\n return {\n success: false,\n error: \"No workspaces found. Please create a workspace first.\",\n };\n }\n\n const user = store.user;\n let selectedWorkspace: Workspace | undefined;\n\n if (user?.defaultWorkspaceId) {\n selectedWorkspace = workspaces.find(\n (ws) => ws.id === user.defaultWorkspaceId,\n );\n }\n\n if (!selectedWorkspace) {\n selectedWorkspace = workspaces[0];\n }\n\n if (!selectedWorkspace) {\n return { success: false, error: \"Could not select a workspace\" };\n }\n\n const tokenResult = await issueWorkspaceToken(\n selectedWorkspace.id,\n selectedWorkspace.organizationId,\n accessToken,\n );\n\n if (!tokenResult.success) {\n console.warn(\n \"Workspace selected but token issue failed:\",\n tokenResult.error,\n );\n return {\n success: true,\n workspace: selectedWorkspace,\n error: `Workspace selected but token issue failed: ${tokenResult.error}`,\n };\n }\n\n // Set workspace/org context so downstream hooks (useProjectSyncEffect)\n // can fetch projects for the context switcher dropdown.\n store.setCurrentWorkspaceId(selectedWorkspace.id);\n store.setCurrentOrganizationId(selectedWorkspace.organizationId);\n\n return {\n success: true,\n workspace: selectedWorkspace,\n };\n } catch (error) {\n console.error(\"Failed to complete auth flow:\", error);\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n } finally {\n store.setLoadingWorkspaces(false);\n // Allow the useQuery to operate normally after the auth flow completes.\n // Use a short delay so that the navigation to \"/\" happens first,\n // preventing the query from firing on the login page.\n setTimeout(() => {\n authFlowInProgressRef.current = false;\n }, 500);\n }\n },\n [store, fetchWorkspaces, issueWorkspaceToken],\n );\n\n return {\n // Data\n workspaces: data?.myWorkspaces?.items ?? store.workspaces,\n totalWorkspaces: data?.myWorkspaces?.total ?? store.workspaces.length,\n currentWorkspaceId: store.currentWorkspaceId,\n workspaceToken: store.workspaceToken,\n\n // State\n isLoading:\n queryLoading ||\n tokenLoading ||\n workspacesLoading ||\n store.isLoadingWorkspaces,\n error: queryError?.message ?? null,\n\n // Actions\n fetchWorkspaces,\n issueWorkspaceToken,\n selectWorkspace,\n completeAuthFlow,\n refetch,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AuthResult } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Supported OAuth providers
|
|
5
|
+
*/
|
|
6
|
+
export type OAuthProvider = "google" | "github" | "microsoft";
|
|
7
|
+
/**
|
|
8
|
+
* Hook for OAuth authentication operations
|
|
9
|
+
*/
|
|
10
|
+
export declare function useOAuthOperations(): {
|
|
11
|
+
initiateOAuth: (provider: OAuthProvider) => void;
|
|
12
|
+
completeOAuth: (code: string, state: string) => Promise<AuthResult>;
|
|
13
|
+
initiateGoogleOAuth: () => void;
|
|
14
|
+
initiateGitHubOAuth: () => void;
|
|
15
|
+
initiateMicrosoftOAuth: () => void;
|
|
16
|
+
isProviderConfigured: (provider: OAuthProvider) => boolean;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=useOAuthOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOAuthOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useOAuthOperations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,UAAU,CAAC;AAgBvD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAyC9D;;GAEG;AACH,wBAAgB,kBAAkB;8BAWC,aAAa;0BAuDtC,MAAM,SACL,MAAM,KACZ,OAAO,CAAC,UAAU,CAAC;;;;qCAmGkB,aAAa,KAAG,OAAO;;EAoBhE"}
|