You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							214 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							214 lines
						
					
					
						
							5.5 KiB
						
					
					
				| # Time Safari Architecture — Patterns and Examples | |
| 
 | |
| > **Agent role**: Reference this file for architectural patterns and | |
| > examples when working with TimeSafari architecture design. | |
| 
 | |
| ## Architectural Patterns | |
| 
 | |
| ### Factory Pattern Implementation | |
| 
 | |
| ```typescript | |
| // PlatformServiceFactory.ts | |
| export class PlatformServiceFactory { | |
|   private static instance: PlatformServiceFactory; | |
| 
 | |
|   static getInstance(): PlatformServiceFactory { | |
|     if (!PlatformServiceFactory.instance) { | |
|       PlatformServiceFactory.instance = new PlatformServiceFactory(); | |
|     } | |
|     return PlatformServiceFactory.instance; | |
|   } | |
| 
 | |
|   getQRScannerService(): QRScannerService { | |
|     const platform = process.env.VITE_PLATFORM; | |
| 
 | |
|     switch (platform) { | |
|       case 'web': | |
|         return new WebInlineQRScanner(); | |
|       case 'capacitor': | |
|         return new CapacitorQRScanner(); | |
|       case 'electron': | |
|         return new ElectronQRScanner(); | |
|       default: | |
|         throw new Error(`Unsupported platform: ${platform}`); | |
|     } | |
|   } | |
| } | |
| ``` | |
| 
 | |
| ### Service Interface Definition | |
| 
 | |
| ```typescript | |
| // interfaces/QRScannerService.ts | |
| export interface QRScannerService { | |
|   startScanning(): Promise<void>; | |
|   stopScanning(): Promise<void>; | |
|   addListener(event: string, callback: Function): void; | |
|   removeListener(event: string, callback: Function): void; | |
| } | |
| ``` | |
| 
 | |
| ### Platform-Specific Implementation | |
| 
 | |
| ```typescript | |
| // services/QRScanner/WebInlineQRScanner.ts | |
| export class WebInlineQRScanner implements QRScannerService { | |
|   private listeners: Map<string, Function[]> = new Map(); | |
| 
 | |
|   async startScanning(): Promise<void> { | |
|     // Web-specific implementation | |
|     const stream = await navigator.mediaDevices.getUserMedia({ video: true }); | |
|     // Process video stream for QR codes | |
|   } | |
| 
 | |
|   async stopScanning(): Promise<void> { | |
|     // Stop video stream | |
|   } | |
| 
 | |
|   addListener(event: string, callback: Function): void { | |
|     if (!this.listeners.has(event)) { | |
|       this.listeners.set(event, []); | |
|     } | |
|     this.listeners.get(event)!.push(callback); | |
|   } | |
| 
 | |
|   removeListener(event: string, callback: Function): void { | |
|     const callbacks = this.listeners.get(event); | |
|     if (callbacks) { | |
|       const index = callbacks.indexOf(callback); | |
|       if (index > -1) { | |
|         callbacks.splice(index, 1); | |
|       } | |
|     } | |
|   } | |
| } | |
| ``` | |
| 
 | |
| ## Deep Linking Implementation | |
| 
 | |
| ### URL Format | |
| 
 | |
| ``` | |
| timesafari://<route>[/<param>][?query=value] | |
| ``` | |
| 
 | |
| ### Web Implementation | |
| 
 | |
| ```typescript | |
| // router/index.ts | |
| router.beforeEach((to, from, next) => { | |
|   // Parse deep link parameters | |
|   if (to.query.deepLink) { | |
|     const deepLink = to.query.deepLink as string; | |
|     // Process deep link | |
|     handleDeepLink(deepLink); | |
|   } | |
|   next(); | |
| }); | |
| 
 | |
| function handleDeepLink(deepLink: string) { | |
|   // Parse and route deep link | |
|   const url = new URL(deepLink); | |
|   const route = url.pathname; | |
|   const params = url.searchParams; | |
| 
 | |
|   // Navigate to appropriate route | |
|   router.push({ name: route, query: Object.fromEntries(params) }); | |
| } | |
| ``` | |
| 
 | |
