rename to core

This commit is contained in:
2025-12-15 13:46:07 +01:00
parent aedf58643d
commit 5c22f8820c
559 changed files with 415 additions and 767 deletions

View File

@@ -0,0 +1,76 @@
import { AuthenticationState } from '../../domain/value-objects/AuthenticationState';
import { BrowserAuthenticationState } from '../../domain/value-objects/BrowserAuthenticationState';
import { Result } from '../../../shared/result/Result';
/**
* Port for authentication services implementing zero-knowledge login.
*
* GridPilot never sees, stores, or transmits user credentials.
* Authentication is handled by opening a visible browser window where
* the user logs in directly with iRacing. GridPilot only observes
* URL changes to detect successful authentication.
*/
export interface AuthenticationServicePort {
/**
* Check if user has a valid session without prompting login.
* Navigates to a protected iRacing page and checks for login redirects.
*
* @returns Result containing the current authentication state
*/
checkSession(): Promise<Result<AuthenticationState>>;
/**
* Open browser for user to login manually.
* The browser window is visible so user can verify they're on the real iRacing site.
* GridPilot waits for URL change indicating successful login.
*
* @returns Result indicating success (login complete) or failure (cancelled/timeout)
*/
initiateLogin(): Promise<Result<void>>;
/**
* Clear the persistent session (logout).
* Removes stored browser context and cookies.
*
* @returns Result indicating success or failure
*/
clearSession(): Promise<Result<void>>;
/**
* Get current authentication state.
* Returns cached state without making network requests.
*
* @returns The current AuthenticationState
*/
getState(): AuthenticationState;
/**
* Validate session with server-side check.
* Makes a lightweight HTTP request to verify cookies are still valid on the server.
*
* @returns Result containing true if server confirms validity, false otherwise
*/
validateServerSide(): Promise<Result<boolean>>;
/**
* Refresh session state from cookie store.
* Re-reads cookies and updates internal state without server validation.
*
* @returns Result indicating success or failure
*/
refreshSession(): Promise<Result<void>>;
/**
* Get session expiry date.
* Returns the expiry time extracted from session cookies.
*
* @returns Result containing the expiry Date or null if no expiration
*/
getSessionExpiry(): Promise<Result<Date | null>>;
/**
* Verify browser page shows authenticated state.
* Checks page content for authentication indicators.
*/
verifyPageAuthentication(): Promise<Result<BrowserAuthenticationState>>;
}

View File

@@ -0,0 +1,11 @@
import type { HostedSessionConfig } from '../../domain/types/HostedSessionConfig';
import { StepId } from '../../domain/value-objects/StepId';
import type { AutomationEngineValidationResultDTO } from '../dto/AutomationEngineValidationResultDTO';
import type { IBrowserAutomation } from './ScreenAutomationPort';
export interface AutomationEnginePort {
validateConfiguration(config: HostedSessionConfig): Promise<AutomationEngineValidationResultDTO>;
executeStep(stepId: StepId, config: HostedSessionConfig): Promise<void>;
stopAutomation(): void;
readonly browserAutomation: IBrowserAutomation;
}

View File

@@ -0,0 +1,10 @@
export type AutomationEvent = {
actionId?: string
type: 'panel-attached'|'modal-opened'|'action-started'|'action-complete'|'action-failed'|'panel-missing'
timestamp: number
payload?: any
}
export interface AutomationEventPublisherPort {
publish(event: AutomationEvent): Promise<void>
}

View File

@@ -0,0 +1,5 @@
export interface AutomationResult {
success: boolean;
error?: string;
metadata?: Record<string, unknown>;
}

View File

@@ -0,0 +1,9 @@
import { Result } from '../../../shared/result/Result';
import { CheckoutConfirmation } from '../../domain/value-objects/CheckoutConfirmation';
import type { CheckoutConfirmationRequestDTO } from '../dto/CheckoutConfirmationRequestDTO';
export interface CheckoutConfirmationPort {
requestCheckoutConfirmation(
request: CheckoutConfirmationRequestDTO
): Promise<Result<CheckoutConfirmation>>;
}

View File

@@ -0,0 +1,7 @@
import { Result } from '../../../shared/result/Result';
import type { CheckoutInfoDTO } from '../dto/CheckoutInfoDTO';
export interface CheckoutServicePort {
extractCheckoutInfo(): Promise<Result<CheckoutInfoDTO>>;
proceedWithCheckout(): Promise<Result<void>>;
}

View File

@@ -0,0 +1,10 @@
export type AutomationEvent = {
actionId?: string
type: 'panel-attached'|'modal-opened'|'action-started'|'action-complete'|'action-failed'|'panel-missing'
timestamp: number
payload?: any
}
export interface IAutomationEventPublisher {
publish(event: AutomationEvent): Promise<void>
}

View File

@@ -0,0 +1,7 @@
export interface ILogger {
debug(message: string, context?: Record<string, any>): void;
info(message: string, context?: Record<string, any>): void;
warn(message: string, context?: Record<string, any>): void;
error(message: string, error?: Error, context?: Record<string, any>): void;
verbose?(message: string, context?: Record<string, any>): void;
}

