@plumile/backoffice-react 0.1.91 → 0.1.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/lib/esm/{AcceptInvitationScreen-DLc4aovr.js → AcceptInvitationScreen-B1IPafwD.js} +2 -2
  2. package/lib/esm/{AcceptInvitationScreen-DLc4aovr.js.map → AcceptInvitationScreen-B1IPafwD.js.map} +1 -1
  3. package/lib/esm/{BackofficeAcceptInvitationPage-D0dZnrV7.js → BackofficeAcceptInvitationPage-CEtApVwL.js} +3 -3
  4. package/lib/esm/{BackofficeAcceptInvitationPage-D0dZnrV7.js.map → BackofficeAcceptInvitationPage-CEtApVwL.js.map} +1 -1
  5. package/lib/esm/{BackofficeLayoutPage-j3VUX3Tu.js → BackofficeLayoutPage-CKXS0nDO.js} +2 -2
  6. package/lib/esm/{BackofficeLayoutPage-j3VUX3Tu.js.map → BackofficeLayoutPage-CKXS0nDO.js.map} +1 -1
  7. package/lib/esm/{BackofficeLoginPage-BkQHm0x6.js → BackofficeLoginPage-Cc3kcOQV.js} +3 -3
  8. package/lib/esm/{BackofficeLoginPage-BkQHm0x6.js.map → BackofficeLoginPage-Cc3kcOQV.js.map} +1 -1
  9. package/lib/esm/backoffice-react.js +1010 -1004
  10. package/lib/esm/backoffice-react.js.map +1 -1
  11. package/lib/esm/{environment-BXoBq_6e.js → environment-DQfVyWHJ.js} +76 -51
  12. package/lib/esm/environment-DQfVyWHJ.js.map +1 -0
  13. package/lib/esm/{synchronizeAuthStatusQuery-1juorUEX.js → synchronizeAuthStatusQuery-BoPKMrP1.js} +2 -2
  14. package/lib/esm/{synchronizeAuthStatusQuery-1juorUEX.js.map → synchronizeAuthStatusQuery-BoPKMrP1.js.map} +1 -1
  15. package/lib/esm/{useAuth-BdSNpGqe.js → useAuth-CheTnq60.js} +2 -2
  16. package/lib/esm/{useAuth-BdSNpGqe.js.map → useAuth-CheTnq60.js.map} +1 -1
  17. package/lib/esm/{useBackofficeAuth-C16Euw2X.js → useBackofficeAuth-ers1FUGe.js} +2 -2
  18. package/lib/esm/{useBackofficeAuth-C16Euw2X.js.map → useBackofficeAuth-ers1FUGe.js.map} +1 -1
  19. package/lib/types/hooks/useConditionalSubscription.d.ts +1 -0
  20. package/lib/types/hooks/useConditionalSubscription.d.ts.map +1 -1
  21. package/lib/types/i18n/resources.d.ts +2 -0
  22. package/lib/types/i18n/resources.d.ts.map +1 -1
  23. package/lib/types/index.d.ts +2 -2
  24. package/lib/types/index.d.ts.map +1 -1
  25. package/lib/types/provider/BackofficeProvider.d.ts.map +1 -1
  26. package/lib/types/relay/RelayProvider.d.ts.map +1 -1
  27. package/lib/types/relay/environment.d.ts +13 -0
  28. package/lib/types/relay/environment.d.ts.map +1 -1
  29. package/package.json +5 -5
  30. package/lib/esm/environment-BXoBq_6e.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useAuth-BdSNpGqe.js","names":[],"sources":["../../src/auth/login/MfaChallengeForm.tsx","../../src/modules/webauthn.ts","../../src/hooks/useAuth.ts"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n useCallback,\n useEffect,\n useState,\n type FormEvent,\n type JSX,\n} from 'react';\nimport { useBackofficeReactTranslation } from '../../i18n/useBackofficeReactTranslation.js';\n\nimport { Button, FormError, FormField } from '@plumile/ui';\n\nimport type { TotpCredentials, UseAuthReturn } from '../../hooks/useAuth.js';\n\nimport * as styles from './loginPage.css.js';\n\ntype Props = {\n auth: Pick<\n UseAuthReturn,\n 'completeMfa' | 'isLoading' | 'error' | 'emailHint' | 'reset' | 'clearError'\n >;\n onSuccess: () => void;\n onBack: () => void;\n};\n\nexport const MfaChallengeForm = ({\n auth,\n onSuccess,\n onBack,\n}: Props): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n const [code, setCode] = useState('');\n const [localError, setLocalError] = useState<string | null>(null);\n\n // Clear any stale errors when the MFA form is shown\n useEffect(() => {\n auth.clearError();\n setLocalError(null);\n }, [auth]);\n\n const handleSubmit = useCallback(\n async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setLocalError(null);\n\n const trimmed = code.trim();\n if (trimmed.length < 4) {\n setLocalError(t('auth.mfa.errors.shortCode'));\n return;\n }\n\n try {\n const credentials: TotpCredentials = {\n code: trimmed,\n };\n await auth.completeMfa(credentials);\n onSuccess();\n } catch {\n const authMessage = auth.error?.message;\n setLocalError(authMessage ?? t('auth.mfa.errors.verificationFailed'));\n }\n },\n [auth, code, onSuccess, t],\n );\n\n const helper =\n auth.emailHint != null\n ? t('auth.mfa.helper.withEmail', { email: auth.emailHint })\n : t('auth.mfa.helper.default');\n\n const formError = localError ?? auth.error?.message ?? null;\n\n return (\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n <form className={styles.formSurface} onSubmit={handleSubmit} noValidate>\n <div className={styles.stack}>\n <p className={styles.helper}>{helper}</p>\n {formError != null ? <FormError>{formError}</FormError> : null}\n <FormField\n label={t('auth.mfa.form.label')}\n name=\"code\"\n type=\"text\"\n value={code}\n onChange={(event) => {\n setCode(event.target.value);\n setLocalError(null);\n }}\n placeholder={t('auth.mfa.form.placeholder')}\n autoComplete=\"one-time-code\"\n autoFocus\n required\n />\n </div>\n <div className={styles.actionsRow}>\n <Button\n type=\"button\"\n variant=\"text\"\n size=\"small\"\n className={styles.inlineLink}\n onClick={() => {\n auth.reset();\n onBack();\n }}\n >\n {t('auth.mfa.actions.back')}\n </Button>\n <Button type=\"submit\" size=\"large\" isLoading={auth.isLoading}>\n {t('auth.mfa.actions.submit')}\n </Button>\n </div>\n </form>\n );\n};\n","/**\n * Buffer to base64 url\n */\nexport function bufferToBase64Url(input: ArrayBuffer): string {\n const byteArray = new Uint8Array(input);\n let binary = '';\n for (const byte of byteArray) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Base64 url to buffer\n */\nexport function base64UrlToBuffer(input: string): ArrayBuffer {\n const normalized = input.replace(/-/g, '+').replace(/_/g, '/');\n const remainder = normalized.length % 4;\n let padding = '';\n if (remainder === 2) {\n padding = '==';\n } else if (remainder === 3) {\n padding = '=';\n } else if (remainder === 1) {\n throw new Error('Invalid base64url input length.');\n }\n const padded = `${normalized}${padding}`;\n const binary = atob(padded);\n const output = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n output[i] = binary.charCodeAt(i);\n }\n return output.buffer;\n}\n\nexport type WebAuthnRegistrationErrorKind =\n | 'cancelled'\n | 'credentialInUse'\n | 'notSupported'\n | 'failed';\n\n/**\n * Maps a browser WebAuthn registration error to a stable UI category.\n */\nexport function mapWebAuthnRegistrationError(\n error: unknown,\n): WebAuthnRegistrationErrorKind {\n if (!(error instanceof DOMException)) {\n return 'failed';\n }\n\n switch (error.name) {\n case 'NotAllowedError':\n case 'AbortError':\n return 'cancelled';\n case 'InvalidStateError':\n return 'credentialInUse';\n case 'SecurityError':\n case 'NotSupportedError':\n return 'notSupported';\n default:\n return 'failed';\n }\n}\n\n/**\n * Parse sign count\n */\nexport function parseSignCount(authenticatorData: ArrayBuffer): number {\n if (authenticatorData.byteLength < 37) {\n return 0;\n }\n const view = new DataView(authenticatorData);\n return view.getUint32(33, false);\n}\n","/* eslint-disable no-ternary */\nimport { useCallback, useState } from 'react';\n\nimport {\n type MutationPayloadBase,\n requireField,\n resolveMutationOutcome,\n} from '../relay/mutationResult.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\n\nimport { resetRelayStore } from '../relay/environment.js';\nimport type { PayloadError } from 'relay-runtime';\n\nimport type {\n AuthMethod,\n LoginNextStep,\n MfaLevel,\n} from '../modules/sharedSchemaTypes.js';\nimport {\n base64UrlToBuffer,\n bufferToBase64Url,\n parseSignCount,\n} from '../modules/webauthn.js';\n\nexport type AuthPayload = {\n authMethod: AuthMethod | null | undefined;\n challengeToken: string | null | undefined;\n loggedInUser: { id: string } | null | undefined;\n mfaLevel: MfaLevel | null | undefined;\n nextStep: LoginNextStep | null | undefined;\n};\n\ntype LoginErrorReason =\n | 'INVALID_CREDENTIALS'\n | 'ACCOUNT_LOCKED'\n | 'RATE_LIMITED'\n | 'INTERNAL_ERROR';\n\ntype LogoutErrorReason =\n | 'UNAUTHENTICATED'\n | 'SESSION_NOT_FOUND'\n | 'INTERNAL_ERROR';\n\ntype BeginAuthenticationErrorReason = 'INVALID_EMAIL' | 'INTERNAL_ERROR';\n\ntype BeginPasskeyLoginErrorReason =\n | 'INVALID_EMAIL'\n | 'PASSKEY_NOT_FOUND'\n | 'PASSKEY_NOT_SUPPORTED'\n | 'INTERNAL_ERROR';\n\ntype FinishPasskeyLoginErrorReason =\n | 'INVALID_CHALLENGE_TOKEN'\n | 'CHALLENGE_EXPIRED'\n | 'INVALID_ASSERTION'\n | 'INTERNAL_ERROR';\n\ntype CompleteMfaErrorReason =\n | 'INVALID_CHALLENGE_TOKEN'\n | 'CHALLENGE_EXPIRED'\n | 'INVALID_CODE'\n | 'TOO_MANY_ATTEMPTS'\n | 'INTERNAL_ERROR';\n\ntype AcceptInvitationErrorReason =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'ALREADY_ACCEPTED'\n | 'PASSWORD_MISMATCH'\n | 'PASSWORD_POLICY_VIOLATION'\n | 'RATE_LIMITED'\n | 'EMAIL_MISMATCH'\n | 'INTERNAL_ERROR';\n\nexport type BeginAuthenticationPayload =\n MutationPayloadBase<BeginAuthenticationErrorReason> & {\n lockedUntil: string | null | undefined;\n methods: readonly {\n method: AuthMethod;\n mfaEnforced?: boolean | null | undefined;\n }[];\n };\n\nexport type BeginPasskeyLoginPayload =\n MutationPayloadBase<BeginPasskeyLoginErrorReason> & {\n allowCredentials: readonly string[];\n challenge: string;\n challengeToken: string;\n rpId: string;\n };\n\ntype LoginMutationPayload = MutationPayloadBase<LoginErrorReason> & {\n payload?: AuthPayload | null | undefined;\n};\n\ntype LogoutPayload = {\n loggedOut?: boolean | null | undefined;\n};\n\ntype LogoutMutationPayload = MutationPayloadBase<LogoutErrorReason> & {\n payload?: LogoutPayload | null | undefined;\n};\n\ntype CompleteMfaMutationPayload =\n MutationPayloadBase<CompleteMfaErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\ntype FinishPasskeyLoginMutationPayload =\n MutationPayloadBase<FinishPasskeyLoginErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\ntype AcceptInvitationMutationPayload =\n MutationPayloadBase<AcceptInvitationErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\nexport type LoginResponse = { login: AuthPayload | LoginMutationPayload };\nexport type LogoutResponse = { logout: LogoutPayload | LogoutMutationPayload };\nexport type CompleteMfaResponse = {\n completeMfa: AuthPayload | CompleteMfaMutationPayload;\n};\nexport type FinishPasskeyLoginResponse = {\n finishPasskeyLogin: AuthPayload | FinishPasskeyLoginMutationPayload;\n};\nexport type AcceptInvitationResponse = {\n acceptInvitation: AuthPayload | AcceptInvitationMutationPayload;\n};\nexport type BeginAuthenticationResponse = {\n beginAuthentication: BeginAuthenticationPayload;\n};\nexport type BeginPasskeyLoginResponse = {\n beginPasskeyLogin: BeginPasskeyLoginPayload;\n};\n\nexport type LoginVariables = {\n input: LoginCredentials;\n};\n\nexport type LogoutVariables = Record<PropertyKey, never>;\n\nexport type CompleteMfaVariables = {\n input: {\n challengeToken: string;\n code: string;\n };\n};\n\nexport type BeginPasskeyLoginVariables = {\n email: string;\n};\n\nexport type FinishPasskeyLoginVariables = {\n input: {\n challenge: string;\n challengeToken: string;\n credentialId: string;\n signCount: number;\n userHandle?: string | null;\n };\n};\n\nexport type AcceptInvitationVariables = {\n input: {\n token: string;\n password: string;\n passwordConfirmation: string;\n };\n};\n\nexport type BeginAuthenticationVariables = {\n email: string;\n};\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\ntype MutationCommit<TVariables, TResponse> = (\n config: MutationCommitConfig<TVariables, TResponse>,\n) => void;\n\ntype MutationEntry<TVariables, TResponse> = {\n commit: MutationCommit<TVariables, TResponse>;\n isInFlight: boolean;\n};\n\nexport type AuthMutationHooks = {\n login: MutationEntry<LoginVariables, LoginResponse>;\n logout: MutationEntry<LogoutVariables, LogoutResponse>;\n completeMfa: MutationEntry<CompleteMfaVariables, CompleteMfaResponse>;\n beginPasskeyLogin: MutationEntry<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >;\n finishPasskeyLogin: MutationEntry<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >;\n acceptInvitation?: MutationEntry<\n AcceptInvitationVariables,\n AcceptInvitationResponse\n >;\n beginAuthentication: MutationEntry<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >;\n};\n\ninterface User {\n id: string;\n}\n\nexport type LoginStatus = 'success' | 'mfa-required' | 'error';\n\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\nexport interface TotpCredentials {\n code: string;\n}\n\nexport interface AcceptInvitationCredentials {\n token: string;\n password: string;\n passwordConfirmation: string;\n}\n\nexport interface AuthError {\n message: string;\n code?: string;\n}\n\nexport interface UseAuthReturn {\n authMethod: AuthMethod | null;\n challengeToken: string | null;\n nextStep: LoginNextStep | null;\n mfaLevel: MfaLevel | null;\n emailHint: string | null;\n lockedUntil: string | null;\n availableMethods: AuthMethod[];\n login: (credentials: LoginCredentials) => Promise<LoginStatus>;\n loginWithPasskey: (params: { email: string }) => Promise<LoginStatus>;\n completeMfa: (credentials: TotpCredentials) => Promise<void>;\n acceptInvitation: (\n credentials: AcceptInvitationCredentials,\n ) => Promise<LoginStatus>;\n beginAuthentication: (\n email: string,\n ) => Promise<{ methods: AuthMethod[]; lockedUntil: string | null }>;\n logout: () => Promise<void>;\n reset: () => void;\n clearError: () => void;\n isLoading: boolean;\n error: AuthError | null;\n user: User | null;\n}\n\nconst initialState = {\n authMethod: null as AuthMethod | null,\n challengeToken: null as string | null,\n emailHint: null as string | null,\n mfaLevel: null as MfaLevel | null,\n nextStep: null as LoginNextStep | null,\n};\n\nexport const createUseAuth = (mutations: AuthMutationHooks) => {\n return (): UseAuthReturn => {\n const { t } = useBackofficeReactTranslation();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n const [user, setUser] = useState<User | null>(null);\n const [lockedUntil, setLockedUntil] = useState<string | null>(null);\n const [availableMethods, setAvailableMethods] = useState<AuthMethod[]>([]);\n const [authState, setAuthState] = useState(initialState);\n\n const commitLoginMutation = mutations.login.commit;\n const commitLogoutMutation = mutations.logout.commit;\n const commitCompleteMfaMutation = mutations.completeMfa.commit;\n const commitBeginPasskeyLoginMutation = mutations.beginPasskeyLogin.commit;\n const commitFinishPasskeyLoginMutation =\n mutations.finishPasskeyLogin.commit;\n const commitAcceptInvitationMutation = mutations.acceptInvitation?.commit;\n const commitBeginAuthenticationMutation =\n mutations.beginAuthentication.commit;\n\n const defaultLoginErrorMessage = t('auth.loginFlow.errors.tryAgain');\n const defaultBeginAuthenticationErrorMessage = t(\n 'auth.loginFlow.errors.tryAgain',\n );\n const defaultPasskeyErrorMessage = t('auth.passkey.errors.failed');\n const defaultMfaErrorMessage = t('auth.mfa.errors.verificationFailed');\n const defaultInvitationErrorMessage = t(\n 'auth.acceptInvitation.errors.default',\n );\n const mfaInvalidChallengeMessage = t('auth.mfa.errors.invalidChallenge');\n const passkeyNotAvailableMessage = t('auth.passkey.errors.notAvailable');\n const defaultLogoutErrorMessage = 'Logout failed.';\n\n const reset = useCallback(() => {\n setError(null);\n setUser(null);\n setLockedUntil(null);\n setAvailableMethods([]);\n setAuthState(initialState);\n }, []);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n const updateAuthStateFromPayload = useCallback(\n (payload: AuthPayload): LoginStatus => {\n const authMethod = payload.authMethod ?? null;\n const challengeToken = payload.challengeToken ?? null;\n const mfaLevel = payload.mfaLevel ?? null;\n const nextStep = payload.nextStep ?? null;\n\n setAuthState((prev) => {\n return {\n ...prev,\n authMethod,\n challengeToken,\n mfaLevel,\n nextStep,\n };\n });\n\n if (payload.loggedInUser != null && nextStep == null) {\n setUser({\n id: payload.loggedInUser.id,\n });\n return 'success';\n }\n\n if (nextStep === 'TOTP' && challengeToken != null) {\n return 'mfa-required';\n }\n\n return 'error';\n },\n [],\n );\n\n const isMutationPayload = useCallback(\n (value: unknown): value is MutationPayloadBase => {\n return (\n value != null &&\n typeof value === 'object' &&\n ('status' in value || 'result' in value)\n );\n },\n [],\n );\n\n const mapLoginReason = useCallback(\n (reason: LoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CREDENTIALS':\n return t('auth.loginFlow.errors.invalidCredentials');\n case 'ACCOUNT_LOCKED':\n return t('auth.loginFlow.errors.accountLocked');\n case 'RATE_LIMITED':\n return t('auth.loginFlow.errors.rateLimited');\n case 'INTERNAL_ERROR':\n return t('auth.loginFlow.errors.tryAgain');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapBeginAuthenticationReason = useCallback(\n (reason: BeginAuthenticationErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_EMAIL':\n return t('auth.loginFlow.errors.invalidEmail');\n case 'INTERNAL_ERROR':\n return t('auth.loginFlow.errors.tryAgain');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapBeginPasskeyLoginReason = useCallback(\n (reason: BeginPasskeyLoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_EMAIL':\n return t('auth.passkey.errors.invalidEmail');\n case 'PASSKEY_NOT_FOUND':\n return t('auth.passkey.errors.notFound');\n case 'PASSKEY_NOT_SUPPORTED':\n return t('auth.passkey.errors.notAvailable');\n case 'INTERNAL_ERROR':\n return t('auth.passkey.errors.failed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapFinishPasskeyLoginReason = useCallback(\n (reason: FinishPasskeyLoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CHALLENGE_TOKEN':\n return t('auth.passkey.errors.invalidChallenge');\n case 'CHALLENGE_EXPIRED':\n return t('auth.passkey.errors.challengeExpired');\n case 'INVALID_ASSERTION':\n return t('auth.passkey.errors.invalidAssertion');\n case 'INTERNAL_ERROR':\n return t('auth.passkey.errors.failed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapCompleteMfaReason = useCallback(\n (reason: CompleteMfaErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CHALLENGE_TOKEN':\n return t('auth.mfa.errors.invalidChallenge');\n case 'CHALLENGE_EXPIRED':\n return t('auth.mfa.errors.expired');\n case 'INVALID_CODE':\n return t('auth.mfa.errors.invalidCode');\n case 'TOO_MANY_ATTEMPTS':\n return t('auth.mfa.errors.tooManyAttempts');\n case 'INTERNAL_ERROR':\n return t('auth.mfa.errors.verificationFailed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapAcceptInvitationReason = useCallback(\n (reason: AcceptInvitationErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_TOKEN':\n return t('auth.acceptInvitation.errors.invalidToken');\n case 'TOKEN_EXPIRED':\n return t('auth.acceptInvitation.errors.expired');\n case 'ALREADY_ACCEPTED':\n return t('auth.acceptInvitation.errors.alreadyAccepted');\n case 'PASSWORD_MISMATCH':\n return t('auth.acceptInvitation.errors.passwordMismatch');\n case 'PASSWORD_POLICY_VIOLATION':\n return t('auth.acceptInvitation.errors.passwordPolicyViolation');\n case 'RATE_LIMITED':\n return t('auth.acceptInvitation.errors.rateLimited');\n case 'EMAIL_MISMATCH':\n return t('auth.acceptInvitation.errors.emailMismatch');\n case 'INTERNAL_ERROR':\n return t('auth.acceptInvitation.errors.default');\n default:\n return null;\n }\n },\n [t],\n );\n\n const beginAuthentication = useCallback(\n async (\n email: string,\n ): Promise<{ methods: AuthMethod[]; lockedUntil: string | null }> => {\n return new Promise((resolve, reject) => {\n commitBeginAuthenticationMutation({\n variables: { email },\n onCompleted: (response) => {\n const rawPayload = response.beginAuthentication;\n let payload = rawPayload;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultBeginAuthenticationErrorMessage,\n mapReason: mapBeginAuthenticationReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n payload = outcome.payload;\n }\n\n const methods = payload.methods.map((item) => {\n return item.method;\n });\n const locked = payload.lockedUntil ?? null;\n setAvailableMethods(methods);\n setLockedUntil(locked);\n resolve({ methods, lockedUntil: locked });\n },\n onError: () => {\n const authError: AuthError = {\n message: defaultBeginAuthenticationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitBeginAuthenticationMutation,\n defaultBeginAuthenticationErrorMessage,\n isMutationPayload,\n mapBeginAuthenticationReason,\n ],\n );\n\n const login = useCallback(\n async (credentials: LoginCredentials): Promise<LoginStatus> => {\n setIsLoading(true);\n setError(null);\n setAuthState((prev) => {\n return {\n ...prev,\n emailHint: credentials.email,\n };\n });\n\n return new Promise((resolve, reject) => {\n commitLoginMutation({\n variables: {\n input: credentials,\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.login;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultLoginErrorMessage,\n mapReason: mapLoginReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success' || status === 'mfa-required') {\n resolve(status);\n return;\n }\n\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitLoginMutation,\n defaultLoginErrorMessage,\n isMutationPayload,\n mapLoginReason,\n updateAuthStateFromPayload,\n ],\n );\n\n const completeMfa = useCallback(\n async (credentials: TotpCredentials): Promise<void> => {\n const { challengeToken } = authState;\n if (challengeToken == null) {\n const authError: AuthError = {\n message: mfaInvalidChallengeMessage,\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise((resolve, reject) => {\n commitCompleteMfaMutation({\n variables: {\n input: {\n challengeToken,\n code: credentials.code,\n },\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.completeMfa;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultMfaErrorMessage,\n mapReason: mapCompleteMfaReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success') {\n resolve();\n return;\n }\n\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n authState,\n commitCompleteMfaMutation,\n defaultMfaErrorMessage,\n isMutationPayload,\n mapCompleteMfaReason,\n mfaInvalidChallengeMessage,\n updateAuthStateFromPayload,\n ],\n );\n\n const loginWithPasskey = useCallback(\n async ({ email }: { email: string }): Promise<LoginStatus> => {\n if (typeof window === 'undefined') {\n const authError: AuthError = {\n message: passkeyNotAvailableMessage,\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n setAuthState((prev) => {\n return {\n ...prev,\n emailHint: email,\n };\n });\n\n return new Promise((resolve, reject) => {\n commitBeginPasskeyLoginMutation({\n variables: {\n email,\n },\n onCompleted: (response) => {\n const rawOptions = response.beginPasskeyLogin;\n let options = rawOptions;\n\n if (isMutationPayload(rawOptions)) {\n const outcome = resolveMutationOutcome(rawOptions, {\n defaultErrorMessage: defaultPasskeyErrorMessage,\n mapReason: mapBeginPasskeyLoginReason,\n });\n if (!outcome.ok) {\n setIsLoading(false);\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n options = outcome.payload;\n }\n\n const continuePasskeyLogin = async (): Promise<void> => {\n try {\n const assertion = (await navigator.credentials.get({\n publicKey: {\n allowCredentials: options.allowCredentials.map(\n (credentialId) => {\n return {\n id: base64UrlToBuffer(credentialId),\n type: 'public-key' as const,\n };\n },\n ),\n challenge: base64UrlToBuffer(options.challenge),\n rpId: options.rpId,\n userVerification: 'preferred',\n },\n })) as PublicKeyCredential | null;\n\n if (assertion == null) {\n throw new Error(\n 'No credential returned by the authenticator.',\n );\n }\n\n const assertionResponse =\n assertion.response as AuthenticatorAssertionResponse;\n const signCount = parseSignCount(\n assertionResponse.authenticatorData,\n );\n\n commitFinishPasskeyLoginMutation({\n variables: {\n input: {\n challenge: options.challenge,\n challengeToken: options.challengeToken,\n credentialId: assertion.id,\n signCount,\n userHandle:\n assertionResponse.userHandle != null\n ? bufferToBase64Url(assertionResponse.userHandle)\n : null,\n },\n },\n onCompleted: (finishResponse) => {\n setIsLoading(false);\n const rawPayload = finishResponse.finishPasskeyLogin;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultPasskeyErrorMessage,\n mapReason: mapFinishPasskeyLoginReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success') {\n resolve(status);\n return;\n }\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n } catch (credentialError) {\n setIsLoading(false);\n const authError: AuthError = {\n message:\n credentialError instanceof Error\n ? credentialError.message\n : 'Passkey login was cancelled.',\n };\n setError(authError);\n reject(authError);\n }\n };\n\n continuePasskeyLogin().catch(() => {\n return undefined;\n });\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitBeginPasskeyLoginMutation,\n commitFinishPasskeyLoginMutation,\n defaultPasskeyErrorMessage,\n isMutationPayload,\n mapBeginPasskeyLoginReason,\n mapFinishPasskeyLoginReason,\n passkeyNotAvailableMessage,\n updateAuthStateFromPayload,\n ],\n );\n\n const acceptInvitation = useCallback(\n async (\n credentials: AcceptInvitationCredentials,\n ): Promise<LoginStatus> => {\n if (commitAcceptInvitationMutation == null) {\n const authError: AuthError = {\n message: 'Invitation acceptance is not available.',\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise((resolve, reject) => {\n commitAcceptInvitationMutation({\n variables: {\n input: {\n token: credentials.token,\n password: credentials.password,\n passwordConfirmation: credentials.passwordConfirmation,\n },\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.acceptInvitation;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultInvitationErrorMessage,\n mapReason: mapAcceptInvitationReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success' || status === 'mfa-required') {\n resolve(status);\n return;\n }\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitAcceptInvitationMutation,\n defaultInvitationErrorMessage,\n isMutationPayload,\n mapAcceptInvitationReason,\n updateAuthStateFromPayload,\n ],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n setIsLoading(true);\n\n return new Promise((resolve, reject) => {\n commitLogoutMutation({\n variables: {},\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.logout;\n let loggedOutValue: boolean | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultLogoutErrorMessage,\n });\n if (!outcome.ok) {\n const authError: AuthError = { message: outcome.message };\n setError(authError);\n reject(authError);\n return;\n }\n\n const loggedOutResult = requireField(\n rawPayload.payload?.loggedOut ?? null,\n defaultLogoutErrorMessage,\n );\n if (!loggedOutResult.ok) {\n const authError: AuthError = {\n message: loggedOutResult.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n loggedOutValue = loggedOutResult.value;\n } else {\n const loggedOutResult = requireField(\n rawPayload.loggedOut ?? null,\n defaultLogoutErrorMessage,\n );\n if (!loggedOutResult.ok) {\n const authError: AuthError = {\n message: loggedOutResult.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n loggedOutValue = loggedOutResult.value;\n }\n\n if (!loggedOutValue) {\n const authError: AuthError = {\n message: defaultLogoutErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n setUser(null);\n setAuthState(initialState);\n resetRelayStore();\n\n resolve();\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultLogoutErrorMessage,\n };\n setError(authError);\n resetRelayStore();\n\n reject(authError);\n },\n });\n });\n }, [commitLogoutMutation, defaultLogoutErrorMessage, isMutationPayload]);\n\n const combinedIsLoading =\n isLoading ||\n mutations.login.isInFlight ||\n mutations.logout.isInFlight ||\n mutations.completeMfa.isInFlight ||\n mutations.beginPasskeyLogin.isInFlight ||\n mutations.finishPasskeyLogin.isInFlight ||\n (mutations.acceptInvitation?.isInFlight ?? false) ||\n mutations.beginAuthentication.isInFlight;\n\n return {\n authMethod: authState.authMethod,\n challengeToken: authState.challengeToken,\n nextStep: authState.nextStep,\n mfaLevel: authState.mfaLevel,\n emailHint: authState.emailHint,\n login,\n loginWithPasskey,\n completeMfa,\n acceptInvitation,\n beginAuthentication,\n logout,\n reset,\n clearError,\n isLoading: combinedIsLoading,\n error,\n user,\n lockedUntil,\n availableMethods,\n };\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAuth-CheTnq60.js","names":[],"sources":["../../src/auth/login/MfaChallengeForm.tsx","../../src/modules/webauthn.ts","../../src/hooks/useAuth.ts"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n useCallback,\n useEffect,\n useState,\n type FormEvent,\n type JSX,\n} from 'react';\nimport { useBackofficeReactTranslation } from '../../i18n/useBackofficeReactTranslation.js';\n\nimport { Button, FormError, FormField } from '@plumile/ui';\n\nimport type { TotpCredentials, UseAuthReturn } from '../../hooks/useAuth.js';\n\nimport * as styles from './loginPage.css.js';\n\ntype Props = {\n auth: Pick<\n UseAuthReturn,\n 'completeMfa' | 'isLoading' | 'error' | 'emailHint' | 'reset' | 'clearError'\n >;\n onSuccess: () => void;\n onBack: () => void;\n};\n\nexport const MfaChallengeForm = ({\n auth,\n onSuccess,\n onBack,\n}: Props): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n const [code, setCode] = useState('');\n const [localError, setLocalError] = useState<string | null>(null);\n\n // Clear any stale errors when the MFA form is shown\n useEffect(() => {\n auth.clearError();\n setLocalError(null);\n }, [auth]);\n\n const handleSubmit = useCallback(\n async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setLocalError(null);\n\n const trimmed = code.trim();\n if (trimmed.length < 4) {\n setLocalError(t('auth.mfa.errors.shortCode'));\n return;\n }\n\n try {\n const credentials: TotpCredentials = {\n code: trimmed,\n };\n await auth.completeMfa(credentials);\n onSuccess();\n } catch {\n const authMessage = auth.error?.message;\n setLocalError(authMessage ?? t('auth.mfa.errors.verificationFailed'));\n }\n },\n [auth, code, onSuccess, t],\n );\n\n const helper =\n auth.emailHint != null\n ? t('auth.mfa.helper.withEmail', { email: auth.emailHint })\n : t('auth.mfa.helper.default');\n\n const formError = localError ?? auth.error?.message ?? null;\n\n return (\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n <form className={styles.formSurface} onSubmit={handleSubmit} noValidate>\n <div className={styles.stack}>\n <p className={styles.helper}>{helper}</p>\n {formError != null ? <FormError>{formError}</FormError> : null}\n <FormField\n label={t('auth.mfa.form.label')}\n name=\"code\"\n type=\"text\"\n value={code}\n onChange={(event) => {\n setCode(event.target.value);\n setLocalError(null);\n }}\n placeholder={t('auth.mfa.form.placeholder')}\n autoComplete=\"one-time-code\"\n autoFocus\n required\n />\n </div>\n <div className={styles.actionsRow}>\n <Button\n type=\"button\"\n variant=\"text\"\n size=\"small\"\n className={styles.inlineLink}\n onClick={() => {\n auth.reset();\n onBack();\n }}\n >\n {t('auth.mfa.actions.back')}\n </Button>\n <Button type=\"submit\" size=\"large\" isLoading={auth.isLoading}>\n {t('auth.mfa.actions.submit')}\n </Button>\n </div>\n </form>\n );\n};\n","/**\n * Buffer to base64 url\n */\nexport function bufferToBase64Url(input: ArrayBuffer): string {\n const byteArray = new Uint8Array(input);\n let binary = '';\n for (const byte of byteArray) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Base64 url to buffer\n */\nexport function base64UrlToBuffer(input: string): ArrayBuffer {\n const normalized = input.replace(/-/g, '+').replace(/_/g, '/');\n const remainder = normalized.length % 4;\n let padding = '';\n if (remainder === 2) {\n padding = '==';\n } else if (remainder === 3) {\n padding = '=';\n } else if (remainder === 1) {\n throw new Error('Invalid base64url input length.');\n }\n const padded = `${normalized}${padding}`;\n const binary = atob(padded);\n const output = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n output[i] = binary.charCodeAt(i);\n }\n return output.buffer;\n}\n\nexport type WebAuthnRegistrationErrorKind =\n | 'cancelled'\n | 'credentialInUse'\n | 'notSupported'\n | 'failed';\n\n/**\n * Maps a browser WebAuthn registration error to a stable UI category.\n */\nexport function mapWebAuthnRegistrationError(\n error: unknown,\n): WebAuthnRegistrationErrorKind {\n if (!(error instanceof DOMException)) {\n return 'failed';\n }\n\n switch (error.name) {\n case 'NotAllowedError':\n case 'AbortError':\n return 'cancelled';\n case 'InvalidStateError':\n return 'credentialInUse';\n case 'SecurityError':\n case 'NotSupportedError':\n return 'notSupported';\n default:\n return 'failed';\n }\n}\n\n/**\n * Parse sign count\n */\nexport function parseSignCount(authenticatorData: ArrayBuffer): number {\n if (authenticatorData.byteLength < 37) {\n return 0;\n }\n const view = new DataView(authenticatorData);\n return view.getUint32(33, false);\n}\n","/* eslint-disable no-ternary */\nimport { useCallback, useState } from 'react';\n\nimport {\n type MutationPayloadBase,\n requireField,\n resolveMutationOutcome,\n} from '../relay/mutationResult.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\n\nimport { resetRelayStore } from '../relay/environment.js';\nimport type { PayloadError } from 'relay-runtime';\n\nimport type {\n AuthMethod,\n LoginNextStep,\n MfaLevel,\n} from '../modules/sharedSchemaTypes.js';\nimport {\n base64UrlToBuffer,\n bufferToBase64Url,\n parseSignCount,\n} from '../modules/webauthn.js';\n\nexport type AuthPayload = {\n authMethod: AuthMethod | null | undefined;\n challengeToken: string | null | undefined;\n loggedInUser: { id: string } | null | undefined;\n mfaLevel: MfaLevel | null | undefined;\n nextStep: LoginNextStep | null | undefined;\n};\n\ntype LoginErrorReason =\n | 'INVALID_CREDENTIALS'\n | 'ACCOUNT_LOCKED'\n | 'RATE_LIMITED'\n | 'INTERNAL_ERROR';\n\ntype LogoutErrorReason =\n | 'UNAUTHENTICATED'\n | 'SESSION_NOT_FOUND'\n | 'INTERNAL_ERROR';\n\ntype BeginAuthenticationErrorReason = 'INVALID_EMAIL' | 'INTERNAL_ERROR';\n\ntype BeginPasskeyLoginErrorReason =\n | 'INVALID_EMAIL'\n | 'PASSKEY_NOT_FOUND'\n | 'PASSKEY_NOT_SUPPORTED'\n | 'INTERNAL_ERROR';\n\ntype FinishPasskeyLoginErrorReason =\n | 'INVALID_CHALLENGE_TOKEN'\n | 'CHALLENGE_EXPIRED'\n | 'INVALID_ASSERTION'\n | 'INTERNAL_ERROR';\n\ntype CompleteMfaErrorReason =\n | 'INVALID_CHALLENGE_TOKEN'\n | 'CHALLENGE_EXPIRED'\n | 'INVALID_CODE'\n | 'TOO_MANY_ATTEMPTS'\n | 'INTERNAL_ERROR';\n\ntype AcceptInvitationErrorReason =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'ALREADY_ACCEPTED'\n | 'PASSWORD_MISMATCH'\n | 'PASSWORD_POLICY_VIOLATION'\n | 'RATE_LIMITED'\n | 'EMAIL_MISMATCH'\n | 'INTERNAL_ERROR';\n\nexport type BeginAuthenticationPayload =\n MutationPayloadBase<BeginAuthenticationErrorReason> & {\n lockedUntil: string | null | undefined;\n methods: readonly {\n method: AuthMethod;\n mfaEnforced?: boolean | null | undefined;\n }[];\n };\n\nexport type BeginPasskeyLoginPayload =\n MutationPayloadBase<BeginPasskeyLoginErrorReason> & {\n allowCredentials: readonly string[];\n challenge: string;\n challengeToken: string;\n rpId: string;\n };\n\ntype LoginMutationPayload = MutationPayloadBase<LoginErrorReason> & {\n payload?: AuthPayload | null | undefined;\n};\n\ntype LogoutPayload = {\n loggedOut?: boolean | null | undefined;\n};\n\ntype LogoutMutationPayload = MutationPayloadBase<LogoutErrorReason> & {\n payload?: LogoutPayload | null | undefined;\n};\n\ntype CompleteMfaMutationPayload =\n MutationPayloadBase<CompleteMfaErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\ntype FinishPasskeyLoginMutationPayload =\n MutationPayloadBase<FinishPasskeyLoginErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\ntype AcceptInvitationMutationPayload =\n MutationPayloadBase<AcceptInvitationErrorReason> & {\n payload?: AuthPayload | null | undefined;\n };\n\nexport type LoginResponse = { login: AuthPayload | LoginMutationPayload };\nexport type LogoutResponse = { logout: LogoutPayload | LogoutMutationPayload };\nexport type CompleteMfaResponse = {\n completeMfa: AuthPayload | CompleteMfaMutationPayload;\n};\nexport type FinishPasskeyLoginResponse = {\n finishPasskeyLogin: AuthPayload | FinishPasskeyLoginMutationPayload;\n};\nexport type AcceptInvitationResponse = {\n acceptInvitation: AuthPayload | AcceptInvitationMutationPayload;\n};\nexport type BeginAuthenticationResponse = {\n beginAuthentication: BeginAuthenticationPayload;\n};\nexport type BeginPasskeyLoginResponse = {\n beginPasskeyLogin: BeginPasskeyLoginPayload;\n};\n\nexport type LoginVariables = {\n input: LoginCredentials;\n};\n\nexport type LogoutVariables = Record<PropertyKey, never>;\n\nexport type CompleteMfaVariables = {\n input: {\n challengeToken: string;\n code: string;\n };\n};\n\nexport type BeginPasskeyLoginVariables = {\n email: string;\n};\n\nexport type FinishPasskeyLoginVariables = {\n input: {\n challenge: string;\n challengeToken: string;\n credentialId: string;\n signCount: number;\n userHandle?: string | null;\n };\n};\n\nexport type AcceptInvitationVariables = {\n input: {\n token: string;\n password: string;\n passwordConfirmation: string;\n };\n};\n\nexport type BeginAuthenticationVariables = {\n email: string;\n};\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\ntype MutationCommit<TVariables, TResponse> = (\n config: MutationCommitConfig<TVariables, TResponse>,\n) => void;\n\ntype MutationEntry<TVariables, TResponse> = {\n commit: MutationCommit<TVariables, TResponse>;\n isInFlight: boolean;\n};\n\nexport type AuthMutationHooks = {\n login: MutationEntry<LoginVariables, LoginResponse>;\n logout: MutationEntry<LogoutVariables, LogoutResponse>;\n completeMfa: MutationEntry<CompleteMfaVariables, CompleteMfaResponse>;\n beginPasskeyLogin: MutationEntry<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >;\n finishPasskeyLogin: MutationEntry<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >;\n acceptInvitation?: MutationEntry<\n AcceptInvitationVariables,\n AcceptInvitationResponse\n >;\n beginAuthentication: MutationEntry<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >;\n};\n\ninterface User {\n id: string;\n}\n\nexport type LoginStatus = 'success' | 'mfa-required' | 'error';\n\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\nexport interface TotpCredentials {\n code: string;\n}\n\nexport interface AcceptInvitationCredentials {\n token: string;\n password: string;\n passwordConfirmation: string;\n}\n\nexport interface AuthError {\n message: string;\n code?: string;\n}\n\nexport interface UseAuthReturn {\n authMethod: AuthMethod | null;\n challengeToken: string | null;\n nextStep: LoginNextStep | null;\n mfaLevel: MfaLevel | null;\n emailHint: string | null;\n lockedUntil: string | null;\n availableMethods: AuthMethod[];\n login: (credentials: LoginCredentials) => Promise<LoginStatus>;\n loginWithPasskey: (params: { email: string }) => Promise<LoginStatus>;\n completeMfa: (credentials: TotpCredentials) => Promise<void>;\n acceptInvitation: (\n credentials: AcceptInvitationCredentials,\n ) => Promise<LoginStatus>;\n beginAuthentication: (\n email: string,\n ) => Promise<{ methods: AuthMethod[]; lockedUntil: string | null }>;\n logout: () => Promise<void>;\n reset: () => void;\n clearError: () => void;\n isLoading: boolean;\n error: AuthError | null;\n user: User | null;\n}\n\nconst initialState = {\n authMethod: null as AuthMethod | null,\n challengeToken: null as string | null,\n emailHint: null as string | null,\n mfaLevel: null as MfaLevel | null,\n nextStep: null as LoginNextStep | null,\n};\n\nexport const createUseAuth = (mutations: AuthMutationHooks) => {\n return (): UseAuthReturn => {\n const { t } = useBackofficeReactTranslation();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n const [user, setUser] = useState<User | null>(null);\n const [lockedUntil, setLockedUntil] = useState<string | null>(null);\n const [availableMethods, setAvailableMethods] = useState<AuthMethod[]>([]);\n const [authState, setAuthState] = useState(initialState);\n\n const commitLoginMutation = mutations.login.commit;\n const commitLogoutMutation = mutations.logout.commit;\n const commitCompleteMfaMutation = mutations.completeMfa.commit;\n const commitBeginPasskeyLoginMutation = mutations.beginPasskeyLogin.commit;\n const commitFinishPasskeyLoginMutation =\n mutations.finishPasskeyLogin.commit;\n const commitAcceptInvitationMutation = mutations.acceptInvitation?.commit;\n const commitBeginAuthenticationMutation =\n mutations.beginAuthentication.commit;\n\n const defaultLoginErrorMessage = t('auth.loginFlow.errors.tryAgain');\n const defaultBeginAuthenticationErrorMessage = t(\n 'auth.loginFlow.errors.tryAgain',\n );\n const defaultPasskeyErrorMessage = t('auth.passkey.errors.failed');\n const defaultMfaErrorMessage = t('auth.mfa.errors.verificationFailed');\n const defaultInvitationErrorMessage = t(\n 'auth.acceptInvitation.errors.default',\n );\n const mfaInvalidChallengeMessage = t('auth.mfa.errors.invalidChallenge');\n const passkeyNotAvailableMessage = t('auth.passkey.errors.notAvailable');\n const defaultLogoutErrorMessage = 'Logout failed.';\n\n const reset = useCallback(() => {\n setError(null);\n setUser(null);\n setLockedUntil(null);\n setAvailableMethods([]);\n setAuthState(initialState);\n }, []);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n const updateAuthStateFromPayload = useCallback(\n (payload: AuthPayload): LoginStatus => {\n const authMethod = payload.authMethod ?? null;\n const challengeToken = payload.challengeToken ?? null;\n const mfaLevel = payload.mfaLevel ?? null;\n const nextStep = payload.nextStep ?? null;\n\n setAuthState((prev) => {\n return {\n ...prev,\n authMethod,\n challengeToken,\n mfaLevel,\n nextStep,\n };\n });\n\n if (payload.loggedInUser != null && nextStep == null) {\n setUser({\n id: payload.loggedInUser.id,\n });\n return 'success';\n }\n\n if (nextStep === 'TOTP' && challengeToken != null) {\n return 'mfa-required';\n }\n\n return 'error';\n },\n [],\n );\n\n const isMutationPayload = useCallback(\n (value: unknown): value is MutationPayloadBase => {\n return (\n value != null &&\n typeof value === 'object' &&\n ('status' in value || 'result' in value)\n );\n },\n [],\n );\n\n const mapLoginReason = useCallback(\n (reason: LoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CREDENTIALS':\n return t('auth.loginFlow.errors.invalidCredentials');\n case 'ACCOUNT_LOCKED':\n return t('auth.loginFlow.errors.accountLocked');\n case 'RATE_LIMITED':\n return t('auth.loginFlow.errors.rateLimited');\n case 'INTERNAL_ERROR':\n return t('auth.loginFlow.errors.tryAgain');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapBeginAuthenticationReason = useCallback(\n (reason: BeginAuthenticationErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_EMAIL':\n return t('auth.loginFlow.errors.invalidEmail');\n case 'INTERNAL_ERROR':\n return t('auth.loginFlow.errors.tryAgain');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapBeginPasskeyLoginReason = useCallback(\n (reason: BeginPasskeyLoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_EMAIL':\n return t('auth.passkey.errors.invalidEmail');\n case 'PASSKEY_NOT_FOUND':\n return t('auth.passkey.errors.notFound');\n case 'PASSKEY_NOT_SUPPORTED':\n return t('auth.passkey.errors.notAvailable');\n case 'INTERNAL_ERROR':\n return t('auth.passkey.errors.failed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapFinishPasskeyLoginReason = useCallback(\n (reason: FinishPasskeyLoginErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CHALLENGE_TOKEN':\n return t('auth.passkey.errors.invalidChallenge');\n case 'CHALLENGE_EXPIRED':\n return t('auth.passkey.errors.challengeExpired');\n case 'INVALID_ASSERTION':\n return t('auth.passkey.errors.invalidAssertion');\n case 'INTERNAL_ERROR':\n return t('auth.passkey.errors.failed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapCompleteMfaReason = useCallback(\n (reason: CompleteMfaErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_CHALLENGE_TOKEN':\n return t('auth.mfa.errors.invalidChallenge');\n case 'CHALLENGE_EXPIRED':\n return t('auth.mfa.errors.expired');\n case 'INVALID_CODE':\n return t('auth.mfa.errors.invalidCode');\n case 'TOO_MANY_ATTEMPTS':\n return t('auth.mfa.errors.tooManyAttempts');\n case 'INTERNAL_ERROR':\n return t('auth.mfa.errors.verificationFailed');\n default:\n return null;\n }\n },\n [t],\n );\n\n const mapAcceptInvitationReason = useCallback(\n (reason: AcceptInvitationErrorReason): string | null => {\n switch (reason) {\n case 'INVALID_TOKEN':\n return t('auth.acceptInvitation.errors.invalidToken');\n case 'TOKEN_EXPIRED':\n return t('auth.acceptInvitation.errors.expired');\n case 'ALREADY_ACCEPTED':\n return t('auth.acceptInvitation.errors.alreadyAccepted');\n case 'PASSWORD_MISMATCH':\n return t('auth.acceptInvitation.errors.passwordMismatch');\n case 'PASSWORD_POLICY_VIOLATION':\n return t('auth.acceptInvitation.errors.passwordPolicyViolation');\n case 'RATE_LIMITED':\n return t('auth.acceptInvitation.errors.rateLimited');\n case 'EMAIL_MISMATCH':\n return t('auth.acceptInvitation.errors.emailMismatch');\n case 'INTERNAL_ERROR':\n return t('auth.acceptInvitation.errors.default');\n default:\n return null;\n }\n },\n [t],\n );\n\n const beginAuthentication = useCallback(\n async (\n email: string,\n ): Promise<{ methods: AuthMethod[]; lockedUntil: string | null }> => {\n return new Promise((resolve, reject) => {\n commitBeginAuthenticationMutation({\n variables: { email },\n onCompleted: (response) => {\n const rawPayload = response.beginAuthentication;\n let payload = rawPayload;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultBeginAuthenticationErrorMessage,\n mapReason: mapBeginAuthenticationReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n payload = outcome.payload;\n }\n\n const methods = payload.methods.map((item) => {\n return item.method;\n });\n const locked = payload.lockedUntil ?? null;\n setAvailableMethods(methods);\n setLockedUntil(locked);\n resolve({ methods, lockedUntil: locked });\n },\n onError: () => {\n const authError: AuthError = {\n message: defaultBeginAuthenticationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitBeginAuthenticationMutation,\n defaultBeginAuthenticationErrorMessage,\n isMutationPayload,\n mapBeginAuthenticationReason,\n ],\n );\n\n const login = useCallback(\n async (credentials: LoginCredentials): Promise<LoginStatus> => {\n setIsLoading(true);\n setError(null);\n setAuthState((prev) => {\n return {\n ...prev,\n emailHint: credentials.email,\n };\n });\n\n return new Promise((resolve, reject) => {\n commitLoginMutation({\n variables: {\n input: credentials,\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.login;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultLoginErrorMessage,\n mapReason: mapLoginReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success' || status === 'mfa-required') {\n resolve(status);\n return;\n }\n\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultLoginErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitLoginMutation,\n defaultLoginErrorMessage,\n isMutationPayload,\n mapLoginReason,\n updateAuthStateFromPayload,\n ],\n );\n\n const completeMfa = useCallback(\n async (credentials: TotpCredentials): Promise<void> => {\n const { challengeToken } = authState;\n if (challengeToken == null) {\n const authError: AuthError = {\n message: mfaInvalidChallengeMessage,\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise((resolve, reject) => {\n commitCompleteMfaMutation({\n variables: {\n input: {\n challengeToken,\n code: credentials.code,\n },\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.completeMfa;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultMfaErrorMessage,\n mapReason: mapCompleteMfaReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success') {\n resolve();\n return;\n }\n\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultMfaErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n authState,\n commitCompleteMfaMutation,\n defaultMfaErrorMessage,\n isMutationPayload,\n mapCompleteMfaReason,\n mfaInvalidChallengeMessage,\n updateAuthStateFromPayload,\n ],\n );\n\n const loginWithPasskey = useCallback(\n async ({ email }: { email: string }): Promise<LoginStatus> => {\n if (typeof window === 'undefined') {\n const authError: AuthError = {\n message: passkeyNotAvailableMessage,\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n setAuthState((prev) => {\n return {\n ...prev,\n emailHint: email,\n };\n });\n\n return new Promise((resolve, reject) => {\n commitBeginPasskeyLoginMutation({\n variables: {\n email,\n },\n onCompleted: (response) => {\n const rawOptions = response.beginPasskeyLogin;\n let options = rawOptions;\n\n if (isMutationPayload(rawOptions)) {\n const outcome = resolveMutationOutcome(rawOptions, {\n defaultErrorMessage: defaultPasskeyErrorMessage,\n mapReason: mapBeginPasskeyLoginReason,\n });\n if (!outcome.ok) {\n setIsLoading(false);\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n options = outcome.payload;\n }\n\n const continuePasskeyLogin = async (): Promise<void> => {\n try {\n const assertion = (await navigator.credentials.get({\n publicKey: {\n allowCredentials: options.allowCredentials.map(\n (credentialId) => {\n return {\n id: base64UrlToBuffer(credentialId),\n type: 'public-key' as const,\n };\n },\n ),\n challenge: base64UrlToBuffer(options.challenge),\n rpId: options.rpId,\n userVerification: 'preferred',\n },\n })) as PublicKeyCredential | null;\n\n if (assertion == null) {\n throw new Error(\n 'No credential returned by the authenticator.',\n );\n }\n\n const assertionResponse =\n assertion.response as AuthenticatorAssertionResponse;\n const signCount = parseSignCount(\n assertionResponse.authenticatorData,\n );\n\n commitFinishPasskeyLoginMutation({\n variables: {\n input: {\n challenge: options.challenge,\n challengeToken: options.challengeToken,\n credentialId: assertion.id,\n signCount,\n userHandle:\n assertionResponse.userHandle != null\n ? bufferToBase64Url(assertionResponse.userHandle)\n : null,\n },\n },\n onCompleted: (finishResponse) => {\n setIsLoading(false);\n const rawPayload = finishResponse.finishPasskeyLogin;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultPasskeyErrorMessage,\n mapReason: mapFinishPasskeyLoginReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success') {\n resolve(status);\n return;\n }\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n } catch (credentialError) {\n setIsLoading(false);\n const authError: AuthError = {\n message:\n credentialError instanceof Error\n ? credentialError.message\n : 'Passkey login was cancelled.',\n };\n setError(authError);\n reject(authError);\n }\n };\n\n continuePasskeyLogin().catch(() => {\n return undefined;\n });\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultPasskeyErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitBeginPasskeyLoginMutation,\n commitFinishPasskeyLoginMutation,\n defaultPasskeyErrorMessage,\n isMutationPayload,\n mapBeginPasskeyLoginReason,\n mapFinishPasskeyLoginReason,\n passkeyNotAvailableMessage,\n updateAuthStateFromPayload,\n ],\n );\n\n const acceptInvitation = useCallback(\n async (\n credentials: AcceptInvitationCredentials,\n ): Promise<LoginStatus> => {\n if (commitAcceptInvitationMutation == null) {\n const authError: AuthError = {\n message: 'Invitation acceptance is not available.',\n };\n setError(authError);\n return Promise.reject(authError);\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise((resolve, reject) => {\n commitAcceptInvitationMutation({\n variables: {\n input: {\n token: credentials.token,\n password: credentials.password,\n passwordConfirmation: credentials.passwordConfirmation,\n },\n },\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.acceptInvitation;\n let authPayload: AuthPayload | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultInvitationErrorMessage,\n mapReason: mapAcceptInvitationReason,\n });\n if (!outcome.ok) {\n const authError: AuthError = {\n message: outcome.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n authPayload = rawPayload.payload ?? null;\n } else {\n authPayload = rawPayload;\n }\n\n if (authPayload == null) {\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n const status = updateAuthStateFromPayload(authPayload);\n if (status === 'success' || status === 'mfa-required') {\n resolve(status);\n return;\n }\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultInvitationErrorMessage,\n };\n setError(authError);\n reject(authError);\n },\n });\n });\n },\n [\n commitAcceptInvitationMutation,\n defaultInvitationErrorMessage,\n isMutationPayload,\n mapAcceptInvitationReason,\n updateAuthStateFromPayload,\n ],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n setIsLoading(true);\n\n return new Promise((resolve, reject) => {\n commitLogoutMutation({\n variables: {},\n onCompleted: (response) => {\n setIsLoading(false);\n const rawPayload = response.logout;\n let loggedOutValue: boolean | null = null;\n\n if (isMutationPayload(rawPayload)) {\n const outcome = resolveMutationOutcome(rawPayload, {\n defaultErrorMessage: defaultLogoutErrorMessage,\n });\n if (!outcome.ok) {\n const authError: AuthError = { message: outcome.message };\n setError(authError);\n reject(authError);\n return;\n }\n\n const loggedOutResult = requireField(\n rawPayload.payload?.loggedOut ?? null,\n defaultLogoutErrorMessage,\n );\n if (!loggedOutResult.ok) {\n const authError: AuthError = {\n message: loggedOutResult.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n loggedOutValue = loggedOutResult.value;\n } else {\n const loggedOutResult = requireField(\n rawPayload.loggedOut ?? null,\n defaultLogoutErrorMessage,\n );\n if (!loggedOutResult.ok) {\n const authError: AuthError = {\n message: loggedOutResult.message,\n };\n setError(authError);\n reject(authError);\n return;\n }\n loggedOutValue = loggedOutResult.value;\n }\n\n if (!loggedOutValue) {\n const authError: AuthError = {\n message: defaultLogoutErrorMessage,\n };\n setError(authError);\n reject(authError);\n return;\n }\n\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n setUser(null);\n setAuthState(initialState);\n resetRelayStore();\n\n resolve();\n },\n onError: () => {\n setIsLoading(false);\n const authError: AuthError = {\n message: defaultLogoutErrorMessage,\n };\n setError(authError);\n resetRelayStore();\n\n reject(authError);\n },\n });\n });\n }, [commitLogoutMutation, defaultLogoutErrorMessage, isMutationPayload]);\n\n const combinedIsLoading =\n isLoading ||\n mutations.login.isInFlight ||\n mutations.logout.isInFlight ||\n mutations.completeMfa.isInFlight ||\n mutations.beginPasskeyLogin.isInFlight ||\n mutations.finishPasskeyLogin.isInFlight ||\n (mutations.acceptInvitation?.isInFlight ?? false) ||\n mutations.beginAuthentication.isInFlight;\n\n return {\n authMethod: authState.authMethod,\n challengeToken: authState.challengeToken,\n nextStep: authState.nextStep,\n mfaLevel: authState.mfaLevel,\n emailHint: authState.emailHint,\n login,\n loginWithPasskey,\n completeMfa,\n acceptInvitation,\n beginAuthentication,\n logout,\n reset,\n clearError,\n isLoading: combinedIsLoading,\n error,\n user,\n lockedUntil,\n availableMethods,\n };\n };\n};\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./useRelayEnvironment-vQ86aW-n.js";
