# Services

Services group related functions together for better organization and discovery.

## Basic Service

```typescript
// src/index.ts
import { definePlugin } from '@majkapp/plugin-kit';

const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
  .pluginRoot(__dirname)

  // Define functions first
  .function('health', { /* ... */, tags: ['monitoring'] })
  .function('getStats', { /* ... */, tags: ['monitoring'] })
  .function('getMetrics', { /* ... */, tags: ['monitoring'] })

  // Group into service
  .service('plugin:my-plugin:monitoring', {
    type: '@my-plugin/monitoring',
    metadata: {
      name: 'Monitoring Service',
      description: 'Health checks and system metrics',
      version: '1.0.0'
    },
    discoverable: true  // Make service discoverable by other plugins
  })
    .withFunction('health', {
      examples: ['Check plugin health status'],
      tags: ['health', 'status']
    })
    .withFunction('getStats', {
      examples: ['Get system statistics'],
      tags: ['stats', 'metrics']
    })
    .withFunction('getMetrics', {
      examples: ['Get detailed metrics'],
      tags: ['metrics', 'monitoring']
    })
  .endService()

  .build();
```

## Real Example from full-featured

```typescript
// samples/full-featured/src/index.ts

// Define monitoring functions
.function('health', {
  description: 'Returns plugin health status',
  input: { /* ... */ },
  output: { /* ... */ },
  handler: async (input, ctx) => {
    return {
      status: 'ok',
      timestamp: new Date().toISOString()
    };
  },
  tags: ['monitoring']
})

.function('getStats', {
  description: 'Get plugin statistics',
  input: { /* ... */ },
  output: { /* ... */ },
  handler: async (input, ctx) => {
    const conversations = await ctx.majk.conversations.list();
    const teammates = await ctx.majk.teammates.list();

    return {
      conversationCount: conversations.length,
      teammateCount: teammates.length,
      timestamp: new Date().toISOString()
    };
  },
  tags: ['monitoring']
})

// Group into service
.service('plugin:full-featured:monitoring', {
  type: '@full-featured/monitoring',
  metadata: {
    name: 'Full Featured Monitoring',
    description: 'Health checks and statistics for the Full Featured plugin',
    version: '1.0.0',
    author: 'Full Featured Team'
  },
  discoverable: true
})
  .withFunction('health', {
    examples: [
      'Get current health status',
      'Check if plugin is running correctly'
    ],
    tags: ['health', 'status', 'monitoring']
  })
  .withFunction('getStats', {
    examples: [
      'Get conversation and teammate counts',
      'View system statistics'
    ],
    tags: ['stats', 'metrics', 'monitoring']
  })
.endService()
```

## Service with Multiple Functions

```typescript
// Events management service
.function('getEvents', {
  description: 'Get all logged events from the event bus',
  input: { /* ... */ },
  output: { /* ... */ },
  handler: async (input, ctx) => {
    const events = await ctx.storage.get('events') || [];
    return { events, count: events.length };
  },
  tags: ['events']
})

.function('clearEvents', {
  description: 'Clear the event log',
  input: { /* ... */ },
  output: { /* ... */ },
  handler: async (input, ctx) => {
    const events = await ctx.storage.get('events') || [];
    await ctx.storage.set('events', []);
    return { success: true, clearedCount: events.length };
  },
  tags: ['events', 'mutations']
})

.service('plugin:my-plugin:events', {
  type: '@my-plugin/events',
  metadata: {
    name: 'Event Management',
    description: 'Manage and monitor system events',
    version: '1.0.0'
  }
})
  .withFunction('getEvents', {
    examples: ['List all logged events', 'View event history'],
    tags: ['read', 'query']
  })
  .withFunction('clearEvents', {
    examples: ['Clear event log', 'Reset event history'],
    tags: ['write', 'mutation']
  })
.endService()
```

## Multiple Services

Organize functions into logical groups:

```typescript
const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
  .pluginRoot(__dirname)

  // Monitoring functions
  .function('health', { /* ... */, tags: ['monitoring'] })
  .function('getStats', { /* ... */, tags: ['monitoring'] })

  // Analytics functions
  .function('getAnalytics', { /* ... */, tags: ['analytics'] })
  .function('getChartData', { /* ... */, tags: ['analytics'] })

  // User management functions
  .function('getUsers', { /* ... */, tags: ['users'] })
  .function('getUserDetail', { /* ... */, tags: ['users'] })

  // Monitoring service
  .service('plugin:my-plugin:monitoring', {
    type: '@my-plugin/monitoring',
    metadata: {
      name: 'Monitoring Service',
      description: 'Health and statistics',
      version: '1.0.0'
    }
  })
    .withFunction('health')
    .withFunction('getStats')
  .endService()

  // Analytics service
  .service('plugin:my-plugin:analytics', {
    type: '@my-plugin/analytics',
    metadata: {
      name: 'Analytics Service',
      description: 'Usage analytics and reporting',
      version: '1.0.0'
    }
  })
    .withFunction('getAnalytics')
    .withFunction('getChartData')
  .endService()

  // User service
  .service('plugin:my-plugin:users', {
    type: '@my-plugin/users',
    metadata: {
      name: 'User Service',
      description: 'User data and management',
      version: '1.0.0'
    }
  })
    .withFunction('getUsers')
    .withFunction('getUserDetail')
  .endService()

  .build();
```

## Service Metadata

Service metadata helps with discovery and documentation:

```typescript
.service('plugin:my-plugin:service-name', {
  type: '@my-plugin/service-type',  // Unique type identifier
  metadata: {
    name: 'Human-Readable Service Name',
    description: 'Detailed description of what this service does',
    version: '1.0.0',
    author: 'Team Name',  // Optional
    homepage: 'https://docs.example.com/service',  // Optional
    tags: ['tag1', 'tag2']  // Optional
  },
  discoverable: true  // Allow other plugins to discover this service
})
```

## Function Enrichment

Add service-specific metadata to functions:

```typescript
.withFunction('functionName', {
  examples: [
    'Example use case 1',
    'Example use case 2'
  ],
  tags: ['tag1', 'tag2'],  // Additional tags for this function in service context
  metadata: {  // Optional custom metadata
    rateLimit: 100,
    requiresAuth: true
  }
})
```

## Best Practices

### 1. Organize by Domain

```typescript
// Good: Functions grouped by business domain
.service('plugin:my-plugin:analytics', { /* ... */ })
  .withFunction('getAnalytics')
  .withFunction('getChartData')
  .withFunction('exportReport')
.endService()

.service('plugin:my-plugin:notifications', { /* ... */ })
  .withFunction('sendNotification')
  .withFunction('getNotificationHistory')
.endService()
```

### 2. Keep Services Focused

```typescript
// Good: Focused service with related functions
.service('plugin:my-plugin:events', { /* ... */ })
  .withFunction('getEvents')
  .withFunction('clearEvents')
  .withFunction('filterEvents')
.endService()

// Bad: Too broad, unrelated functions
.service('plugin:my-plugin:everything', { /* ... */ })
  .withFunction('getEvents')
  .withFunction('sendEmail')  // Unrelated
  .withFunction('calculateTax')  // Unrelated
.endService()
```

### 3. Use Descriptive Metadata

```typescript
.service('plugin:my-plugin:monitoring', {
  type: '@my-plugin/monitoring',
  metadata: {
    name: 'System Monitoring',  // Clear name
    description: 'Provides health checks, system statistics, and performance metrics for the plugin',  // Detailed description
    version: '1.0.0'
  }
})
```

## Service Naming Convention

**Format:** `plugin:{plugin-id}:{service-name}`

Examples:
- `plugin:my-plugin:monitoring`
- `plugin:my-plugin:analytics`
- `plugin:my-plugin:data-management`
- `plugin:full-featured:events`

## Testing Services

Services are tested through their functions:

```typescript
// tests/plugin/functions/unit/monitoring.test.js
import { test, invoke, mock } from '@majkapp/plugin-test';
import assert from 'assert';

test('monitoring service - health check', async () => {
  const context = mock().build();
  const result = await invoke('health', {}, { context });

  assert.strictEqual(result.status, 'ok');
  assert.ok(result.timestamp);
});

test('monitoring service - get stats', async () => {
  const context = mock()
    .withMajkData({
      conversations: [{ id: '1' }, { id: '2' }],
      teammates: [{ id: 't1' }]
    })
    .build();

  const result = await invoke('getStats', {}, { context });

  assert.strictEqual(result.conversationCount, 2);
  assert.strictEqual(result.teammateCount, 1);
});
```

## Next Steps

Run `npx @majkapp/plugin-kit --functions` - Define functions for services
Run `npx @majkapp/plugin-kit --testing` - Test your services
Run `npx @majkapp/plugin-kit --lifecycle` - Service initialization with onReady