View File

@@ -0,0 +1,7 @@
export type OverlayAction = { id: string; label: string; meta?: Record<string, unknown>; timeoutMs?: number }
export type ActionAck = { id: string; status: 'confirmed' | 'tentative' | 'failed'; reason?: string }
export interface IOverlaySyncPort {
startAction(action: OverlayAction): Promise<ActionAck>
cancelAction(actionId: string): Promise<void>
}

View File

@@ -0,0 +1,17 @@
/**
* Contextual metadata attached to log entries
*/
export interface LogContext {
/** Unique session identifier for correlation */
sessionId?: string;
/** Current automation step (1-18) */
stepId?: number;
/** Step name for human readability */
stepName?: string;
/** Adapter or component name */
adapter?: string;
/** Operation duration in milliseconds */
durationMs?: number;
/** Additional arbitrary metadata */
[key: string]: unknown;
}

View File

@@ -0,0 +1,4 @@
/**
* Log levels in order of severity (lowest to highest)
*/
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';

View File

@@ -0,0 +1,16 @@
import type { LogLevel } from './LoggerLogLevel';
import type { LogContext } from './LoggerContext';
import type { ILogger } from '@gridpilot/shared/logging/ILogger';
/**
* LoggerPort - Port interface for application-layer logging.
*/
export interface LoggerPort extends ILogger {
debug(message: string, context?: LogContext): void;
info(message: string, context?: LogContext): void;
warn(message: string, context?: LogContext): void;
error(message: string, error?: Error, context?: LogContext): void;
fatal(message: string, error?: Error, context?: LogContext): void;
child(context: LogContext): LoggerPort;
flush(): Promise<void>;
}

View File

@@ -0,0 +1,7 @@
export type OverlayAction = { id: string; label: string; meta?: Record<string, unknown>; timeoutMs?: number }
export type ActionAck = { id: string; status: 'confirmed' | 'tentative' | 'failed'; reason?: string }
export interface OverlaySyncPort {
startAction(action: OverlayAction): Promise<ActionAck>
cancelAction(actionId: string): Promise<void>
}

View File

@@ -0,0 +1,62 @@
import { StepId } from '../../domain/value-objects/StepId';
import type { NavigationResultDTO } from '../dto/NavigationResultDTO';
import type { ClickResultDTO } from '../dto/ClickResultDTO';
import type { WaitResultDTO } from '../dto/WaitResultDTO';
import type { ModalResultDTO } from '../dto/ModalResultDTO';
import type { AutomationResultDTO } from '../dto/AutomationResultDTO';
import type { FormFillResultDTO } from '../dto/FormFillResultDTO';
/**
* Browser automation interface for Playwright-based automation.
*
* This interface defines the contract for browser automation using
* standard DOM manipulation via Playwright. All automation is done
* through browser DevTools protocol - no OS-level automation.
*/
export interface IBrowserAutomation {
/**
* Navigate to a URL.
*/
navigateToPage(url: string): Promise<NavigationResultDTO>;
/**
* Fill a form field by name or selector.
*/
fillFormField(fieldName: string, value: string): Promise<FormFillResultDTO>;
/**
* Click an element by selector or action name.
*/
clickElement(target: string): Promise<ClickResultDTO>;
/**
* Wait for an element to appear.
*/
waitForElement(target: string, maxWaitMs?: number): Promise<WaitResultDTO>;
/**
* Handle modal dialogs.
*/
handleModal(stepId: StepId, action: string): Promise<ModalResultDTO>;
/**
* Execute a complete workflow step.
*/
executeStep?(stepId: StepId, config: Record<string, unknown>): Promise<AutomationResultDTO>;
/**
* Initialize the browser connection.
* Returns an AutomationResult indicating success or failure.
*/
connect?(): Promise<AutomationResultDTO>;
/**
* Clean up browser resources.
*/
disconnect?(): Promise<void>;
/**
* Check if browser is connected and ready.
*/
isConnected?(): boolean;
}

View File

@@ -0,0 +1,11 @@
import { AutomationSession } from '../../domain/entities/AutomationSession';
import { SessionStateValue } from '../../domain/value-objects/SessionState';
export interface SessionRepositoryPort {
save(session: AutomationSession): Promise<void>;
findById(id: string): Promise<AutomationSession | null>;
update(session: AutomationSession): Promise<void>;
delete(id: string): Promise<void>;
findAll(): Promise<AutomationSession[]>;
findByState(state: SessionStateValue): Promise<AutomationSession[]>;
}

View File

@@ -0,0 +1,5 @@
import type { Result } from '../../../shared/result/Result';
export interface SessionValidatorPort {
validateSession(): Promise<Result<boolean>>;
}

View File

@@ -0,0 +1,3 @@
export interface IUserConfirmationPort {
confirm(message: string): Promise<boolean>;
}