2
2
  import { r as t } from "./useBackofficeReactTranslation-Btt58EIo.js";
3
- import { t as n } from "./useAuth-BdSNpGqe.js";
3
+ import { t as n } from "./useAuth-CheTnq60.js";
4
4
  import { useCallback as r, useMemo as i, useState as a } from "react";
5
5
  import * as o from "react-relay";
6
6
  //#region src/hooks/useBackofficeAuth.ts
@@ -86,4 +86,4 @@ function d() {
86
86
  //#endregion
87
87
  export { d as t };
88
88
 
89
- //# sourceMappingURL=useBackofficeAuth-C16Euw2X.js.map
89
+ //# sourceMappingURL=useBackofficeAuth-ers1FUGe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBackofficeAuth-C16Euw2X.js","names":[],"sources":["../../src/hooks/useBackofficeAuth.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { GraphQLTaggedNode, PayloadError } from 'relay-runtime';\n\nimport {\n createUseAuth,\n type UseAuthReturn,\n type AcceptInvitationResponse,\n type AcceptInvitationVariables,\n type BeginAuthenticationResponse,\n type BeginAuthenticationVariables,\n type BeginPasskeyLoginResponse,\n type BeginPasskeyLoginVariables,\n type CompleteMfaResponse,\n type CompleteMfaVariables,\n type FinishPasskeyLoginResponse,\n type FinishPasskeyLoginVariables,\n type LoginResponse,\n type LoginVariables,\n type LogoutResponse,\n type LogoutVariables,\n} from './useAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { BackofficeLazyValue } from '../provider/lazyValue.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\n\nconst { commitMutation } = ReactRelay;\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\nconst toMutationLoadError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n return new Error('Unable to load auth mutation.');\n};\n\nconst useDeferredMutation = <TVariables extends object, TResponse>(\n loadMutation: () => Promise<GraphQLTaggedNode | null>,\n) => {\n const relayEnvironment = useRelayEnvironment();\n const [inFlightCount, setInFlightCount] = useState(0);\n\n const commit = useCallback(\n (config: MutationCommitConfig<TVariables, TResponse>) => {\n setInFlightCount((count) => {\n return count + 1;\n });\n\n const finish = () => {\n setInFlightCount((count) => {\n return Math.max(0, count - 1);\n });\n };\n\n loadMutation()\n .then((mutation) => {\n if (mutation == null) {\n throw new Error('Missing auth mutation config.');\n }\n\n commitMutation(relayEnvironment, {\n mutation,\n variables: config.variables,\n onCompleted: (response, errors) => {\n finish();\n config.onCompleted?.(response as TResponse, errors ?? null);\n },\n onError: (error) => {\n finish();\n config.onError?.(error);\n },\n });\n })\n .catch((error: unknown) => {\n finish();\n config.onError?.(toMutationLoadError(error));\n });\n },\n [loadMutation, relayEnvironment],\n );\n\n return {\n commit,\n isInFlight: inFlightCount > 0,\n };\n};\n\nconst loadOptionalMutation = async <TConfig>(\n eagerMutation: GraphQLTaggedNode | null | undefined,\n lazyConfig: BackofficeLazyValue<TConfig> | null | undefined,\n selectMutation: (config: TConfig) => GraphQLTaggedNode,\n): Promise<GraphQLTaggedNode | null> => {\n if (eagerMutation != null) {\n return eagerMutation;\n }\n if (lazyConfig == null) {\n return null;\n }\n const loadedConfig = await lazyConfig.load();\n return selectMutation(loadedConfig);\n};\n\n/**\n * Provides auth actions/state backed by Relay mutations from BackofficeProvider.\n */\nexport function useBackofficeAuth(): UseAuthReturn {\n const { auth: authConfig } = useBackofficeConfig();\n const { commit: commitLogin, isInFlight: isLoginInFlight } =\n useDeferredMutation<LoginVariables, LoginResponse>(\n useCallback(async () => {\n const loginConfig = authConfig.login.get();\n return loadOptionalMutation(\n loginConfig?.loginMutation,\n authConfig.login,\n (config) => {\n return config.loginMutation;\n },\n );\n }, [authConfig.login]),\n );\n const { commit: commitLogout, isInFlight: isLogoutInFlight } =\n useDeferredMutation<LogoutVariables, LogoutResponse>(\n useCallback(async () => {\n const logoutConfig = await authConfig.logout.load();\n return logoutConfig.logoutMutation;\n }, [authConfig.logout]),\n );\n const { commit: commitCompleteMfa, isInFlight: isCompleteMfaInFlight } =\n useDeferredMutation<CompleteMfaVariables, CompleteMfaResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.completeMfaMutation,\n authConfig.completeMfa,\n (config) => {\n return config.completeMfaMutation;\n },\n );\n }, [authConfig.completeMfa, authConfig.login]),\n );\n const {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n } = useDeferredMutation<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.beginPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n } = useDeferredMutation<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.finishPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.finishPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n } = useDeferredMutation<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginAuthenticationMutation,\n authConfig.authentication,\n (config) => {\n return config.beginAuthenticationMutation;\n },\n );\n }, [authConfig.authentication, authConfig.login]),\n );\n const {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n } = useDeferredMutation<AcceptInvitationVariables, AcceptInvitationResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.acceptInvitationMutation,\n authConfig.acceptInvitation,\n (config) => {\n return config.acceptInvitationMutation;\n },\n );\n }, [authConfig.acceptInvitation, authConfig.login]),\n );\n const hasAcceptInvitationMutation =\n authConfig.login.get()?.acceptInvitationMutation != null ||\n authConfig.acceptInvitation != null;\n\n const useAuthWithMutations = useMemo(() => {\n let acceptInvitation:\n | {\n commit: typeof commitAcceptInvitation;\n isInFlight: boolean;\n }\n | undefined;\n if (hasAcceptInvitationMutation) {\n acceptInvitation = {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n };\n }\n return createUseAuth({\n login: { commit: commitLogin, isInFlight: isLoginInFlight },\n logout: { commit: commitLogout, isInFlight: isLogoutInFlight },\n completeMfa: {\n commit: commitCompleteMfa,\n isInFlight: isCompleteMfaInFlight,\n },\n beginPasskeyLogin: {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n },\n finishPasskeyLogin: {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n },\n beginAuthentication: {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n },\n acceptInvitation,\n });\n }, [\n commitAcceptInvitation,\n commitBeginAuthentication,\n commitBeginPasskeyLogin,\n commitCompleteMfa,\n commitFinishPasskeyLogin,\n commitLogin,\n commitLogout,\n hasAcceptInvitationMutation,\n isAcceptInvitationInFlight,\n isBeginAuthenticationInFlight,\n isBeginPasskeyLoginInFlight,\n isCompleteMfaInFlight,\n isFinishPasskeyLoginInFlight,\n isLoginInFlight,\n isLogoutInFlight,\n ]);\n\n return useAuthWithMutations();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useBackofficeAuth-ers1FUGe.js","names":[],"sources":["../../src/hooks/useBackofficeAuth.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { GraphQLTaggedNode, PayloadError } from 'relay-runtime';\n\nimport {\n createUseAuth,\n type UseAuthReturn,\n type AcceptInvitationResponse,\n type AcceptInvitationVariables,\n type BeginAuthenticationResponse,\n type BeginAuthenticationVariables,\n type BeginPasskeyLoginResponse,\n type BeginPasskeyLoginVariables,\n type CompleteMfaResponse,\n type CompleteMfaVariables,\n type FinishPasskeyLoginResponse,\n type FinishPasskeyLoginVariables,\n type LoginResponse,\n type LoginVariables,\n type LogoutResponse,\n type LogoutVariables,\n} from './useAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { BackofficeLazyValue } from '../provider/lazyValue.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\n\nconst { commitMutation } = ReactRelay;\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\nconst toMutationLoadError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n return new Error('Unable to load auth mutation.');\n};\n\nconst useDeferredMutation = <TVariables extends object, TResponse>(\n loadMutation: () => Promise<GraphQLTaggedNode | null>,\n) => {\n const relayEnvironment = useRelayEnvironment();\n const [inFlightCount, setInFlightCount] = useState(0);\n\n const commit = useCallback(\n (config: MutationCommitConfig<TVariables, TResponse>) => {\n setInFlightCount((count) => {\n return count + 1;\n });\n\n const finish = () => {\n setInFlightCount((count) => {\n return Math.max(0, count - 1);\n });\n };\n\n loadMutation()\n .then((mutation) => {\n if (mutation == null) {\n throw new Error('Missing auth mutation config.');\n }\n\n commitMutation(relayEnvironment, {\n mutation,\n variables: config.variables,\n onCompleted: (response, errors) => {\n finish();\n config.onCompleted?.(response as TResponse, errors ?? null);\n },\n onError: (error) => {\n finish();\n config.onError?.(error);\n },\n });\n })\n .catch((error: unknown) => {\n finish();\n config.onError?.(toMutationLoadError(error));\n });\n },\n [loadMutation, relayEnvironment],\n );\n\n return {\n commit,\n isInFlight: inFlightCount > 0,\n };\n};\n\nconst loadOptionalMutation = async <TConfig>(\n eagerMutation: GraphQLTaggedNode | null | undefined,\n lazyConfig: BackofficeLazyValue<TConfig> | null | undefined,\n selectMutation: (config: TConfig) => GraphQLTaggedNode,\n): Promise<GraphQLTaggedNode | null> => {\n if (eagerMutation != null) {\n return eagerMutation;\n }\n if (lazyConfig == null) {\n return null;\n }\n const loadedConfig = await lazyConfig.load();\n return selectMutation(loadedConfig);\n};\n\n/**\n * Provides auth actions/state backed by Relay mutations from BackofficeProvider.\n */\nexport function useBackofficeAuth(): UseAuthReturn {\n const { auth: authConfig } = useBackofficeConfig();\n const { commit: commitLogin, isInFlight: isLoginInFlight } =\n useDeferredMutation<LoginVariables, LoginResponse>(\n useCallback(async () => {\n const loginConfig = authConfig.login.get();\n return loadOptionalMutation(\n loginConfig?.loginMutation,\n authConfig.login,\n (config) => {\n return config.loginMutation;\n },\n );\n }, [authConfig.login]),\n );\n const { commit: commitLogout, isInFlight: isLogoutInFlight } =\n useDeferredMutation<LogoutVariables, LogoutResponse>(\n useCallback(async () => {\n const logoutConfig = await authConfig.logout.load();\n return logoutConfig.logoutMutation;\n }, [authConfig.logout]),\n );\n const { commit: commitCompleteMfa, isInFlight: isCompleteMfaInFlight } =\n useDeferredMutation<CompleteMfaVariables, CompleteMfaResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.completeMfaMutation,\n authConfig.completeMfa,\n (config) => {\n return config.completeMfaMutation;\n },\n );\n }, [authConfig.completeMfa, authConfig.login]),\n );\n const {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n } = useDeferredMutation<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.beginPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n } = useDeferredMutation<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.finishPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.finishPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n } = useDeferredMutation<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginAuthenticationMutation,\n authConfig.authentication,\n (config) => {\n return config.beginAuthenticationMutation;\n },\n );\n }, [authConfig.authentication, authConfig.login]),\n );\n const {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n } = useDeferredMutation<AcceptInvitationVariables, AcceptInvitationResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.acceptInvitationMutation,\n authConfig.acceptInvitation,\n (config) => {\n return config.acceptInvitationMutation;\n },\n );\n }, [authConfig.acceptInvitation, authConfig.login]),\n );\n const hasAcceptInvitationMutation =\n authConfig.login.get()?.acceptInvitationMutation != null ||\n authConfig.acceptInvitation != null;\n\n const useAuthWithMutations = useMemo(() => {\n let acceptInvitation:\n | {\n commit: typeof commitAcceptInvitation;\n isInFlight: boolean;\n }\n | undefined;\n if (hasAcceptInvitationMutation) {\n acceptInvitation = {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n };\n }\n return createUseAuth({\n login: { commit: commitLogin, isInFlight: isLoginInFlight },\n logout: { commit: commitLogout, isInFlight: isLogoutInFlight },\n completeMfa: {\n commit: commitCompleteMfa,\n isInFlight: isCompleteMfaInFlight,\n },\n beginPasskeyLogin: {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n },\n finishPasskeyLogin: {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n },\n beginAuthentication: {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n },\n acceptInvitation,\n });\n }, [\n commitAcceptInvitation,\n commitBeginAuthentication,\n commitBeginPasskeyLogin,\n commitCompleteMfa,\n commitFinishPasskeyLogin,\n commitLogin,\n commitLogout,\n hasAcceptInvitationMutation,\n isAcceptInvitationInFlight,\n isBeginAuthenticationInFlight,\n isBeginPasskeyLoginInFlight,\n isCompleteMfaInFlight,\n isFinishPasskeyLoginInFlight,\n isLoginInFlight,\n isLogoutInFlight,\n ]);\n\n return useAuthWithMutations();\n}\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ type ConditionalOptions<T extends OperationType> = {
6
6
  };
