- Remove legacy rule files (documentation.mdc, general_development.mdc, etc.) - Implement new meta-rule system with core, app, and feature categories - Add meta-rule files for different workflows (bug diagnosis, feature planning, etc.) - Create organized directory structure: core/, app/, features/, database/, etc. - Add comprehensive README.md for rules documentation - Establish new rule architecture with always-on and workflow-specific rules This restructuring improves rule organization, enables better workflow management, and provides clearer separation of concerns for different development tasks.
247 lines
5.8 KiB
Plaintext
247 lines
5.8 KiB
Plaintext
# Time Safari Architecture — Examples and Testing
|
|
|
|
> **Agent role**: Reference this file for architectural examples and
|
|
testing patterns when working with TimeSafari architecture.
|
|
|
|
## Error Handling Patterns
|
|
|
|
### Global Error Handler
|
|
|
|
```typescript
|
|
|
|
// main.ts
|
|
app.config.errorHandler = (err, instance, info) => {
|
|
const componentName = instance?.$options?.name || 'Unknown';
|
|
logger.error(`[${componentName}] Vue error`, err, info);
|
|
};
|
|
|
|
window.addEventListener('unhandledrejection', (event) => {
|
|
logger.error('[Global] Unhandled promise rejection', event.reason);
|
|
});
|
|
|
|
```
|
|
|
|
### Platform-Specific Error Wrapping
|
|
|
|
```typescript
|
|
|
|
// services/platforms/CapacitorPlatformService.ts
|
|
export class CapacitorPlatformService {
|
|
async getFileContents(path: string): Promise<string> {
|
|
try {
|
|
const result = await Filesystem.readFile({
|
|
path: path,
|
|
encoding: 'utf8'
|
|
});
|
|
return result.data;
|
|
} catch (error) {
|
|
logger.error('[Capacitor API Error] Failed to read file', error, path);
|
|
throw new Error(`Failed to read file: ${path}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Testing Patterns
|
|
|
|
### Platform-Specific Test Skipping
|
|
|
|
```typescript
|
|
|
|
// tests/QRScanner.test.ts
|
|
describe('QRScanner Service', () => {
|
|
test('should start scanning on web', async () => {
|
|
test.skip(process.env.VITE_PLATFORM !== 'web', 'Web-only test');
|
|
|
|
const scanner = new WebInlineQRScanner();
|
|
await scanner.startScanning();
|
|
// Assert scanning started
|
|
});
|
|
|
|
test('should start scanning on mobile', async () => {
|
|
test.skip(process.env.VITE_PLATFORM !== 'capacitor', 'Mobile-only test');
|
|
|
|
const scanner = new CapacitorQRScanner();
|
|
await scanner.startScanning();
|
|
// Assert scanning started
|
|
});
|
|
});
|
|
|
|
```
|
|
|
|
### Mock Service Testing
|
|
|
|
```typescript
|
|
|
|
// tests/mocks/QRScannerMock.ts
|
|
export class QRScannerMock implements QRScannerService {
|
|
private isScanning = false;
|
|
private listeners: Map<string, Function[]> = new Map();
|
|
|
|
async startScanning(): Promise<void> {
|
|
this.isScanning = true;
|
|
this.emit('scanningStarted');
|
|
}
|
|
|
|
async stopScanning(): Promise<void> {
|
|
this.isScanning = false;
|
|
this.emit('scanningStopped');
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
private emit(event: string, ...args: any[]): void {
|
|
const callbacks = this.listeners.get(event);
|
|
if (callbacks) {
|
|
callbacks.forEach(callback => callback(...args));
|
|
}
|
|
}
|
|
|
|
getScanningState(): boolean {
|
|
return this.isScanning;
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Integration Examples
|
|
|
|
### Service Composition
|
|
|
|
```typescript
|
|
|
|
// services/QRScannerService.ts
|
|
export class QRScannerService {
|
|
constructor(
|
|
private platformService: PlatformService,
|
|
private notificationService: NotificationService
|
|
) {}
|
|
|
|
async startScanning(): Promise<void> {
|
|
try {
|
|
await this.platformService.startCamera();
|
|
this.notificationService.show('Camera started');
|
|
} catch (error) {
|
|
this.notificationService.showError('Failed to start camera');
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
### Component Integration
|
|
|
|
```typescript
|
|
|
|
// components/QRScannerDialog.vue
|
|
export default class QRScannerDialog extends Vue {
|
|
@Inject() private qrScannerService!: QRScannerService;
|
|
|
|
async mounted() {
|
|
try {
|
|
await this.qrScannerService.startScanning();
|
|
} catch (error) {
|
|
this.$notify.error('Failed to start scanner');
|
|
}
|
|
}
|
|
|
|
beforeDestroy() {
|
|
this.qrScannerService.stopScanning();
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Service Design
|
|
|
|
- Keep services focused and single-purpose
|
|
|
|
- Use dependency injection for service composition
|
|
|
|
- Implement proper error handling and logging
|
|
|
|
- Provide clear interfaces and contracts
|
|
|
|
### Testing Strategy
|
|
|
|
- Test platform-specific behavior separately
|
|
|
|
- Use mocks for external dependencies
|
|
|
|
- Test error conditions and edge cases
|
|
|
|
- Validate service contracts and interfaces
|
|
|
|
### Error Handling
|
|
|
|
- Log errors with appropriate context
|
|
|
|
- Provide user-friendly error messages
|
|
|
|
- Implement graceful degradation
|
|
|
|
- Handle platform-specific error scenarios
|
|
|
|
---
|
|
|
|
**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_patterns.mdc` for core patterns
|
|
|
|
**Status**: Active examples and testing guide
|
|
**Priority**: Medium
|
|
**Estimated Effort**: Ongoing reference
|
|
**Dependencies**: architectural_patterns.mdc
|
|
**Stakeholders**: Development team, Testing team
|
|
|
|
## Model Implementation Checklist
|
|
|
|
### Before Architectural Examples
|
|
|
|
- [ ] **Pattern Selection**: Choose appropriate architectural pattern for the use
|
|
case
|
|
- [ ] **Service Design**: Plan service structure and dependencies
|
|
- [ ] **Testing Strategy**: Plan testing approach for the example
|
|
- [ ] **Error Handling**: Plan error handling and logging strategy
|
|
|
|
### During Architectural Examples
|
|
|
|
- [ ] **Service Implementation**: Implement focused, single-purpose services
|
|
- [ ] **Dependency Injection**: Use proper dependency injection patterns
|
|
- [ ] **Error Handling**: Implement proper error handling and logging
|
|
- [ ] **Interface Design**: Provide clear interfaces and contracts
|
|
|
|
### After Architectural Examples
|
|
|
|
- [ ] **Testing Execution**: Test platform-specific behavior separately
|
|
- [ ] **Service Validation**: Validate service contracts and interfaces
|
|
- [ ] **Error Testing**: Test error conditions and edge cases
|
|
- [ ] **Documentation**: Update architectural examples documentation
|