# โš™๏ธ Core Services Overview > **Shared infrastructure services** providing foundational functionality across all modules with reactive architecture, dependency injection, and lifecycle management. ## Table of Contents - [[#Service Architecture]] - [[#Available Services]] - [[#Service Lifecycle]] - [[#Dependency Injection]] - [[#Service Development]] - [[#Testing Services]] ## Service Architecture ### **BaseService Foundation** All core services extend the `BaseService` abstract class which provides: - **Reactive State Management** - Integration with Vue's reactivity system - **Lifecycle Management** - Standardized initialization and disposal - **Error Handling** - Consistent error patterns across services - **Type Safety** - Full TypeScript support with strict typing ```typescript abstract class BaseService { protected isInitialized = ref(false) protected isDisposed = ref(false) abstract initialize(): Promise abstract dispose(): Promise // Reactive state helpers protected createReactiveState(initialValue: T): Ref protected createComputedState(getter: () => T): ComputedRef } ``` ### **Service Registration Pattern** Services are registered in the dependency injection container during module installation: ```typescript // Service registration (in base module) container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub) container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService) container.provide(SERVICE_TOKENS.STORAGE_SERVICE, storageService) // Service consumption (anywhere in app) const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB) const auth = injectService(SERVICE_TOKENS.AUTH_SERVICE) ``` ## Available Services ### **AuthService** ๐Ÿ” **Purpose:** User authentication and identity management **Location:** `src/modules/base/auth/auth-service.ts` **Token:** `SERVICE_TOKENS.AUTH_SERVICE` **Key Features:** - **Key Management** - Secure generation, import, and storage of Nostr keys - **User Sessions** - Persistent authentication with encrypted storage - **Profile Management** - User profile creation and updates - **Security** - Client-side key handling with no server storage **Reactive State:** ```typescript interface AuthService { user: Ref // Current authenticated user isAuthenticated: ComputedRef // Authentication status isLoading: Ref // Loading state loginError: Ref // Login error message } ``` **Key Methods:** - `generateKeyPair()` - Create new Nostr key pair - `loginWithPrivateKey(privateKey: string)` - Authenticate with existing key - `logout()` - Clear session and user data - `updateProfile(profile: UserMetadata)` - Update user profile **See:** [[authentication|๐Ÿ“– Authentication Service Documentation]] ### **RelayHub** ๐ŸŒ **Purpose:** Centralized Nostr relay connection management **Location:** `src/modules/base/nostr/relay-hub.ts` **Token:** `SERVICE_TOKENS.RELAY_HUB` **Key Features:** - **Connection Management** - Automatic connection, reconnection, and failover - **Event Publishing** - Reliable event publishing across multiple relays - **Subscription Management** - Efficient event subscriptions with deduplication - **Performance Monitoring** - Relay latency and success rate tracking **Reactive State:** ```typescript interface RelayHub { connectedRelays: Ref // Currently connected relays connectionStatus: ComputedRef // Overall connection status relayStats: Ref> // Per-relay statistics isConnecting: Ref // Connection in progress } ``` **Key Methods:** - `connect(relays: string[])` - Connect to relay URLs - `publishEvent(event: NostrEvent)` - Publish event to all connected relays - `subscribe(filters: Filter[], callback: EventCallback)` - Subscribe to events - `getRelayInfo(url: string)` - Get relay connection information **See:** [[../01-architecture/relay-hub|๐Ÿ“– Relay Hub Architecture Documentation]] ### **StorageService** ๐Ÿ’พ **Purpose:** User-scoped local storage operations **Location:** `src/core/services/StorageService.ts` **Token:** `SERVICE_TOKENS.STORAGE_SERVICE` **Key Features:** - **User-Scoped Storage** - Automatic key prefixing per authenticated user - **Type-Safe Operations** - Strongly typed get/set operations with JSON serialization - **Reactive Updates** - Optional reactive storage with Vue refs - **Migration Support** - Data migration between storage schema versions **Key Methods:** ```typescript interface StorageService { setUserData(key: string, data: T): void getUserData(key: string, defaultValue?: T): T | undefined removeUserData(key: string): void clearUserData(): void // Reactive variants getReactiveUserData(key: string, defaultValue: T): Ref setReactiveUserData(key: string, ref: Ref): void } ``` **Storage Patterns:** - User-specific keys: `user:{pubkey}:settings` - Global application keys: `app:theme` - Module-specific keys: `user:{pubkey}:chat:contacts` **See:** [[storage-service|๐Ÿ“– Storage Service Documentation]] ### **ToastService** ๐Ÿ“ข **Purpose:** Application-wide notifications and user feedback **Location:** `src/core/services/ToastService.ts` **Token:** `SERVICE_TOKENS.TOAST_SERVICE` **Key Features:** - **Context-Specific Methods** - Pre-configured toasts for common scenarios - **Consistent Messaging** - Standardized success, error, and info messages - **Accessibility** - Screen reader compatible notifications - **Customizable** - Support for custom toast content and actions **Organized by Context:** ```typescript interface ToastService { // Authentication context auth: { loginSuccess(): void loginError(error?: string): void logoutSuccess(): void keyGenerated(): void } // Payment context payment: { invoiceCreated(): void paymentReceived(): void paymentFailed(error?: string): void } // Clipboard operations clipboard: { copied(item?: string): void copyFailed(): void } // General operations operation: { success(message: string): void error(message: string): void info(message: string): void } } ``` **See:** [[toast-service|๐Ÿ“– Toast Service Documentation]] ### **EventBus** ๐Ÿ“ก **Purpose:** Inter-module communication and event coordination **Location:** `src/core/services/EventBus.ts` **Token:** `SERVICE_TOKENS.EVENT_BUS` **Key Features:** - **Type-Safe Events** - Strongly typed event payloads - **Module Isolation** - Clean communication between modules - **Event Namespacing** - Organized event names by domain - **Subscription Management** - Easy subscribe/unsubscribe patterns **Event Categories:** ```typescript interface EventBusEvents { // User events 'user:authenticated': { userId: string, profile: UserMetadata } 'user:profile-updated': { userId: string, changes: Partial } 'user:logout': { userId: string } // Chat events 'chat:message-received': { messageId: string, from: string, content: string } 'chat:typing-start': { from: string, chatId: string } // Payment events 'payment:invoice-created': { invoiceId: string, amount: number } 'payment:received': { invoiceId: string, amount: number } // Relay events 'relay:connected': { url: string } 'relay:disconnected': { url: string, reason?: string } } ``` **See:** [[../01-architecture/event-bus|๐Ÿ“– Event Bus Communication Documentation]] ## Service Lifecycle ### **Initialization Phase** Services are initialized in dependency order during application startup: ```typescript // 1. Base services (no dependencies) await authService.initialize() await storageService.initialize() // 2. Infrastructure services (depend on base services) await relayHub.initialize() await toastService.initialize() // 3. Feature services (depend on infrastructure) await chatService.initialize() await eventsService.initialize() ``` ### **Service Dependencies** Services declare their dependencies through constructor injection: ```typescript class ChatService extends BaseService { constructor( private auth = injectService(SERVICE_TOKENS.AUTH_SERVICE), private relayHub = injectService(SERVICE_TOKENS.RELAY_HUB), private storage = injectService(SERVICE_TOKENS.STORAGE_SERVICE), private eventBus = injectService(SERVICE_TOKENS.EVENT_BUS) ) { super() } } ``` ### **Disposal Phase** Services are disposed in reverse dependency order during application shutdown: ```typescript async dispose(): Promise { // Clean up subscriptions this.subscriptions.forEach(sub => sub.close()) // Save persistent state await this.storage.setUserData('chat:messages', this.messages.value) // Mark as disposed this.isDisposed.value = true } ``` ## Dependency Injection ### **Service Tokens** Type-safe service tokens prevent runtime errors and enable proper TypeScript inference: ```typescript export const SERVICE_TOKENS = { AUTH_SERVICE: Symbol('AUTH_SERVICE') as InjectionKey, RELAY_HUB: Symbol('RELAY_HUB') as InjectionKey, STORAGE_SERVICE: Symbol('STORAGE_SERVICE') as InjectionKey, TOAST_SERVICE: Symbol('TOAST_SERVICE') as InjectionKey, } as const ``` ### **Service Registration** Services are registered during module installation: ```typescript // In base module installation export async function installBaseModule(app: App) { // Create service instances const authService = new AuthService() const relayHub = new RelayHub() const storageService = new StorageService() // Register in container container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService) container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub) container.provide(SERVICE_TOKENS.STORAGE_SERVICE, storageService) // Initialize services await authService.initialize() await relayHub.initialize() } ``` ### **Service Consumption** Services are injected where needed using type-safe injection: ```typescript // In composables export function useAuth() { const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) return { user: authService.user, login: authService.login, logout: authService.logout } } // In components ``` ## Service Development ### **Creating a New Service** #### 1. Service Class Implementation ```typescript // src/core/services/MyService.ts export class MyService extends BaseService { // Reactive state private readonly _data = ref([]) private readonly _isLoading = ref(false) // Public readonly access to state public readonly data = readonly(this._data) public readonly isLoading = readonly(this._isLoading) constructor( private dependency = injectService(SERVICE_TOKENS.DEPENDENCY) ) { super() } async initialize(): Promise { // Initialization logic await this.loadInitialData() this.isInitialized.value = true } async dispose(): Promise { // Cleanup logic this._data.value = [] this.isDisposed.value = true } // Public methods async createItem(item: CreateItemRequest): Promise { this._isLoading.value = true try { const newItem = await this.dependency.create(item) this._data.value.push(newItem) return newItem } finally { this._isLoading.value = false } } } ``` #### 2. Service Token Registration ```typescript // Add to SERVICE_TOKENS export const SERVICE_TOKENS = { // ... existing tokens MY_SERVICE: Symbol('MY_SERVICE') as InjectionKey, } as const ``` #### 3. Service Registration in Module ```typescript // In module installation const myService = new MyService() container.provide(SERVICE_TOKENS.MY_SERVICE, myService) await myService.initialize() ``` ### **Service Best Practices** #### **Reactive State Management** - Use `ref()` for mutable state, `readonly()` for public access - Provide computed properties for derived state - Use `watch()` and `watchEffect()` for side effects #### **Error Handling** - Throw descriptive errors with proper types - Use try/catch blocks with proper cleanup - Log errors appropriately for debugging #### **Performance Optimization** - Implement proper subscription cleanup in `dispose()` - Use debouncing for frequent operations - Cache expensive computations with `computed()` ## Testing Services ### **Service Unit Tests** ```typescript // tests/unit/services/MyService.test.ts describe('MyService', () => { let service: MyService let mockDependency: MockType beforeEach(() => { // Setup mocks mockDependency = createMockService() // Create service with mocks service = new MyService(mockDependency) }) afterEach(async () => { await service.dispose() }) it('should initialize correctly', async () => { await service.initialize() expect(service.isInitialized.value).toBe(true) expect(service.data.value).toEqual([]) }) it('should create items', async () => { await service.initialize() const item = await service.createItem({ name: 'test' }) expect(service.data.value).toContain(item) expect(mockDependency.create).toHaveBeenCalledWith({ name: 'test' }) }) }) ``` ### **Integration Tests** ```typescript // tests/integration/services/ServiceIntegration.test.ts describe('Service Integration', () => { let container: DIContainer beforeEach(async () => { container = createTestContainer() await installTestServices(container) }) it('should handle cross-service communication', async () => { const authService = container.get(SERVICE_TOKENS.AUTH_SERVICE) const chatService = container.get(SERVICE_TOKENS.CHAT_SERVICE) await authService.login('test-key') const message = await chatService.sendMessage('Hello') expect(message.author).toBe(authService.user.value?.pubkey) }) }) ``` ## See Also ### Service Documentation - **[[authentication|๐Ÿ” Authentication Service]]** - User identity and session management - **[[storage-service|๐Ÿ’พ Storage Service]]** - User-scoped data persistence - **[[toast-service|๐Ÿ“ข Toast Service]]** - User notifications and feedback - **[[visibility-service|๐Ÿ‘๏ธ Visibility Service]]** - Dynamic UI component control ### Architecture References - **[[../01-architecture/dependency-injection|โš™๏ธ Dependency Injection]]** - DI container system - **[[../01-architecture/event-bus|๐Ÿ“ก Event Bus Communication]]** - Inter-service messaging - **[[../02-modules/index|๐Ÿ“ฆ Module System]]** - How services integrate with modules - **[[../04-development/testing|๐Ÿงช Testing Guide]]** - Service testing patterns --- **Tags:** #services #architecture #dependency-injection #reactive-state **Last Updated:** 2025-09-06 **Author:** Development Team