/** * F5 Integration Module - Type Definitions * * Core types for Jira/Redmine integration with bi-directional sync support. */ /** * F5 Internal Issue Format - normalized representation for all PM systems */ export interface F5Issue { id: string; externalId?: string; summary: string; description?: string; issueType: F5IssueType; priority: F5Priority; status: F5Status; assignee?: string; reporter?: string; labels?: string[]; components?: string[]; dueDate?: Date; createdAt?: Date; updatedAt?: Date; customFields?: Record; attachments?: F5Attachment[]; syncMeta?: { source: 'jira' | 'redmine' | 'excel' | 'local'; sourceId: string; lastSyncAt: Date; hash: string; version: number; }; } /** * F5 Attachment - file attachments for issues */ export interface F5Attachment { id: string; filename: string; mimeType: string; size: number; url?: string; localPath?: string; thumbnailUrl?: string; author?: string; createdAt?: Date; } export type F5IssueType = 'Bug' | 'Story' | 'Task' | 'Improvement' | 'Epic' | 'Subtask'; export type F5Priority = 'Highest' | 'High' | 'Medium' | 'Low' | 'Lowest'; export type F5Status = 'Open' | 'In Progress' | 'Done' | 'Closed' | 'Blocked' | 'Review'; /** * Universal adapter interface for PM systems (Jira, Redmine, etc.) */ export interface PMAdapter { readonly name: string; readonly version: string; connect(): Promise; disconnect(): Promise; testConnection(): Promise; getIssue(id: string): Promise; getIssues(filter: IssueFilter): Promise; createIssue(issue: Omit): Promise; updateIssue(id: string, updates: Partial): Promise; deleteIssue(id: string): Promise; bulkCreate(issues: Omit[]): Promise; bulkUpdate(updates: Array<{ id: string; changes: Partial; }>): Promise; getChangedSince(since: Date): Promise; getIssueHash(id: string): Promise; getAvailableFields(): Promise; getProjects(): Promise; getIssueTypes(): Promise; getPriorities(): Promise; getStatuses(): Promise; } export interface ConnectionTestResult { success: boolean; message: string; serverInfo?: { version: string; baseUrl: string; permissions?: string[]; }; error?: Error; } export interface IssueFilter { project?: string; issueType?: F5IssueType[]; status?: F5Status[]; priority?: F5Priority[]; assignee?: string; reporter?: string; labels?: string[]; createdAfter?: Date; updatedAfter?: Date; jql?: string; query?: string; maxResults?: number; startAt?: number; } export interface BulkOperationResult { total: number; successful: number; failed: number; results: Array<{ index: number; success: boolean; id?: string; error?: string; }>; } export interface FieldDefinition { id: string; name: string; type: 'string' | 'number' | 'date' | 'array' | 'option' | 'user'; required: boolean; options?: string[]; customField?: boolean; } export interface ProjectInfo { id: string; key: string; name: string; description?: string; } export interface IssueTypeInfo { id: string; name: string; description?: string; subtask: boolean; } export interface PriorityInfo { id: string; name: string; iconUrl?: string; } export interface StatusInfo { id: string; name: string; category: 'todo' | 'in_progress' | 'done'; } /** * Sync state tracking for bi-directional synchronization */ export interface SyncState { id: string; localIssue: F5Issue; remoteId: string; remoteSystem: 'jira' | 'redmine'; lastLocalHash: string; lastRemoteHash: string; lastSyncAt: Date; version: number; status: 'synced' | 'local_changed' | 'remote_changed' | 'conflict'; } /** * Conflict information when both sides have changes */ export interface SyncConflict { id: string; localIssue: F5Issue; remoteIssue: F5Issue; conflictingFields: string[]; localChanges: Record; remoteChanges: Record; detectedAt: Date; resolved: boolean; resolution?: ConflictResolution; } export type ConflictResolutionStrategy = 'local-wins' | 'remote-wins' | 'newest-wins' | 'manual' | 'merge'; export interface ConflictResolution { strategy: ConflictResolutionStrategy; resolvedAt: Date; resolvedBy?: string; mergedValues?: Record; } /** * Result of a sync operation */ export interface SyncResult { success: boolean; syncedAt: Date; direction: 'push' | 'pull' | 'bidirectional'; stats: { created: number; updated: number; deleted: number; conflicts: number; errors: number; }; conflicts: SyncConflict[]; errors: SyncError[]; details: SyncDetail[]; } export interface SyncError { issueId: string; operation: 'create' | 'update' | 'delete' | 'fetch'; message: string; error?: Error; } export interface SyncDetail { issueId: string; operation: 'created' | 'updated' | 'deleted' | 'skipped' | 'conflict'; direction: 'local_to_remote' | 'remote_to_local'; fields?: string[]; } /** * Jira-specific configuration */ export interface JiraConfig { baseUrl: string; apiVersion?: '2' | '3'; auth: JiraAuthConfig; project: string; defaultIssueType?: string; customFieldMappings?: Record; statusMappings?: Record; priorityMappings?: Record; issueTypeMappings?: Record; /** Fields to skip when creating/updating issues (e.g., ['duedate'] if not on screen) */ skipFields?: string[]; } export type JiraAuthConfig = { type: 'basic'; email: string; apiToken: string; } | { type: 'pat'; token: string; } | { type: 'oauth2'; clientId: string; clientSecret: string; accessToken?: string; refreshToken?: string; }; /** * Redmine-specific configuration */ export interface RedmineConfig { baseUrl: string; apiKey: string; project: string | number; defaultTracker?: string; customFieldMappings?: Record; statusMappings?: Record; priorityMappings?: Record; trackerMappings?: Record; } /** * Sync configuration */ export interface SyncConfig { enabled: boolean; direction: 'push' | 'pull' | 'bidirectional'; autoSync: boolean; syncInterval?: number; conflictStrategy: ConflictResolutionStrategy; fieldMappings?: Record; excludeFields?: string[]; filters?: IssueFilter; } /** * Complete integration configuration */ export interface IntegrationConfig { jira?: JiraConfig; redmine?: RedmineConfig; sync: SyncConfig; excel?: ExcelImportConfig; } export interface ExcelImportConfig { schemaDir: string; defaultSchema?: string; autoDetect: boolean; preserveExternalIds: boolean; } /** * Default issue type mappings for various languages */ export declare const DEFAULT_ISSUE_TYPE_MAPPINGS: Record; /** * Default priority mappings for various languages */ export declare const DEFAULT_PRIORITY_MAPPINGS: Record; /** * Default status mappings for various languages */ export declare const DEFAULT_STATUS_MAPPINGS: Record; /** * Type guard for checking if a value is a valid F5IssueType */ export declare function isF5IssueType(value: string): value is F5IssueType; /** * Type guard for checking if a value is a valid F5Priority */ export declare function isF5Priority(value: string): value is F5Priority; /** * Type guard for checking if a value is a valid F5Status */ export declare function isF5Status(value: string): value is F5Status; /** * Hash utility for change detection */ export declare function createIssueHash(issue: F5Issue): string; /** * Map external value to F5 type using mapping tables */ export declare function mapToF5IssueType(value: string, customMappings?: Record): F5IssueType; export declare function mapToF5Priority(value: string, customMappings?: Record): F5Priority; export declare function mapToF5Status(value: string, customMappings?: Record): F5Status;