7
7
  type UseConditionalSubscriptionReturn = {
8
8
  active: boolean;
9
+ completed: boolean;
9
10
  error: Error | null;
10
11
  };
11
12
  export declare function useConditionalSubscription<T extends OperationType>(config: GraphQLSubscriptionConfig<T>, options: ConditionalOptions<T>): UseConditionalSubscriptionReturn;
@@ -1 +1 @@
1
- {"version":3,"file":"useConditionalSubscription.d.ts","sourceRoot":"","sources":["../../../src/hooks/useConditionalSubscription.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9E,KAAK,kBAAkB,CAAC,CAAC,SAAS,aAAa,IAAI;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;CACrC,CAAC;AAEF,KAAK,gCAAgC,GAAG;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAkBF,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,aAAa,EAChE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,EACpC,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,gCAAgC,CAoFlC"}
1
+ {"version":3,"file":"useConditionalSubscription.d.ts","sourceRoot":"","sources":["../../../src/hooks/useConditionalSubscription.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAO9E,KAAK,kBAAkB,CAAC,CAAC,SAAS,aAAa,IAAI;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;CACrC,CAAC;AAEF,KAAK,gCAAgC,GAAG;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAkBF,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,aAAa,EAChE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,EACpC,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,gCAAgC,CAyGlC"}
@@ -1,3 +1,4 @@
1
+ import type { Resource } from 'i18next';
1
2
  export declare const backofficeReactI18nResources: {
2
3
  readonly en: {
3
4
  readonly backofficeReact: {
@@ -797,4 +798,5 @@ export declare const backofficeReactI18nResources: {
797
798
  };
798
799
  };
799
800
  export type BackofficeReactI18nResources = typeof backofficeReactI18nResources;
801
+ export declare function withBackofficeReactI18nResources(appResources?: Resource): Resource;
800
802
  //# sourceMappingURL=resources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/i18n/resources.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG/B,CAAC;AAEX,MAAM,MAAM,4BAA4B,GAAG,OAAO,4BAA4B,CAAC"}
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/i18n/resources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,SAAS,CAAC;AAI1D,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG/B,CAAC;AAEX,MAAM,MAAM,4BAA4B,GAAG,OAAO,4BAA4B,CAAC;AAsB/E,wBAAgB,gCAAgC,CAC9C,YAAY,GAAE,QAAa,GAC1B,QAAQ,CAsBV"}
@@ -28,7 +28,7 @@ export { useConditionalSubscription } from './hooks/useConditionalSubscription.j
28
28
  export { useCopyToClipboard } from './hooks/useCopyToClipboard.js';
29
29
  export { useRefetchNeededReload } from './hooks/useRefetchNeededReload.js';
30
30
  export { createI18nInstance } from './i18n/createI18nInstance.js';
31
- export { backofficeReactI18nResources } from './i18n/resources.js';
31
+ export { backofficeReactI18nResources, withBackofficeReactI18nResources, } from './i18n/resources.js';
32
32
  export { useReviewStatusLabel } from './i18n/useReviewStatusLabel.js';
33
33
  export { decodeBase64ToUtf8, encodeUtf8ToBase64 } from './modules/base64.js';
34
34
  export { formatFileSize } from './modules/formatFileSize.js';
@@ -39,7 +39,7 @@ export { BackofficeRightPageLayout } from './components/backoffice/layout/breadc
39
39
  export { EntityIdPickerDialog } from './components/backoffice/pickers/EntityIdPickerDialog.js';
40
40
  export { createInlineDataReader } from './relay/createInlineReader.js';
41
41
  export { RelayProvider } from './relay/RelayProvider.js';
42
- export { configureRelayEnvironment, getEnvironment, getNetwork, resetRelayStore, } from './relay/environment.js';
42
+ export { configureRelayEnvironment, getEnvironment, getNetwork, getRelayTransportSnapshot, reconnectRelayWebSocket, resetRelayStore, subscribeRelayTransport, type RelayReconnectOptions, type RelayTransportSnapshot, type RelayTransportStatus, } from './relay/environment.js';
43
43
  export { identityView } from './relay/identityView.js';
44
44
  export { requireField, requireLinkedRecordId, resolveAgentStartOutcome, resolveMutationOutcome, } from './relay/mutationResult.js';
45
45
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,YAAY,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2DAA2D,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAAE,MAAM,2DAA2D,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,wBAAwB,EAAE,MAAM,8DAA8D,CAAC;AACxG,OAAO,EAAE,0BAA0B,EAAE,MAAM,4DAA4D,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,kEAAkE,CAAC;AAC/G,OAAO,EAAE,yBAAyB,EAAE,MAAM,6DAA6D,CAAC;AACxG,OAAO,EAAE,wBAAwB,EAAE,MAAM,4DAA4D,CAAC;AACtG,YAAY,EAAE,0BAA0B,EAAE,MAAM,yDAAyD,CAAC;AAC1G,OAAO,EAAE,uBAAuB,EAAE,MAAM,2DAA2D,CAAC;AACpG,OAAO,EAAE,qBAAqB,EAAE,MAAM,yDAAyD,CAAC;AAChG,OAAO,EACL,uBAAuB,EACvB,KAAK,4BAA4B,GAClC,MAAM,2DAA2D,CAAC;AACnE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EACL,aAAa,EACb,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,cAAc,EACd,KAAK,6BAA6B,GACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,0DAA0D,CAAC;AACjG,OAAO,EAAE,yBAAyB,EAAE,MAAM,wEAAwE,CAAC;AACnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yDAAyD,CAAC;AAC/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,2BAA2B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeProvider.d.ts","sourceRoot":"","sources":["../../../src/provider/BackofficeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAqBjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAgH1D,eAAO,MAAM,kBAAkB,GAC7B,OAAO,uBAAuB,KAC7B,GAAG,CAAC,OAuJN,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"BackofficeProvider.d.ts","sourceRoot":"","sources":["../../../src/provider/BackofficeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAejE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAuG1D,eAAO,MAAM,kBAAkB,GAC7B,OAAO,uBAAuB,KAC7B,GAAG,CAAC,OA+HN,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RelayProvider.d.ts","sourceRoot":"","sources":["../../../src/relay/RelayProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOjD,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,cAAc,KAAK,KAAG,GAAG,CAAC,OAQvD,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"RelayProvider.d.ts","sourceRoot":"","sources":["../../../src/relay/RelayProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAWvE,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,cAAc,KAAK,KAAG,GAAG,CAAC,OAiBvD,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -1,4 +1,17 @@
1
1
  import { Environment, Network } from 'relay-runtime';
2
+ export type RelayTransportStatus = 'idle' | 'configured' | 'reconnecting';
3
+ export interface RelayTransportSnapshot {
4
+ generation: number;
5
+ reason: string | null;
6
+ status: RelayTransportStatus;
7
+ }
8
+ export interface RelayReconnectOptions {
9
+ reason?: string;
10
+ }
11
+ type RelayTransportListener = () => void;
12
+ export declare function getRelayTransportSnapshot(): RelayTransportSnapshot;
13
+ export declare function subscribeRelayTransport(listener: RelayTransportListener): () => void;
14
+ export declare function reconnectRelayWebSocket(options?: RelayReconnectOptions): void;
2
15
  export interface RelayEnvironmentConfiguration {
3
16
  httpUrl?: string;
4
17
  wsUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../src/relay/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,OAAO,EAOR,MAAM,eAAe,CAAC;AAuDvB,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrE,cAAc,CAAC,EAAE,MACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;AAKD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,6BAAkC,GAC1C,IAAI,CA8CN;AAoGD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,IAAI,CAK1D;AAED,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAGD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAkB3E;AAGD,iBAAS,aAAa,CACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,QAAQ,CAqBV;AAKD,UAAU,YAAY;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAGhE;AAGD,iBAAS,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAGD,iBAAS,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK7C;AAmLD,wBAAgB,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC,MAAM,CAAC,CAK9D;AAKD,wBAAgB,cAAc,IAAI,WAAW,CAS5C;AAKD,wBAAgB,eAAe,IAAI,IAAI,CAWtC;AAED,eAAO,MAAM,MAAM;;;;4BAxeY,OAAO,YAAY,MAAM,KAAG,MAAM,GAAG,IAAI;;;;CAgfvE,CAAC"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../src/relay/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,OAAO,EAOR,MAAM,eAAe,CAAC;AAmBvB,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;AAE1E,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,sBAAsB,GAAG,MAAM,IAAI,CAAC;AAqFzC,wBAAgB,yBAAyB,IAAI,sBAAsB,CAElE;AAKD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,sBAAsB,GAC/B,MAAM,IAAI,CAKZ;AAKD,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAMN;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrE,cAAc,CAAC,EAAE,MACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;AAKD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,6BAAkC,GAC1C,IAAI,CAkCN;AAoGD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,IAAI,CAK1D;AAED,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAGD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAkB3E;AAGD,iBAAS,aAAa,CACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,QAAQ,CAqBV;AAKD,UAAU,YAAY;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAGhE;AAGD,iBAAS,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAGD,iBAAS,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK7C;AAmLD,wBAAgB,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC,MAAM,CAAC,CAK9D;AAKD,wBAAgB,cAAc,IAAI,WAAW,CAS5C;AAKD,wBAAgB,eAAe,IAAI,IAAI,CAWtC;AAED,eAAO,MAAM,MAAM;;;;4BAjiBY,OAAO,YAAY,MAAM,KAAG,MAAM,GAAG,IAAI;;;;CAyiBvE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumile/backoffice-react",
3
- "version": "0.1.91",
3
+ "version": "0.1.94",
4
4
  "description": "React provider and pages for Kronex backoffice",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -160,10 +160,10 @@
160
160
  "npm": ">=8.0.0"
161
161
  },
162
162
  "dependencies": {
163
- "@plumile/backoffice-core": "^0.1.91",
164
- "@plumile/filter-query": "^0.1.91",
165
- "@plumile/router": "^0.1.91",
166
- "@plumile/ui": "^0.1.91",
163
+ "@plumile/backoffice-core": "^0.1.94",
164
+ "@plumile/filter-query": "^0.1.94",
165
+ "@plumile/router": "^0.1.94",
166
+ "@plumile/ui": "^0.1.94",
167
167
  "graphql-ws": "6.0.8",
168
168
  "i18next": "^26.0.8",
169
169
  "i18next-browser-languagedetector": "8.2.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"environment-BXoBq_6e.js","names":[],"sources":["../../src/relay/envHelpers.ts","../../src/relay/environment.ts"],"sourcesContent":["type EnvRecord = Record<string, string | boolean | undefined>;\n\nconst viteEnv: EnvRecord = (() => {\n try {\n const meta = import.meta as unknown as { env?: EnvRecord };\n if (meta.env != null) {\n return meta.env;\n }\n return {};\n } catch {\n // `import.meta` is not defined outside of ESM environments; fall back to an empty record.\n return {};\n }\n})();\n\nexport type ReadEnvFn = (key: string) => string | undefined;\n\nconst readEnvFromRecord = (env: EnvRecord, key: string): string | undefined => {\n const value = env[key];\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (trimmed === '') {\n return undefined;\n }\n\n return trimmed;\n};\n\nconst readBooleanEnvFromRecord = (\n env: EnvRecord,\n key: string,\n): boolean | undefined => {\n const value = env[key];\n if (value === true || value === false) {\n return value;\n }\n if (typeof value === 'string') {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n }\n return undefined;\n};\n\nconst isDevEnvFromRecord = (env: EnvRecord): boolean => {\n return Boolean(readBooleanEnvFromRecord(env, 'DEV'));\n};\n\n/**\n * Read a string environment variable from Vite's `import.meta.env` (if available).\n * Returns `undefined` when the value is missing or empty.\n */\nexport function readEnv(key: string): string | undefined {\n return readEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Reads an environment variable and coerces common string values to booleans.\n */\nexport function readBooleanEnv(key: string): boolean | undefined {\n return readBooleanEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Indicates whether the current build is running in development mode.\n */\nexport function isDevEnv(): boolean {\n return isDevEnvFromRecord(viteEnv);\n}\n\ninterface ResolveEndpointOptions {\n envKeys: readonly string[];\n fallback: string;\n read?: ReadEnvFn;\n}\n\n/**\n * Resolve HTTP endpoint from environment variables.\n */\nexport function resolveHttpEndpoint(options: ResolveEndpointOptions): string {\n const { envKeys, fallback, read = readEnv } = options;\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n return fallback;\n}\n\ninterface ResolveWebsocketEndpointOptions extends ResolveEndpointOptions {\n httpEndpoint: string;\n}\n\n/**\n * Resolve websocket endpoint from environment variables or derive it from the HTTP endpoint.\n */\nexport function resolveWebsocketEndpoint(\n options: ResolveWebsocketEndpointOptions,\n): string {\n const { envKeys, fallback, httpEndpoint, read = readEnv } = options;\n\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n\n if (httpEndpoint.startsWith('http')) {\n return httpEndpoint.replace(/^http/, 'ws');\n }\n\n if (httpEndpoint.startsWith('/')) {\n return httpEndpoint.replace(/\\/graphql$/, '/ws');\n }\n\n return fallback;\n}\n\nexport const __test = {\n isDevEnvFromRecord,\n readBooleanEnvFromRecord,\n readEnvFromRecord,\n};\n","import {\n Environment,\n Network,\n Observable,\n RecordSource,\n Store,\n type FetchFunction,\n type SubscribeFunction,\n type RelayFieldLogger,\n} from 'relay-runtime';\nimport { createClient, type Client } from 'graphql-ws';\nimport { isDevEnv } from './envHelpers.js';\n\nlet graphqlHttpEndpoint = '/api/graphql';\nlet graphqlWsEndpoint = '/api/ws';\n\n// (anonymousEnvironment reserved if needed later for public access / logout scenarios)\n// Removed until actually required to avoid lint errors.\n// let anonymousEnvironment: Environment | undefined;\nlet environment: Environment | undefined;\nlet wsClient: Client | undefined;\nlet getAuthHeaders:\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\nlet customDataIdResolver:\n | ((fieldValue: unknown, typeName: string) => string | null)\n | undefined;\n\n/**\n * No-op Relay field logger used to satisfy @required(action: LOG).\n */\nfunction noopRelayFieldLogger(): void {}\n\nlet relayFieldLogger: RelayFieldLogger = noopRelayFieldLogger;\n\nif (isDevEnv()) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n}\n\nconst defaultGetDataId: (\n fieldValue: unknown,\n typeName: string,\n) => string | null = (fieldValue) => {\n if (fieldValue == null || typeof fieldValue !== 'object') {\n return null;\n }\n const { id } = fieldValue as { id?: unknown };\n if (typeof id !== 'string' || id.trim() === '') {\n return null;\n }\n return id;\n};\n\nconst getDataId = (fieldValue: unknown, typeName: string): string | null => {\n const customId = customDataIdResolver?.(fieldValue, typeName);\n if (customId != null) {\n return customId;\n }\n return defaultGetDataId(fieldValue, typeName);\n};\n\nexport interface RelayEnvironmentConfiguration {\n httpUrl?: string;\n wsUrl?: string;\n logEvents?: boolean;\n getDataId?: (fieldValue: unknown, typeName: string) => string | null;\n getAuthHeaders?: () =>\n | Record<string, string>\n | Promise<Record<string, string>>;\n}\n\n/**\n * Configure the endpoints and logging behavior used by the shared Relay environment.\n */\nexport function configureRelayEnvironment(\n options: RelayEnvironmentConfiguration = {},\n): void {\n const {\n httpUrl,\n wsUrl,\n logEvents,\n getDataId: nextGetDataId,\n getAuthHeaders: nextGetAuthHeaders,\n } = options;\n\n if (typeof httpUrl === 'string' && httpUrl !== '') {\n graphqlHttpEndpoint = httpUrl;\n }\n\n if (typeof wsUrl === 'string' && wsUrl !== '') {\n graphqlWsEndpoint = wsUrl;\n }\n\n if (logEvents != null) {\n if (logEvents) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n } else {\n relayFieldLogger = noopRelayFieldLogger;\n }\n }\n\n customDataIdResolver = nextGetDataId;\n getAuthHeaders = nextGetAuthHeaders;\n\n if (wsClient != null) {\n try {\n const result = wsClient.dispose();\n if (result instanceof Promise) {\n result.catch(() => {\n // ignore dispose rejections\n });\n }\n } catch {\n // ignore errors during dispose\n }\n wsClient = undefined;\n }\n\n environment = undefined;\n}\n\n/**\n * Resolve the websocket endpoint into an absolute URL suitable for graphql-ws.\n */\nfunction resolveWebsocketUrl(): string {\n const endpoint = graphqlWsEndpoint;\n\n if (endpoint.startsWith('ws')) {\n return endpoint;\n }\n\n if (endpoint.startsWith('http')) {\n return endpoint.replace(/^http/, 'ws');\n }\n\n if (endpoint.startsWith('/')) {\n if (typeof window === 'undefined') {\n return endpoint;\n }\n let protocol = 'ws:';\n if (window.location.protocol === 'https:') {\n protocol = 'wss:';\n }\n return `${protocol}//${window.location.host}${endpoint}`;\n }\n\n return endpoint;\n}\n\n/**\n * Build or get a singleton graphql-ws client with basic auto-reconnect.\n * The graphql-ws library already supports lazy connections and we add retry logic.\n */\nfunction getWsClient(): Client {\n if (wsClient != null) {\n return wsClient;\n }\n if (typeof window === 'undefined') {\n throw new Error(\n 'GraphQL subscriptions unavailable in non-browser environment',\n );\n }\n\n const url = resolveWebsocketUrl();\n\n // Exponential backoff parameters\n const maxAttempts = 10;\n const baseDelayMs = 500;\n\n wsClient = createClient({\n url,\n keepAlive: 10_000,\n lazy: true,\n retryAttempts: maxAttempts,\n shouldRetry() {\n return true;\n },\n async retryWait(retries) {\n // retries starts at 0\n const delay =\n Math.min(8000, baseDelayMs * 2 ** retries) + Math.random() * 200;\n await new Promise<void>((resolve) => {\n setTimeout(() => {\n resolve();\n }, delay);\n });\n },\n connectionParams: async () => {\n if (getAuthHeaders == null) {\n return {};\n }\n try {\n return await getAuthHeaders();\n } catch {\n return {};\n }\n },\n });\n\n return wsClient;\n}\n\n/**\n * Get organization slug from current window location\n */\n// export function getOrganizationSlug(): string | null {\n// const { pathname } = window.location;\n// const slug = pathname.split('/')[1];\n// if (slug == null) {\n// return null;\n// }\n\n// return slug;\n// }\n\n// -------------------------\n// Upload detection helpers\n// -------------------------\n/** Test if a value is an uploadable (File/Blob) */\nfunction isUploadable(value: unknown): value is File | Blob {\n return (\n (typeof File !== 'undefined' && value instanceof File) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n );\n}\n\ninterface FileRef {\n path: string; // JSON pointer-like (e.g. variables.input.file)\n file: File | Blob;\n}\n\n/** Recursively clone a structure replacing files with null and collecting them */\nfunction collectFiles(value: unknown, path: string, acc: FileRef[]): unknown {\n if (isUploadable(value)) {\n acc.push({ path, file: value });\n return null; // placeholder per multipart spec\n }\n if (Array.isArray(value)) {\n return value.map((v, i) => {\n return collectFiles(v, `${path}.${i}`, acc);\n });\n }\n if (value != null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = collectFiles(v, `${path}.${k}`, acc);\n }\n return out;\n }\n return value; // primitives unchanged\n}\n\n/** Build GraphQL multipart form-data payload */\nfunction buildFormData(\n query: string,\n variables: Record<string, unknown>,\n): FormData {\n const files: FileRef[] = [];\n // Deep clone variables while replacing files with null\n const clonedVars = collectFiles(variables, 'variables', files) as Record<\n string,\n unknown\n >;\n\n const form = new FormData();\n const operations = { query, variables: clonedVars };\n form.append('operations', JSON.stringify(operations));\n\n const map: Record<string, string[]> = {};\n files.forEach((ref, idx) => {\n map[idx] = [ref.path];\n });\n form.append('map', JSON.stringify(map));\n files.forEach((ref, idx) => {\n form.append(String(idx), ref.file);\n });\n return form;\n}\n\n// -------------------------\n// Retry / timeout helpers\n// -------------------------\ninterface RetryOptions {\n maxAttempts: number; // total attempts including initial\n baseDelayMs: number;\n maxDelayMs: number;\n fetchTimeoutMs: number;\n}\n\nconst RETRY_OPTIONS: RetryOptions = {\n maxAttempts: 3,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n fetchTimeoutMs: 600_000, // 10 minutes (parité avec ancien middleware)\n};\n\n/** Sleep helper with Promise */\nasync function sleep(ms: number): Promise<void> {\n await new Promise<void>((res) => {\n setTimeout(() => {\n res();\n }, ms);\n });\n}\n\n/** Exponential backoff with jitter */\nfunction calcBackoff(attempt: number, opts: RetryOptions): number {\n const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * 2 ** attempt);\n return exp + Math.random() * 0.2 * exp; // jitter 0-20%\n}\n\n/** Determine if an HTTP status is retryable */\nfunction isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || (status >= 500 && status < 600);\n}\n\n/** Determine if an error should be treated as transient network issue */\nfunction isNetworkError(err: unknown): boolean {\n return (\n err instanceof TypeError ||\n (err instanceof Error && err.name === 'AbortError')\n );\n}\n\n// -------------------------\n// fetchFn implementation\n// -------------------------\ninterface GraphQLResponseErrorItem {\n [key: string]: unknown;\n message: string;\n}\n\ninterface GraphQLResponseShape<T = unknown> {\n data?: T;\n errors?: GraphQLResponseErrorItem[];\n extensions?: Record<string, unknown>;\n}\n\n/** Debug log helper (no-op en production) */\nfunction debugLog(...args: unknown[]): void {\n if (isDevEnv()) {\n // eslint-disable-next-line no-console\n console.log('[RelayNetwork]', ...args);\n }\n}\n\n/** Fetch GraphQL (with retry + upload) */\nasync function fetchFn(\n request: { text: string | null | undefined },\n variables: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _cacheConfig: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _uploadables: unknown,\n): Promise<GraphQLResponseShape> {\n const queryText: string | null | undefined = request.text; // no persisted queries here (yet)\n if (queryText == null) {\n throw new Error('Missing GraphQL query text');\n }\n const safeQueryText: string = queryText; // narrowed non-null\n\n /** Execute one network attempt */\n async function execOnce(attempt: number): Promise<GraphQLResponseShape> {\n const controller = new AbortController();\n const timeout = setTimeout(() => {\n controller.abort();\n }, RETRY_OPTIONS.fetchTimeoutMs);\n try {\n let body: BodyInit;\n const headers: Record<string, string> = {};\n if (getAuthHeaders != null) {\n try {\n Object.assign(headers, await getAuthHeaders());\n } catch {\n // ignore auth header failures\n }\n }\n const hasFiles = ((): boolean => {\n try {\n const stack: unknown[] = [variables];\n while (stack.length > 0) {\n const v = stack.pop();\n if (isUploadable(v)) {\n return true;\n }\n if (Array.isArray(v)) {\n stack.push(...v);\n } else if (v != null && typeof v === 'object') {\n stack.push(...Object.values(v as Record<string, unknown>));\n }\n }\n } catch {\n // ignore traversal errors\n }\n return false;\n })();\n\n if (hasFiles) {\n body = buildFormData(safeQueryText, variables);\n } else {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify({ query: safeQueryText, variables });\n }\n\n const response = await fetch(graphqlHttpEndpoint, {\n method: 'POST',\n body,\n headers,\n credentials: 'include',\n signal: controller.signal,\n });\n\n if (!response.ok) {\n if (\n attempt < RETRY_OPTIONS.maxAttempts - 1 &&\n isRetryableStatus(response.status)\n ) {\n throw new Error(`Retryable HTTP status ${response.status}`);\n }\n const text = await response.text().catch(() => {\n return '';\n });\n throw new Error(`GraphQL HTTP error ${response.status}: ${text}`);\n }\n\n const json: GraphQLResponseShape = await response.json();\n if (Array.isArray(json.errors) && json.errors.length > 0) {\n debugLog('GraphQL errors', json.errors);\n }\n return json;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n for (let attempt = 0; attempt < RETRY_OPTIONS.maxAttempts; attempt += 1) {\n try {\n return await execOnce(attempt);\n } catch (err) {\n const last = attempt === RETRY_OPTIONS.maxAttempts - 1;\n const retryable =\n isNetworkError(err) ||\n (err instanceof Error && err.message.includes('Retryable HTTP status'));\n if (!retryable || last) {\n debugLog('GraphQL fetch error', err);\n throw err;\n }\n const delay = calcBackoff(attempt, RETRY_OPTIONS);\n await sleep(delay);\n }\n }\n throw new Error('Exhausted retries without returning a result');\n}\n\n// -------------------------\n// subscribeFn implementation (wrap existing logic in Relay Observable)\n// -------------------------\n/** Subscription function bridging graphql-ws client to Relay */\nfunction subscribeFn(\n operation: { text: string | null | undefined; name: string },\n variables: Record<string, unknown>,\n): Observable<unknown> {\n debugLog('subscription:start', operation.name, variables);\n return Observable.create<unknown>((sink) => {\n const query = operation.text;\n if (query == null || query === '') {\n sink.error(new Error('Subscription operation text is empty'));\n return () => {\n // noop\n };\n }\n const client = getWsClient();\n const dispose = client.subscribe(\n { query, variables, operationName: operation.name },\n {\n next: (data) => {\n sink.next(data);\n },\n error: (err) => {\n let errorObj: Error;\n if (err instanceof Error) {\n errorObj = err;\n } else {\n errorObj = new Error('Subscription error');\n }\n sink.error(errorObj);\n },\n complete: () => {\n sink.complete();\n },\n },\n );\n return () => {\n dispose();\n };\n });\n}\n\n/**\n * Create native Relay network layer (fetch + subscribe)\n */\nexport function getNetwork(): ReturnType<typeof Network.create> {\n return Network.create(\n fetchFn as FetchFunction,\n subscribeFn as SubscribeFunction,\n );\n}\n\n/**\n * Get anonymous relay environment\n */\nexport function getEnvironment(): Environment {\n environment ??= new Environment({\n getDataID: getDataId,\n relayFieldLogger,\n network: getNetwork(),\n store: new Store(new RecordSource()),\n });\n\n return environment;\n}\n\n/**\n * Reset the Relay store by creating a new empty source\n */\nexport function resetRelayStore(): void {\n const environment = getEnvironment();\n\n // Create a new store with an empty source\n const source = new RecordSource();\n\n // Replace the data in the store with our empty source\n environment.getStore().publish(source);\n\n // Notify subscribers that the data has changed\n environment.getStore().notify();\n}\n\nexport const __test = {\n buildFormData,\n calcBackoff,\n collectFiles,\n getDataId,\n isNetworkError,\n isRetryableStatus,\n isUploadable,\n};\n"],"mappings":"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"}