UNPKG

@documedis-components/prescription-sign

Version:

React component for signing electronic prescriptions with HIN authentication

913 lines (912 loc) 186 kB
import { CallbackActorLogic, AnyEventObject, PromiseActorLogic, ActorRef, AnyMachineSnapshot } from 'xstate'; import { PrescriptionSignContext, PrescriptionSignEvents, PrescriptionSignErrorType, UsePrescriptionSigningProps } from './types'; /** * Hook to manage the ePrescription signature process * * This is a standalone hook that can be shipped in a library. * It handles the complete HIN authentication and signing flow. * * Required peer dependencies: * - next-auth/react (for session management) * - xstate and @xstate/react * * @returns Object containing: * - start: Function to initiate the signing process with CHMED data * - interrupt: Function to terminate the signing process at any time * - state: Raw XState machine state (for advanced usage) * - isIdle: true when ready to start signing (initial state) * - isActive: true when actively processing (excludes error/success states) * - isError: true when in error state (persists until retry) * - isSuccess: true when signing completed successfully * - isSigning: true during the actual signature operation * - signedCHMED: The signed prescription data (available after success) */ export declare function usePrescriptionSigning(props: UsePrescriptionSigningProps): { start: (encodedCHMED: string) => void; interrupt: () => void; state: import('xstate').MachineSnapshot<PrescriptionSignContext, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, { [x: string]: import('xstate').ActorRefFromLogic<CallbackActorLogic<AnyEventObject>> | import('xstate').ActorRefFromLogic<CallbackActorLogic<AnyEventObject, { popupRef: Window | null; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; skipRestorationLogs?: boolean; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; recover: boolean; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; authCode: string; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<void, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; }>> | import('xstate').ActorRefFromLogic<PromiseActorLogic<string, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; recover: boolean; }>> | import('xstate').ActorRefFromLogic<CallbackActorLogic<AnyEventObject, { error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; }>> | import('xstate').ActorRefFromLogic<CallbackActorLogic<AnyEventObject, { signedCHMED?: string; }>> | undefined; }, "Idle" | { Started: { Popup: "Opening" | "Open" | "Closed"; Signing: "Authentication" | "SAMLAuth" | "Error" | "End" | "ValidatingCHMED" | "VerifySessionGuard" | "SigningCHMED" | "SAMLAuthCode" | "TokenRefreshing" | "OAuth" | "SAMLAuthHandle" | "Success"; }; }, string, import('xstate').NonReducibleUnknown, import('xstate').MetaObject, { readonly context: () => { popupRef: null; encodedCHMED: undefined; signedCHMED: undefined; skipRestorationLogs: false; }; readonly id: "HINPrescriptionSigning"; readonly initial: "Idle"; readonly states: { readonly Idle: { readonly on: { readonly START: { readonly target: "Started"; readonly actions: import('xstate').ActionFunction<PrescriptionSignContext, { type: "START"; encodedCHMED: string; }, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, undefined, import('xstate').Values<{ openPopup: { src: "openPopup"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; trackPopup: { src: "trackPopup"; logic: CallbackActorLogic<AnyEventObject, { popupRef: Window | null; }>; id: string | undefined; }; listenAuthenticationMessage: { src: "listenAuthenticationMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; listenSamlAuthMessage: { src: "listenSamlAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; verifySession: { src: "verifySession"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; skipRestorationLogs?: boolean; }>; id: string | undefined; }; refreshToken: { src: "refreshToken"; logic: PromiseActorLogic<void>; id: string | undefined; }; initSAMLAuthCode: { src: "initSAMLAuthCode"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; recover: boolean; }>; id: string | undefined; }; listenSAMLAuthCodeMessage: { src: "listenSAMLAuthCodeMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; initOAuth: { src: "initOAuth"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; }>; id: string | undefined; }; listenOAuthMessage: { src: "listenOAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; getSAMLAuthHandle: { src: "getSAMLAuthHandle"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; authCode: string; }>; id: string | undefined; }; validateCHMED: { src: "validateCHMED"; logic: PromiseActorLogic<void, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; }>; id: string | undefined; }; signCHMEDRx: { src: "signCHMEDRx"; logic: PromiseActorLogic<string, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; recover: boolean; }>; id: string | undefined; }; errorHandler: { src: "errorHandler"; logic: CallbackActorLogic<AnyEventObject, { error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; }>; id: string | undefined; }; successHandler: { src: "successHandler"; logic: CallbackActorLogic<AnyEventObject, { signedCHMED?: string; }>; id: string | undefined; }; }>, never, never, never, never>; }; }; }; readonly Started: { readonly type: "parallel"; readonly onDone: { readonly target: "Idle"; readonly actions: import('xstate').ActionFunction<PrescriptionSignContext, import('xstate').DoneStateEvent<unknown>, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, undefined, import('xstate').Values<{ openPopup: { src: "openPopup"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; trackPopup: { src: "trackPopup"; logic: CallbackActorLogic<AnyEventObject, { popupRef: Window | null; }>; id: string | undefined; }; listenAuthenticationMessage: { src: "listenAuthenticationMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; listenSamlAuthMessage: { src: "listenSamlAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; verifySession: { src: "verifySession"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; skipRestorationLogs?: boolean; }>; id: string | undefined; }; refreshToken: { src: "refreshToken"; logic: PromiseActorLogic<void>; id: string | undefined; }; initSAMLAuthCode: { src: "initSAMLAuthCode"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; recover: boolean; }>; id: string | undefined; }; listenSAMLAuthCodeMessage: { src: "listenSAMLAuthCodeMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; initOAuth: { src: "initOAuth"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; }>; id: string | undefined; }; listenOAuthMessage: { src: "listenOAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; getSAMLAuthHandle: { src: "getSAMLAuthHandle"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; authCode: string; }>; id: string | undefined; }; validateCHMED: { src: "validateCHMED"; logic: PromiseActorLogic<void, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; }>; id: string | undefined; }; signCHMEDRx: { src: "signCHMEDRx"; logic: PromiseActorLogic<string, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; recover: boolean; }>; id: string | undefined; }; errorHandler: { src: "errorHandler"; logic: CallbackActorLogic<AnyEventObject, { error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; }>; id: string | undefined; }; successHandler: { src: "successHandler"; logic: CallbackActorLogic<AnyEventObject, { signedCHMED?: string; }>; id: string | undefined; }; }>, never, never, never, never>; }; readonly states: { readonly Popup: { readonly initial: "Opening"; readonly states: { readonly Opening: { readonly on: { readonly OPEN_POPUP: { readonly target: "Open"; readonly actions: import('xstate').ActionFunction<PrescriptionSignContext, { type: "OPEN_POPUP"; popupRef: Window | null; }, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, undefined, import('xstate').Values<{ openPopup: { src: "openPopup"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; trackPopup: { src: "trackPopup"; logic: CallbackActorLogic<AnyEventObject, { popupRef: Window | null; }>; id: string | undefined; }; listenAuthenticationMessage: { src: "listenAuthenticationMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; listenSamlAuthMessage: { src: "listenSamlAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; verifySession: { src: "verifySession"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; skipRestorationLogs?: boolean; }>; id: string | undefined; }; refreshToken: { src: "refreshToken"; logic: PromiseActorLogic<void>; id: string | undefined; }; initSAMLAuthCode: { src: "initSAMLAuthCode"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; recover: boolean; }>; id: string | undefined; }; listenSAMLAuthCodeMessage: { src: "listenSAMLAuthCodeMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; initOAuth: { src: "initOAuth"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; }>; id: string | undefined; }; listenOAuthMessage: { src: "listenOAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; getSAMLAuthHandle: { src: "getSAMLAuthHandle"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; authCode: string; }>; id: string | undefined; }; validateCHMED: { src: "validateCHMED"; logic: PromiseActorLogic<void, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; }>; id: string | undefined; }; signCHMEDRx: { src: "signCHMEDRx"; logic: PromiseActorLogic<string, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; recover: boolean; }>; id: string | undefined; }; errorHandler: { src: "errorHandler"; logic: CallbackActorLogic<AnyEventObject, { error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; }>; id: string | undefined; }; successHandler: { src: "successHandler"; logic: CallbackActorLogic<AnyEventObject, { signedCHMED?: string; }>; id: string | undefined; }; }>, never, never, never, never>; }; }; readonly invoke: { readonly id: "openPopup"; readonly src: "openPopup"; }; }; readonly Open: { readonly on: { readonly CLOSE_POPUP: { readonly target: "Closed"; }; readonly ERROR: { readonly target: "Closed"; }; }; readonly invoke: { readonly id: "trackPopup"; readonly input: ({ context }: { context: PrescriptionSignContext; event: { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }; self: ActorRef<import('xstate').MachineSnapshot<PrescriptionSignContext, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, Record<string, import('xstate').AnyActorRef>, import('xstate').StateValue, string, unknown, any, any>, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, AnyEventObject>; }) => { popupRef: Window | null; }; readonly src: "trackPopup"; }; }; readonly Closed: { readonly type: "final"; readonly entry: import('xstate').ActionFunction<PrescriptionSignContext, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, { type: "OPEN_POPUP"; popupRef: Window | null; } | { type: "CLOSE_POPUP"; } | { type: "START"; encodedCHMED: string; } | { type: "TERMINATE"; } | { type: "VERIFY_SESSION"; } | { type: "REFRESH_TOKEN"; } | { type: "GET_TOKEN"; } | { type: "GET_SAML_AUTH_CODE"; recoverable?: boolean; } | { type: "GET_SAML_AUTH_HANDLE"; authCode: string; } | { type: "VALIDATE_CHMED"; } | { type: "SIGN_PRESCRIPTION"; } | { type: "AUTHENTICATION_SUCCESS"; } | { type: "ERROR"; error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; } | { type: "UNAUTHORIZED_TOKEN"; } | { type: "UNAUTHORIZED_HANDLE"; }, undefined, import('xstate').Values<{ openPopup: { src: "openPopup"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; trackPopup: { src: "trackPopup"; logic: CallbackActorLogic<AnyEventObject, { popupRef: Window | null; }>; id: string | undefined; }; listenAuthenticationMessage: { src: "listenAuthenticationMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; listenSamlAuthMessage: { src: "listenSamlAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; verifySession: { src: "verifySession"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; skipRestorationLogs?: boolean; }>; id: string | undefined; }; refreshToken: { src: "refreshToken"; logic: PromiseActorLogic<void>; id: string | undefined; }; initSAMLAuthCode: { src: "initSAMLAuthCode"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; recover: boolean; }>; id: string | undefined; }; listenSAMLAuthCodeMessage: { src: "listenSAMLAuthCodeMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; initOAuth: { src: "initOAuth"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; popupRef: Window | null; }>; id: string | undefined; }; listenOAuthMessage: { src: "listenOAuthMessage"; logic: CallbackActorLogic<AnyEventObject>; id: string | undefined; }; getSAMLAuthHandle: { src: "getSAMLAuthHandle"; logic: PromiseActorLogic<void, { parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; authCode: string; }>; id: string | undefined; }; validateCHMED: { src: "validateCHMED"; logic: PromiseActorLogic<void, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; }>; id: string | undefined; }; signCHMEDRx: { src: "signCHMEDRx"; logic: PromiseActorLogic<string, { encodedCHMED?: string; parent: ActorRef<AnyMachineSnapshot, PrescriptionSignEvents>; recover: boolean; }>; id: string | undefined; }; errorHandler: { src: "errorHandler"; logic: CallbackActorLogic<AnyEventObject, { error: PrescriptionSignErrorType; details?: { message?: string; originalError?: unknown; context?: Record<string, unknown>; }; }>;