| ### Capacitor Implementation | |
| 
 | |
| ```typescript | |
| // main.capacitor.ts | |
| import { App } from '@capacitor/app'; | |
| 
 | |
| App.addListener('appUrlOpen', (data) => { | |
|   const url = data.url; | |
|   // Parse deep link and navigate | |
|   handleDeepLink(url); | |
| }); | |
| ``` | |
| 
 | |
| ## Platform Detection | |
| 
 | |
| ### Feature Detection vs Platform Detection | |
| 
 | |
| ```typescript | |
| // ✅ Good: Feature detection | |
| function hasCameraAccess(): boolean { | |
|   return 'mediaDevices' in navigator && | |
|          'getUserMedia' in navigator.mediaDevices; | |
| } | |
| 
 | |
| // ❌ Bad: Platform detection | |
| function isWeb(): boolean { | |
|   return process.env.VITE_PLATFORM === 'web'; | |
| } | |
| ``` | |
| 
 | |
| ### Conditional Imports | |
| 
 | |
| ```typescript | |
| // services/platforms/index.ts | |
| export async function getPlatformService() { | |
|   const platform = process.env.VITE_PLATFORM; | |
| 
 | |
|   switch (platform) { | |
|     case 'capacitor': | |
|       const { CapacitorPlatformService } = | |
|         await import('./CapacitorPlatformService'); | |
|       return new CapacitorPlatformService(); | |
|     case 'electron': | |
|       const { ElectronPlatformService } = | |
|         await import('./ElectronPlatformService'); | |
|       return new ElectronPlatformService(); | |
|     default: | |
|       const { WebPlatformService } = | |
|         await import('./WebPlatformService'); | |
|       return new WebPlatformService(); | |
|   } | |
| } | |
| ``` | |
| 
 | |
| --- | |
| 
 | |
| **See also**: | |
| 
 | |
| - `.cursor/rules/app/architectural_decision_record.mdc` for core | |
|   architecture principles | |
| - `.cursor/rules/app/architectural_implementation.mdc` for | |
|   implementation details | |
| - `.cursor/rules/app/architectural_examples.mdc` for examples and | |
|   testing patterns | |
| 
 | |
| **Status**: Active patterns and examples | |
| **Priority**: Medium | |
| **Estimated Effort**: Ongoing reference | |
| **Dependencies**: architectural_decision_record.mdc, | |
|   architectural_implementation.mdc | |
| **Stakeholders**: Development team, Architecture team | |
| 
 | |
| ## Model Implementation Checklist | |
| 
 | |
| ### Before Architectural Patterns | |
| 
 | |
| - [ ] **Pattern Selection**: Choose appropriate architectural pattern for the use | |
|   case | |
| - [ ] **Platform Analysis**: Identify platform-specific requirements | |
| - [ ] **Service Planning**: Plan service structure and dependencies | |
| - [ ] **Testing Strategy**: Plan testing approach for the pattern | |
| 
 | |
| ### During Architectural Patterns | |
| 
 | |
| - [ ] **Pattern Implementation**: Implement chosen architectural pattern | |
| - [ ] **Platform Abstraction**: Use platform abstraction layers appropriately | |
| - [ ] **Service Composition**: Compose services using dependency injection | |
| - [ ] **Interface Design**: Provide clear interfaces and contracts | |
| 
 | |
| ### After Architectural Patterns | |
| 
 | |
| - [ ] **Pattern Validation**: Verify pattern is implemented correctly | |
| - [ ] **Platform Testing**: Test across all target platforms | |
| - [ ] **Service Testing**: Test service composition and dependencies | |
| - [ ] **Documentation**: Update architectural patterns documentation
 | |
| 
 |