@majkapp/plugin-kit 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/promptable-cli.js +35 -0
- package/dist/generator/generator.js +12 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/plugin-kit.d.ts +34 -1
- package/dist/plugin-kit.d.ts.map +1 -1
- package/dist/plugin-kit.js +87 -1
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/API.md +394 -0
- package/docs/CONFIG.md +428 -0
- package/docs/CONTEXT.md +500 -0
- package/docs/FULL.md +848 -0
- package/docs/FUNCTIONS.md +623 -0
- package/docs/HOOKS.md +532 -0
- package/docs/INDEX.md +486 -0
- package/docs/LIFECYCLE.md +490 -0
- package/docs/SCREENS.md +547 -0
- package/docs/SERVICES.md +350 -0
- package/docs/TESTING.md +593 -0
- package/docs/mcp-execution-api.md +490 -0
- package/package.json +18 -3
package/docs/SERVICES.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Services
|
|
2
|
+
|
|
3
|
+
Services group related functions together for better organization and discovery.
|
|
4
|
+
|
|
5
|
+
## Basic Service
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import { definePlugin } from '@majkapp/plugin-kit';
|
|
10
|
+
|
|
11
|
+
const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
|
|
12
|
+
.pluginRoot(__dirname)
|
|
13
|
+
|
|
14
|
+
// Define functions first
|
|
15
|
+
.function('health', { /* ... */, tags: ['monitoring'] })
|
|
16
|
+
.function('getStats', { /* ... */, tags: ['monitoring'] })
|
|
17
|
+
.function('getMetrics', { /* ... */, tags: ['monitoring'] })
|
|
18
|
+
|
|
19
|
+
// Group into service
|
|
20
|
+
.service('plugin:my-plugin:monitoring', {
|
|
21
|
+
type: '@my-plugin/monitoring',
|
|
22
|
+
metadata: {
|
|
23
|
+
name: 'Monitoring Service',
|
|
24
|
+
description: 'Health checks and system metrics',
|
|
25
|
+
version: '1.0.0'
|
|
26
|
+
},
|
|
27
|
+
discoverable: true // Make service discoverable by other plugins
|
|
28
|
+
})
|
|
29
|
+
.withFunction('health', {
|
|
30
|
+
examples: ['Check plugin health status'],
|
|
31
|
+
tags: ['health', 'status']
|
|
32
|
+
})
|
|
33
|
+
.withFunction('getStats', {
|
|
34
|
+
examples: ['Get system statistics'],
|
|
35
|
+
tags: ['stats', 'metrics']
|
|
36
|
+
})
|
|
37
|
+
.withFunction('getMetrics', {
|
|
38
|
+
examples: ['Get detailed metrics'],
|
|
39
|
+
tags: ['metrics', 'monitoring']
|
|
40
|
+
})
|
|
41
|
+
.endService()
|
|
42
|
+
|
|
43
|
+
.build();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Real Example from full-featured
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// samples/full-featured/src/index.ts
|
|
50
|
+
|
|
51
|
+
// Define monitoring functions
|
|
52
|
+
.function('health', {
|
|
53
|
+
description: 'Returns plugin health status',
|
|
54
|
+
input: { /* ... */ },
|
|
55
|
+
output: { /* ... */ },
|
|
56
|
+
handler: async (input, ctx) => {
|
|
57
|
+
return {
|
|
58
|
+
status: 'ok',
|
|
59
|
+
timestamp: new Date().toISOString()
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
tags: ['monitoring']
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
.function('getStats', {
|
|
66
|
+
description: 'Get plugin statistics',
|
|
67
|
+
input: { /* ... */ },
|
|
68
|
+
output: { /* ... */ },
|
|
69
|
+
handler: async (input, ctx) => {
|
|
70
|
+
const conversations = await ctx.majk.conversations.list();
|
|
71
|
+
const teammates = await ctx.majk.teammates.list();
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
conversationCount: conversations.length,
|
|
75
|
+
teammateCount: teammates.length,
|
|
76
|
+
timestamp: new Date().toISOString()
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
tags: ['monitoring']
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Group into service
|
|
83
|
+
.service('plugin:full-featured:monitoring', {
|
|
84
|
+
type: '@full-featured/monitoring',
|
|
85
|
+
metadata: {
|
|
86
|
+
name: 'Full Featured Monitoring',
|
|
87
|
+
description: 'Health checks and statistics for the Full Featured plugin',
|
|
88
|
+
version: '1.0.0',
|
|
89
|
+
author: 'Full Featured Team'
|
|
90
|
+
},
|
|
91
|
+
discoverable: true
|
|
92
|
+
})
|
|
93
|
+
.withFunction('health', {
|
|
94
|
+
examples: [
|
|
95
|
+
'Get current health status',
|
|
96
|
+
'Check if plugin is running correctly'
|
|
97
|
+
],
|
|
98
|
+
tags: ['health', 'status', 'monitoring']
|
|
99
|
+
})
|
|
100
|
+
.withFunction('getStats', {
|
|
101
|
+
examples: [
|
|
102
|
+
'Get conversation and teammate counts',
|
|
103
|
+
'View system statistics'
|
|
104
|
+
],
|
|
105
|
+
tags: ['stats', 'metrics', 'monitoring']
|
|
106
|
+
})
|
|
107
|
+
.endService()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Service with Multiple Functions
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Events management service
|
|
114
|
+
.function('getEvents', {
|
|
115
|
+
description: 'Get all logged events from the event bus',
|
|
116
|
+
input: { /* ... */ },
|
|
117
|
+
output: { /* ... */ },
|
|
118
|
+
handler: async (input, ctx) => {
|
|
119
|
+
const events = await ctx.storage.get('events') || [];
|
|
120
|
+
return { events, count: events.length };
|
|
121
|
+
},
|
|
122
|
+
tags: ['events']
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
.function('clearEvents', {
|
|
126
|
+
description: 'Clear the event log',
|
|
127
|
+
input: { /* ... */ },
|
|
128
|
+
output: { /* ... */ },
|
|
129
|
+
handler: async (input, ctx) => {
|
|
130
|
+
const events = await ctx.storage.get('events') || [];
|
|
131
|
+
await ctx.storage.set('events', []);
|
|
132
|
+
return { success: true, clearedCount: events.length };
|
|
133
|
+
},
|
|
134
|
+
tags: ['events', 'mutations']
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
.service('plugin:my-plugin:events', {
|
|
138
|
+
type: '@my-plugin/events',
|
|
139
|
+
metadata: {
|
|
140
|
+
name: 'Event Management',
|
|
141
|
+
description: 'Manage and monitor system events',
|
|
142
|
+
version: '1.0.0'
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
.withFunction('getEvents', {
|
|
146
|
+
examples: ['List all logged events', 'View event history'],
|
|
147
|
+
tags: ['read', 'query']
|
|
148
|
+
})
|
|
149
|
+
.withFunction('clearEvents', {
|
|
150
|
+
examples: ['Clear event log', 'Reset event history'],
|
|
151
|
+
tags: ['write', 'mutation']
|
|
152
|
+
})
|
|
153
|
+
.endService()
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Multiple Services
|
|
157
|
+
|
|
158
|
+
Organize functions into logical groups:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
|
|
162
|
+
.pluginRoot(__dirname)
|
|
163
|
+
|
|
164
|
+
// Monitoring functions
|
|
165
|
+
.function('health', { /* ... */, tags: ['monitoring'] })
|
|
166
|
+
.function('getStats', { /* ... */, tags: ['monitoring'] })
|
|
167
|
+
|
|
168
|
+
// Analytics functions
|
|
169
|
+
.function('getAnalytics', { /* ... */, tags: ['analytics'] })
|
|
170
|
+
.function('getChartData', { /* ... */, tags: ['analytics'] })
|
|
171
|
+
|
|
172
|
+
// User management functions
|
|
173
|
+
.function('getUsers', { /* ... */, tags: ['users'] })
|
|
174
|
+
.function('getUserDetail', { /* ... */, tags: ['users'] })
|
|
175
|
+
|
|
176
|
+
// Monitoring service
|
|
177
|
+
.service('plugin:my-plugin:monitoring', {
|
|
178
|
+
type: '@my-plugin/monitoring',
|
|
179
|
+
metadata: {
|
|
180
|
+
name: 'Monitoring Service',
|
|
181
|
+
description: 'Health and statistics',
|
|
182
|
+
version: '1.0.0'
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
.withFunction('health')
|
|
186
|
+
.withFunction('getStats')
|
|
187
|
+
.endService()
|
|
188
|
+
|
|
189
|
+
// Analytics service
|
|
190
|
+
.service('plugin:my-plugin:analytics', {
|
|
191
|
+
type: '@my-plugin/analytics',
|
|
192
|
+
metadata: {
|
|
193
|
+
name: 'Analytics Service',
|
|
194
|
+
description: 'Usage analytics and reporting',
|
|
195
|
+
version: '1.0.0'
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
.withFunction('getAnalytics')
|
|
199
|
+
.withFunction('getChartData')
|
|
200
|
+
.endService()
|
|
201
|
+
|
|
202
|
+
// User service
|
|
203
|
+
.service('plugin:my-plugin:users', {
|
|
204
|
+
type: '@my-plugin/users',
|
|
205
|
+
metadata: {
|
|
206
|
+
name: 'User Service',
|
|
207
|
+
description: 'User data and management',
|
|
208
|
+
version: '1.0.0'
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
.withFunction('getUsers')
|
|
212
|
+
.withFunction('getUserDetail')
|
|
213
|
+
.endService()
|
|
214
|
+
|
|
215
|
+
.build();
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Service Metadata
|
|
219
|
+
|
|
220
|
+
Service metadata helps with discovery and documentation:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
.service('plugin:my-plugin:service-name', {
|
|
224
|
+
type: '@my-plugin/service-type', // Unique type identifier
|
|
225
|
+
metadata: {
|
|
226
|
+
name: 'Human-Readable Service Name',
|
|
227
|
+
description: 'Detailed description of what this service does',
|
|
228
|
+
version: '1.0.0',
|
|
229
|
+
author: 'Team Name', // Optional
|
|
230
|
+
homepage: 'https://docs.example.com/service', // Optional
|
|
231
|
+
tags: ['tag1', 'tag2'] // Optional
|
|
232
|
+
},
|
|
233
|
+
discoverable: true // Allow other plugins to discover this service
|
|
234
|
+
})
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Function Enrichment
|
|
238
|
+
|
|
239
|
+
Add service-specific metadata to functions:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
.withFunction('functionName', {
|
|
243
|
+
examples: [
|
|
244
|
+
'Example use case 1',
|
|
245
|
+
'Example use case 2'
|
|
246
|
+
],
|
|
247
|
+
tags: ['tag1', 'tag2'], // Additional tags for this function in service context
|
|
248
|
+
metadata: { // Optional custom metadata
|
|
249
|
+
rateLimit: 100,
|
|
250
|
+
requiresAuth: true
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Best Practices
|
|
256
|
+
|
|
257
|
+
### 1. Organize by Domain
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
// Good: Functions grouped by business domain
|
|
261
|
+
.service('plugin:my-plugin:analytics', { /* ... */ })
|
|
262
|
+
.withFunction('getAnalytics')
|
|
263
|
+
.withFunction('getChartData')
|
|
264
|
+
.withFunction('exportReport')
|
|
265
|
+
.endService()
|
|
266
|
+
|
|
267
|
+
.service('plugin:my-plugin:notifications', { /* ... */ })
|
|
268
|
+
.withFunction('sendNotification')
|
|
269
|
+
.withFunction('getNotificationHistory')
|
|
270
|
+
.endService()
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### 2. Keep Services Focused
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Good: Focused service with related functions
|
|
277
|
+
.service('plugin:my-plugin:events', { /* ... */ })
|
|
278
|
+
.withFunction('getEvents')
|
|
279
|
+
.withFunction('clearEvents')
|
|
280
|
+
.withFunction('filterEvents')
|
|
281
|
+
.endService()
|
|
282
|
+
|
|
283
|
+
// Bad: Too broad, unrelated functions
|
|
284
|
+
.service('plugin:my-plugin:everything', { /* ... */ })
|
|
285
|
+
.withFunction('getEvents')
|
|
286
|
+
.withFunction('sendEmail') // Unrelated
|
|
287
|
+
.withFunction('calculateTax') // Unrelated
|
|
288
|
+
.endService()
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 3. Use Descriptive Metadata
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
.service('plugin:my-plugin:monitoring', {
|
|
295
|
+
type: '@my-plugin/monitoring',
|
|
296
|
+
metadata: {
|
|
297
|
+
name: 'System Monitoring', // Clear name
|
|
298
|
+
description: 'Provides health checks, system statistics, and performance metrics for the plugin', // Detailed description
|
|
299
|
+
version: '1.0.0'
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Service Naming Convention
|
|
305
|
+
|
|
306
|
+
**Format:** `plugin:{plugin-id}:{service-name}`
|
|
307
|
+
|
|
308
|
+
Examples:
|
|
309
|
+
- `plugin:my-plugin:monitoring`
|
|
310
|
+
- `plugin:my-plugin:analytics`
|
|
311
|
+
- `plugin:my-plugin:data-management`
|
|
312
|
+
- `plugin:full-featured:events`
|
|
313
|
+
|
|
314
|
+
## Testing Services
|
|
315
|
+
|
|
316
|
+
Services are tested through their functions:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// tests/plugin/functions/unit/monitoring.test.js
|
|
320
|
+
import { test, invoke, mock } from '@majkapp/plugin-test';
|
|
321
|
+
import assert from 'assert';
|
|
322
|
+
|
|
323
|
+
test('monitoring service - health check', async () => {
|
|
324
|
+
const context = mock().build();
|
|
325
|
+
const result = await invoke('health', {}, { context });
|
|
326
|
+
|
|
327
|
+
assert.strictEqual(result.status, 'ok');
|
|
328
|
+
assert.ok(result.timestamp);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test('monitoring service - get stats', async () => {
|
|
332
|
+
const context = mock()
|
|
333
|
+
.withMajkData({
|
|
334
|
+
conversations: [{ id: '1' }, { id: '2' }],
|
|
335
|
+
teammates: [{ id: 't1' }]
|
|
336
|
+
})
|
|
337
|
+
.build();
|
|
338
|
+
|
|
339
|
+
const result = await invoke('getStats', {}, { context });
|
|
340
|
+
|
|
341
|
+
assert.strictEqual(result.conversationCount, 2);
|
|
342
|
+
assert.strictEqual(result.teammateCount, 1);
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Next Steps
|
|
347
|
+
|
|
348
|
+
Run `npx @majkapp/plugin-kit --functions` - Define functions for services
|
|
349
|
+
Run `npx @majkapp/plugin-kit --testing` - Test your services
|
|
350
|
+
Run `npx @majkapp/plugin-kit --lifecycle` - Service initialization with onReady
|