@documedis-components/prescription-sign
Version:
React component for signing electronic prescriptions with HIN authentication
247 lines (246 loc) • 9.35 kB
TypeScript
import { Environment } from '../../../../../core/src/infrastructure/shared';
export interface PrescriptionSignProps {
/**
* Environment configuration for the prescription service
* - 'local': Development environment (localhost:52247)
* - 'dev': Development Azure Container Apps
* - 'int': Integration Azure Container Apps
* - 'prod': Production Azure Container Apps
*/
environment: Environment;
/** Base64-encoded CHMED prescription data to be signed */
chmed: string;
/** Access token for authenticating with the backend service */
accessToken: string;
/**
* Optional existing session token to reuse authentication state.
* If provided, the component will attempt to use existing authentication.
*/
sessionToken?: string;
/**
* Optional callback invoked when the session token is updated.
* Use this to persist the session token for reuse across components.
*/
onSessionTokenUpdate?: (sessionToken: string) => void;
/**
* Optional callback invoked when prescription signing succeeds.
* Receives the signed CHMED data as a base64-encoded string.
*/
onSuccess?: (signedCHMED: string) => void;
/**
* Optional callback invoked when prescription signing fails.
* Receives a specific error type indicating what went wrong.
*/
onError?: (error: PrescriptionSignErrorType) => void;
/**
* Optional logger for detailed process tracking.
* Provides step-by-step information about the signing process.
*/
logger?: PrescriptionSignLogger;
/** Optional additional CSS class names to apply to the component */
className?: string;
}
/**
* Internal events used by the prescription signing state machine
* These events coordinate the complex authentication and signing workflow
*/
export type PrescriptionSignEvents = {
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';
};
/**
* Specific error types that can occur during prescription signing
*/
export type PrescriptionSignErrorType =
/** User canceled the signing process */
'canceled'
/** Authentication popup window was closed by user */
| 'popupClosed'
/** Browser blocked the authentication popup window */
| 'popupBlocked'
/** HIN authentication failed */
| 'login'
/** Invalid or malformed CHMED prescription data */
| 'chmed'
/** OAuth authentication with HIN failed */
| 'oauth'
/** Failed to obtain SAML authorization code */
| 'authCode'
/** Failed to obtain SAML authentication handle */
| 'authHandle'
/** Failed to digitally sign the prescription */
| 'signature';
/**
* Internal context used by the prescription signing state machine
*/
export type PrescriptionSignContext = {
/** The CHMED data being processed (base64-encoded) */
encodedCHMED?: string;
/** The signed CHMED data returned from HIN (base64-encoded) */
signedCHMED?: string;
/** Reference to the authentication popup window */
popupRef: Window | null;
/** Skip session restoration logs when verifying session after fresh operations */
skipRestorationLogs?: boolean;
};
/**
* Structured log event types for programmatic reaction by developers.
* These events enable monitoring, debugging, and analytics of the prescription signing process.
*/
export type PrescriptionSignLogEvent = PrescriptionSignFlowEvent | PrescriptionSignErrorEvent;
/**
* Flow events for tracking prescription signing progress.
* Emitted at various stages of the signing process to provide visibility into the workflow.
*
* @example
* ```typescript
* logger.emit({
* type: 'flow_step_started',
* phase: 'authentication',
* step: 'saml_auth_initiated',
* timestamp: new Date()
* });
* ```
*/
export type PrescriptionSignFlowEvent = {
/** Event type indicating the nature of the flow event */
type: 'flow_started' | 'flow_step_started' | 'flow_step_completed' | 'flow_completed';
/** Current phase of the prescription signing process */
phase: 'initialization' | 'securisation' | 'authentication' | 'authorization' | 'validation' | 'signing' | 'completion';
/** Specific step within the current phase */
step: PrescriptionSignFlowStep;
/** Timestamp when the event occurred */
timestamp: Date;
/** Optional contextual information about the event (e.g., user ID, session info) */
context?: Record<string, unknown>;
/** Optional data specific to this event (e.g., token expiry, validation results) */
data?: Record<string, unknown>;
};
/**
* Error events with structured data for programmatic error handling.
* Provides detailed information about failures to enable proper error recovery and user feedback.
*
* @example
* ```typescript
* logger.emit({
* type: 'error',
* errorType: 'popupBlocked',
* phase: 'authentication',
* step: 'popup_opened',
* timestamp: new Date(),
* message: 'Browser blocked authentication popup'
* });
* ```
*/
export type PrescriptionSignErrorEvent = {
/** Indicates this is an error event */
type: 'error';
/** Categorized error type for programmatic handling */
errorType: PrescriptionSignErrorType;
/** Phase where the error occurred */
phase: 'initialization' | 'securisation' | 'authentication' | 'authorization' | 'validation' | 'signing';
/** Specific step where the error occurred */
step: PrescriptionSignFlowStep;
/** Timestamp when the error occurred */
timestamp: Date;
/** Original error object if available (e.g., network error, API response) */
originalError?: unknown;
/** Additional context about the error (e.g., HTTP status, request ID) */
context?: Record<string, unknown>;
/** Human-readable error message for debugging */
message?: string;
};
/**
* Detailed flow steps for granular progress tracking.
* Each step represents a specific point in the prescription signing workflow.
* Steps are organized by phase to help developers understand the process flow.
*/
export type PrescriptionSignFlowStep = 'process_started' | 'popup_opened' | 'saml_handle_retrieved_from_session' | 'oauth_token_retrieved_from_session' | 'oauth_token_eligible_for_refresh' | 'authentication_ready' | 'authentication_completed' | 'saml_auth_initiated' | 'saml_auth_completed' | 'oauth_flow_initiated' | 'oauth_code_received' | 'oauth_token_received' | 'token_refresh_initiated' | 'token_refreshed' | 'saml_auth_code_initiated' | 'saml_code_received' | 'saml_handle_initiated' | 'saml_handle_received' | 'chmed_validation_started' | 'chmed_validation_completed' | 'prescription_signing_started' | 'prescription_signing_completed' | 'process_completed' | 'process_terminated';
/**
* Logger interface for emitting structured events that developers can programmatically react to
* This is designed for component library usage, not end-user applications
*/
export type PrescriptionSignLogger = {
/**
* Emit a structured log event for programmatic consumption
* @param event - Structured event data that developers can filter, react to, and process
*/
emit: (event: PrescriptionSignLogEvent) => void;
};
/**
* Props for the usePrescriptionSigning hook
*/
export type UsePrescriptionSigningProps = {
/**
* Environment configuration for the prescription service
* - 'local': Development environment (localhost:52247)
* - 'dev': Development Azure Container Apps
* - 'int': Integration Azure Container Apps
* - 'prod': Production Azure Container Apps
*/
environment: Environment;
/** Access token for authenticating with the backend service */
accessToken: string;
/**
* Optional existing session token to reuse authentication state.
* If provided, the hook will attempt to use existing authentication.
*/
sessionToken?: string;
/**
* Optional callback invoked when the session token is updated.
* Use this to persist the session token for reuse across hook instances.
*/
onSessionTokenUpdate?: (token: string) => void;
/**
* Optional callback invoked when prescription signing succeeds.
* Receives the signed CHMED data as a base64-encoded string.
*/
onSuccess?: (signedCHMED: string) => void;
/**
* Optional callback invoked when prescription signing fails.
* Receives a specific error type indicating what went wrong.
*/
onError?: (error: PrescriptionSignErrorType) => void;
/**
* Optional logger for step-by-step process tracking.
* Emits detailed events throughout the signing process for debugging and monitoring.
*/
logger?: PrescriptionSignLogger;
};