@breadstone/archipel-mcp 0.0.10 → 0.0.13
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/data/guides/ai-text-generation.md +361 -0
- package/data/guides/analytics-and-error-tracking.md +189 -0
- package/data/guides/authentication-and-authorization.md +657 -0
- package/data/guides/blob-storage.md +242 -0
- package/data/guides/caching.md +255 -0
- package/data/guides/cryptography-and-otp.md +240 -0
- package/data/guides/database-setup.md +546 -0
- package/data/guides/document-generation.md +174 -0
- package/data/guides/email-delivery.md +196 -0
- package/data/guides/esigning-integration.md +231 -0
- package/data/guides/getting-started.md +351 -0
- package/data/guides/implementing-ports.md +317 -0
- package/data/guides/index.md +62 -0
- package/data/guides/mcp-server.md +222 -0
- package/data/guides/openapi-and-feature-discovery.md +266 -0
- package/data/guides/payments-and-feature-gating.md +244 -0
- package/data/guides/resource-management.md +352 -0
- package/data/guides/telemetry-and-observability.md +190 -0
- package/data/guides/testing.md +319 -0
- package/data/guides/tsdoc-guidelines.md +45 -0
- package/data/packages/platform-database/api/Class.DatabaseModule.md +3 -5
- package/data/packages/platform-database/api/Class.DatabaseService.md +5 -4
- package/data/packages/platform-database/api/Class.PrismaService.md +8 -7
- package/data/packages/platform-database/api/Interface.IDatabaseModuleConfig.md +13 -1
- package/data/packages/platform-database/api/Interface.IPrismaServiceOptions.md +22 -0
- package/data/packages/platform-database/api/Variable.DATABASE_MODULE_CONFIG.md +14 -0
- package/data/packages/platform-database/api/Variable.DB_ACCELERATE_URL.md +14 -0
- package/data/packages/platform-database/api/Variable.DB_AUTO_CONNECTION.md +14 -0
- package/data/packages/platform-database/api/Variable.DB_OPTIMIZE.md +14 -0
- package/data/packages/platform-database/api/Variable.DB_OPTIMIZE_API_KEY.md +14 -0
- package/data/packages/platform-database/api/Variable.PLATFORM_DATABASE_CONFIG_ENTRIES.md +14 -0
- package/data/packages/platform-database/api/index.md +13 -1
- package/data/packages/platform-database/index.md +41 -18
- package/data/packages/platform-openapi/api/Class.SwaggerFeatureDiscovery.md +10 -6
- package/data/packages/platform-telemetry/api/Class.NoopTelemetryFacade.md +10 -10
- package/data/packages/platform-telemetry/api/Interface.ITelemetryFacade.md +1 -1
- package/package.json +1 -1
- package/src/GuidesLoader.d.ts +13 -0
- package/src/GuidesLoader.js +81 -0
- package/src/main.js +36 -198
- package/src/models/IGuideDoc.d.ts +15 -0
- package/src/models/IGuideDoc.js +3 -0
- package/src/tools/registerGetConfigPatternTool.d.ts +5 -0
- package/src/tools/registerGetConfigPatternTool.js +15 -0
- package/src/tools/registerGetDtoPatternTool.d.ts +5 -0
- package/src/tools/registerGetDtoPatternTool.js +15 -0
- package/src/tools/registerGetErrorHandlingPatternTool.d.ts +5 -0
- package/src/tools/registerGetErrorHandlingPatternTool.js +15 -0
- package/src/tools/registerGetGuardPatternTool.d.ts +5 -0
- package/src/tools/registerGetGuardPatternTool.js +15 -0
- package/src/tools/registerGetGuideTool.d.ts +6 -0
- package/src/tools/registerGetGuideTool.js +32 -0
- package/src/tools/registerGetMappingPatternTool.d.ts +5 -0
- package/src/tools/registerGetMappingPatternTool.js +34 -0
- package/src/tools/registerGetModulePatternTool.d.ts +5 -0
- package/src/tools/registerGetModulePatternTool.js +29 -0
- package/src/tools/registerGetPackageDocTool.d.ts +6 -0
- package/src/tools/registerGetPackageDocTool.js +43 -0
- package/src/tools/registerGetQueryPatternTool.d.ts +5 -0
- package/src/tools/registerGetQueryPatternTool.js +29 -0
- package/src/tools/registerGetRepositoryPatternTool.d.ts +5 -0
- package/src/tools/registerGetRepositoryPatternTool.js +29 -0
- package/src/tools/registerGetTestingPatternTool.d.ts +5 -0
- package/src/tools/registerGetTestingPatternTool.js +15 -0
- package/src/tools/registerListGuidesTool.d.ts +6 -0
- package/src/tools/registerListGuidesTool.js +22 -0
- package/src/tools/registerListPackagesTool.d.ts +6 -0
- package/src/tools/registerListPackagesTool.js +20 -0
- package/src/tools/registerSearchDocsTool.d.ts +6 -0
- package/src/tools/registerSearchDocsTool.js +35 -0
- package/src/tools/registerSearchGuidesTool.d.ts +6 -0
- package/src/tools/registerSearchGuidesTool.js +28 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AI Text Generation
|
|
3
|
+
description: Generate text completions with multi-provider support for OpenAI, Anthropic, Google Gemini, and Grok using a unified configuration layer.
|
|
4
|
+
order: 15
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AI Text Generation
|
|
8
|
+
|
|
9
|
+
This guide covers text generation with `platform-intelligence`: choosing an AI provider, configuring the module, generating completions, registering custom capabilities, and building intent-based orchestration.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn add @breadstone/archipel-platform-intelligence
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Install the AI SDK provider package for the model you want to use:
|
|
20
|
+
|
|
21
|
+
| Provider | Package |
|
|
22
|
+
| -------------- | ------------------- |
|
|
23
|
+
| **OpenAI** | `@ai-sdk/openai` |
|
|
24
|
+
| **Anthropic** | `@ai-sdk/anthropic` |
|
|
25
|
+
| **Google** | `@ai-sdk/google` |
|
|
26
|
+
| **Grok (xAI)** | `@ai-sdk/openai` |
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Example: OpenAI
|
|
30
|
+
yarn add @ai-sdk/openai
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> Grok uses the OpenAI-compatible endpoint, so it shares the `@ai-sdk/openai` package.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Module Registration
|
|
38
|
+
|
|
39
|
+
Import `IntelligenceModule` into your application module. It exposes `IntelligenceTextGenerator` and `IntelligenceCapabilityRegistry` as shared providers.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { Module } from '@nestjs/common';
|
|
43
|
+
import { IntelligenceModule } from '@breadstone/archipel-platform-intelligence';
|
|
44
|
+
|
|
45
|
+
@Module({
|
|
46
|
+
imports: [IntelligenceModule],
|
|
47
|
+
})
|
|
48
|
+
export class AppModule {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
All intelligence settings are read from environment variables via `ConfigService`. No direct `process.env` access is needed.
|
|
56
|
+
|
|
57
|
+
```env
|
|
58
|
+
INTELLIGENCE_PROVIDER=openai
|
|
59
|
+
INTELLIGENCE_MODEL=gpt-4o-mini
|
|
60
|
+
INTELLIGENCE_API_KEY=sk-...
|
|
61
|
+
INTELLIGENCE_TEMPERATURE=0.7
|
|
62
|
+
INTELLIGENCE_TOP_P=1
|
|
63
|
+
INTELLIGENCE_MAX_OUTPUT_TOKENS=1024
|
|
64
|
+
INTELLIGENCE_BASE_URL= # optional — override for custom endpoints
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Supported Providers
|
|
68
|
+
|
|
69
|
+
| `INTELLIGENCE_PROVIDER` | Default model | Notes |
|
|
70
|
+
| ----------------------- | -------------------------- | ---------------------------------- |
|
|
71
|
+
| `openai` | `gpt-4o-mini` | OpenAI API |
|
|
72
|
+
| `anthropic` | `claude-sonnet-4-20250514` | Anthropic API |
|
|
73
|
+
| `google` | `gemini-2.0-flash` | Google Gemini API |
|
|
74
|
+
| `grok` | `grok-3-mini-fast` | xAI Grok via OpenAI-compatible API |
|
|
75
|
+
|
|
76
|
+
Each provider resolves its API key and base URL from dedicated environment variables when the generic `INTELLIGENCE_API_KEY` is not set:
|
|
77
|
+
|
|
78
|
+
```env
|
|
79
|
+
# Provider-specific keys (optional — fallback from INTELLIGENCE_API_KEY)
|
|
80
|
+
OPENAI_API_KEY=sk-...
|
|
81
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
82
|
+
GOOGLE_GENERATIVE_AI_API_KEY=AI...
|
|
83
|
+
GROK_API_KEY=xai-...
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Generating Text
|
|
89
|
+
|
|
90
|
+
Inject `IntelligenceTextGenerator` to generate completions:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { Injectable } from '@nestjs/common';
|
|
94
|
+
import { IntelligenceTextGenerator } from '@breadstone/archipel-platform-intelligence';
|
|
95
|
+
import type { IIntelligencePrompt } from '@breadstone/archipel-platform-intelligence';
|
|
96
|
+
|
|
97
|
+
@Injectable()
|
|
98
|
+
export class SummaryService {
|
|
99
|
+
private readonly _textGenerator: IntelligenceTextGenerator;
|
|
100
|
+
|
|
101
|
+
constructor(textGenerator: IntelligenceTextGenerator) {
|
|
102
|
+
this._textGenerator = textGenerator;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public async summarize(content: string): Promise<string> {
|
|
106
|
+
const prompt: IIntelligencePrompt = {
|
|
107
|
+
systemPrompt: 'You are a concise summarizer. Respond with a short summary.',
|
|
108
|
+
messages: [{ role: 'user', content: content }],
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const completion = await this._textGenerator.generateText(prompt);
|
|
112
|
+
|
|
113
|
+
return completion.text;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Prompt Structure
|
|
119
|
+
|
|
120
|
+
A prompt consists of an optional system prompt and an ordered array of messages:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface IIntelligencePrompt {
|
|
124
|
+
readonly systemPrompt: string | null;
|
|
125
|
+
readonly messages: ReadonlyArray<IIntelligencePromptMessage>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
interface IIntelligencePromptMessage {
|
|
129
|
+
readonly role: 'user' | 'assistant' | 'system';
|
|
130
|
+
readonly content: string;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Per-Request Overrides
|
|
135
|
+
|
|
136
|
+
Override generation parameters for individual requests without changing the global configuration:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const completion = await this._textGenerator.generateText(prompt, {
|
|
140
|
+
temperature: 0.2, // more deterministic
|
|
141
|
+
maxOutputTokens: 256, // shorter responses
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Completion Response
|
|
146
|
+
|
|
147
|
+
The response includes the generated text, the provider/model used, and optional token usage telemetry:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
interface IIntelligenceTextCompletion {
|
|
151
|
+
readonly text: string;
|
|
152
|
+
readonly provider: string;
|
|
153
|
+
readonly model: string;
|
|
154
|
+
readonly usage: IIntelligenceCompletionUsage | null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface IIntelligenceCompletionUsage {
|
|
158
|
+
readonly promptTokens: number | null;
|
|
159
|
+
readonly completionTokens: number | null;
|
|
160
|
+
readonly totalTokens: number | null;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Multi-Turn Conversations
|
|
167
|
+
|
|
168
|
+
Build multi-turn conversations by passing the full message history:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const prompt: IIntelligencePrompt = {
|
|
172
|
+
systemPrompt: 'You are a helpful fitness coach.',
|
|
173
|
+
messages: [
|
|
174
|
+
{ role: 'user', content: 'What should I eat before a workout?' },
|
|
175
|
+
{ role: 'assistant', content: 'A balanced meal with carbs and protein about 2 hours before.' },
|
|
176
|
+
{ role: 'user', content: 'Can you give me a specific example?' },
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const completion = await this._textGenerator.generateText(prompt);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Capability System
|
|
186
|
+
|
|
187
|
+
The intelligence module includes a capability registry that lets you build intent-based orchestration. Capabilities are domain-specific handlers that respond to classified user intents.
|
|
188
|
+
|
|
189
|
+
### Defining a Capability
|
|
190
|
+
|
|
191
|
+
Implement the `IIntelligenceCapability` interface:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import type {
|
|
195
|
+
IIntelligenceCapability,
|
|
196
|
+
IIntelligenceCapabilityMetadata,
|
|
197
|
+
IIntelligenceCapabilityPayload,
|
|
198
|
+
IIntelligenceCapabilityResult,
|
|
199
|
+
IIntelligenceContext,
|
|
200
|
+
IIntelligenceIntent,
|
|
201
|
+
} from '@breadstone/archipel-platform-intelligence';
|
|
202
|
+
|
|
203
|
+
export class WorkoutRecommendationCapability implements IIntelligenceCapability {
|
|
204
|
+
public readonly metadata: IIntelligenceCapabilityMetadata = {
|
|
205
|
+
id: 'workout-recommendation',
|
|
206
|
+
name: 'Workout Recommendation',
|
|
207
|
+
description: 'Recommends workouts based on user preferences.',
|
|
208
|
+
priority: 10,
|
|
209
|
+
intentName: 'recommend_workout',
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
public canHandle(intent: IIntelligenceIntent, _context: IIntelligenceContext): boolean {
|
|
213
|
+
return intent.name === 'recommend_workout' && intent.confidence >= 0.7;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public async execute(payload: IIntelligenceCapabilityPayload): Promise<IIntelligenceCapabilityResult> {
|
|
217
|
+
// Use payload.intent, payload.context, payload.userMessage
|
|
218
|
+
return {
|
|
219
|
+
messages: [{ content: 'Here is your personalized workout plan...', metadata: null }],
|
|
220
|
+
artifacts: [],
|
|
221
|
+
followUps: [{ id: 'adjust', label: 'Adjust difficulty', payload: { action: 'adjust' } }],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Registering Capabilities
|
|
228
|
+
|
|
229
|
+
Use `IntelligenceCapabilityRegistrarBase` to auto-register capabilities when a module initializes:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { Injectable } from '@nestjs/common';
|
|
233
|
+
import {
|
|
234
|
+
IntelligenceCapabilityRegistrarBase,
|
|
235
|
+
IntelligenceCapabilityRegistry,
|
|
236
|
+
} from '@breadstone/archipel-platform-intelligence';
|
|
237
|
+
import type { IIntelligenceCapability } from '@breadstone/archipel-platform-intelligence';
|
|
238
|
+
|
|
239
|
+
@Injectable()
|
|
240
|
+
export class WorkoutCapabilityRegistrar extends IntelligenceCapabilityRegistrarBase {
|
|
241
|
+
constructor(registry: IntelligenceCapabilityRegistry) {
|
|
242
|
+
super(registry);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
protected getCapabilities(): ReadonlyArray<IIntelligenceCapability> {
|
|
246
|
+
return [new WorkoutRecommendationCapability()];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Register the registrar as a provider in your feature module:
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { Module } from '@nestjs/common';
|
|
255
|
+
import { IntelligenceModule } from '@breadstone/archipel-platform-intelligence';
|
|
256
|
+
|
|
257
|
+
@Module({
|
|
258
|
+
imports: [IntelligenceModule],
|
|
259
|
+
providers: [WorkoutCapabilityRegistrar],
|
|
260
|
+
})
|
|
261
|
+
export class WorkoutModule {}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Resolving Capabilities at Runtime
|
|
265
|
+
|
|
266
|
+
Use the registry to find the best-matching capability for a classified intent:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { Injectable } from '@nestjs/common';
|
|
270
|
+
import { IntelligenceCapabilityRegistry } from '@breadstone/archipel-platform-intelligence';
|
|
271
|
+
import type {
|
|
272
|
+
IIntelligenceCapabilityResult,
|
|
273
|
+
IIntelligenceContext,
|
|
274
|
+
IIntelligenceIntent,
|
|
275
|
+
} from '@breadstone/archipel-platform-intelligence';
|
|
276
|
+
|
|
277
|
+
@Injectable()
|
|
278
|
+
export class ChatOrchestrator {
|
|
279
|
+
private readonly _registry: IntelligenceCapabilityRegistry;
|
|
280
|
+
|
|
281
|
+
constructor(registry: IntelligenceCapabilityRegistry) {
|
|
282
|
+
this._registry = registry;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public async handle(
|
|
286
|
+
intent: IIntelligenceIntent,
|
|
287
|
+
context: IIntelligenceContext,
|
|
288
|
+
userMessage: string,
|
|
289
|
+
): Promise<IIntelligenceCapabilityResult | null> {
|
|
290
|
+
const capability = this._registry.resolve(intent, context);
|
|
291
|
+
if (!capability) {
|
|
292
|
+
return null; // No matching capability — fall back to generic response
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return capability.execute({ intent, context, userMessage });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Capabilities are resolved by priority (lowest number first). If multiple capabilities can handle the same intent, the one with the highest priority (lowest value) wins.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Inspecting Configuration
|
|
305
|
+
|
|
306
|
+
Retrieve the resolved provider configuration at runtime:
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
const config = this._textGenerator.getConfiguration();
|
|
310
|
+
console.log(config.provider); // 'openai'
|
|
311
|
+
console.log(config.model); // 'gpt-4o-mini'
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Error Handling
|
|
317
|
+
|
|
318
|
+
`IntelligenceTextGenerator` logs errors via the NestJS `Logger` and re-throws them. Wrap calls in try/catch to handle provider failures gracefully:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
try {
|
|
322
|
+
const result = await this._textGenerator.generateText(prompt);
|
|
323
|
+
return result.text;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
// Handle rate limits, network errors, invalid API keys, etc.
|
|
326
|
+
this._logger.error(`Text generation failed: ${(error as Error).message}`);
|
|
327
|
+
return 'Sorry, I could not generate a response right now.';
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
If an AI SDK provider package is not installed, the error message clearly states which package is missing.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Architecture Overview
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
┌────────────────────────────────────┐
|
|
339
|
+
│ IntelligenceModule │
|
|
340
|
+
│ │
|
|
341
|
+
│ ┌──────────────────────────────┐ │
|
|
342
|
+
│ │ IntelligenceTextGenerator │──┼── generateText(prompt, options?)
|
|
343
|
+
│ │ (ConfigService → provider) │ │
|
|
344
|
+
│ └──────────────────────────────┘ │
|
|
345
|
+
│ │
|
|
346
|
+
│ ┌──────────────────────────────┐ │
|
|
347
|
+
│ │ IntelligenceCapability │──┼── resolve(intent, context)
|
|
348
|
+
│ │ Registry │ │ register(capability)
|
|
349
|
+
│ └──────────────────────────────┘ │
|
|
350
|
+
└────────────────────────────────────┘
|
|
351
|
+
│ │
|
|
352
|
+
▼ ▼
|
|
353
|
+
┌─────────────┐ ┌──────────────┐
|
|
354
|
+
│ Provider │ │ Feature │
|
|
355
|
+
│ Loaders │ │ Capabilities │
|
|
356
|
+
│ (OpenAI, │ │ (custom │
|
|
357
|
+
│ Anthropic, │ │ handlers) │
|
|
358
|
+
│ Google, │ │ │
|
|
359
|
+
│ Grok) │ │ │
|
|
360
|
+
└─────────────┘ └──────────────┘
|
|
361
|
+
```
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Analytics & Error Tracking
|
|
3
|
+
description: Capture errors, messages, and user context with Sentry, Application Insights, Datadog, or a custom provider.
|
|
4
|
+
order: 14
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Analytics & Error Tracking
|
|
8
|
+
|
|
9
|
+
This guide covers error tracking and analytics with `platform-analytics`: choosing a provider, capturing exceptions, recording breadcrumbs, and setting user context.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn add @breadstone/archipel-platform-analytics
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Choose a Provider
|
|
22
|
+
|
|
23
|
+
`platform-analytics` abstracts error tracking and analytics behind an `AnalyticsClientPort`. Supported providers:
|
|
24
|
+
|
|
25
|
+
| Provider | When to use |
|
|
26
|
+
| ------------------------ | -------------------------------------------- |
|
|
27
|
+
| **Sentry** | Full-featured error tracking and performance |
|
|
28
|
+
| **Application Insights** | Azure-native monitoring |
|
|
29
|
+
| **Datadog** | Infrastructure + APM monitoring |
|
|
30
|
+
| **Noop** | Development / testing — discards all events |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Module Registration
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Module } from '@nestjs/common';
|
|
38
|
+
import { AnalyticsModule } from '@breadstone/archipel-platform-analytics';
|
|
39
|
+
import { SentryAnalyticsClient } from './adapters/SentryAnalyticsClient';
|
|
40
|
+
import { SENTRY_CONFIG_ENTRIES } from './env';
|
|
41
|
+
|
|
42
|
+
@Module({
|
|
43
|
+
imports: [
|
|
44
|
+
AnalyticsModule.register({
|
|
45
|
+
analyticsClient: SentryAnalyticsClient,
|
|
46
|
+
configEntries: [...SENTRY_CONFIG_ENTRIES],
|
|
47
|
+
isGlobal: true,
|
|
48
|
+
}),
|
|
49
|
+
],
|
|
50
|
+
})
|
|
51
|
+
export class AppModule {}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Implementing the Client Port
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { Injectable } from '@nestjs/common';
|
|
60
|
+
import {
|
|
61
|
+
AnalyticsClientPort,
|
|
62
|
+
AnalyticsLevel,
|
|
63
|
+
type IAnalyticsUser,
|
|
64
|
+
type IAnalyticsBreadcrumb,
|
|
65
|
+
} from '@breadstone/archipel-platform-analytics';
|
|
66
|
+
import * as Sentry from '@sentry/node';
|
|
67
|
+
|
|
68
|
+
@Injectable()
|
|
69
|
+
export class SentryAnalyticsClient extends AnalyticsClientPort {
|
|
70
|
+
public captureException(error: Error, context?: Record<string, unknown>): void {
|
|
71
|
+
Sentry.captureException(error, { extra: context });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public captureMessage(message: string, level: AnalyticsLevel): void {
|
|
75
|
+
Sentry.captureMessage(message, level);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public setUser(user: IAnalyticsUser): void {
|
|
79
|
+
Sentry.setUser({ id: user.id, email: user.email });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public addBreadcrumb(breadcrumb: IAnalyticsBreadcrumb): void {
|
|
83
|
+
Sentry.addBreadcrumb({
|
|
84
|
+
category: breadcrumb.category,
|
|
85
|
+
message: breadcrumb.message,
|
|
86
|
+
level: breadcrumb.level,
|
|
87
|
+
data: breadcrumb.data,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Capturing Errors
|
|
96
|
+
|
|
97
|
+
Inject `AnalyticsClientPort` to capture exceptions with full context:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { Injectable } from '@nestjs/common';
|
|
101
|
+
import { AnalyticsClientPort } from '@breadstone/archipel-platform-analytics';
|
|
102
|
+
|
|
103
|
+
@Injectable()
|
|
104
|
+
export class PaymentService {
|
|
105
|
+
private readonly _analytics: AnalyticsClientPort;
|
|
106
|
+
|
|
107
|
+
constructor(analytics: AnalyticsClientPort) {
|
|
108
|
+
this._analytics = analytics;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public async processPayment(orderId: string): Promise<void> {
|
|
112
|
+
try {
|
|
113
|
+
// ... payment logic
|
|
114
|
+
} catch (error) {
|
|
115
|
+
this._analytics.captureException(error as Error, {
|
|
116
|
+
orderId,
|
|
117
|
+
action: 'processPayment',
|
|
118
|
+
});
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## User Context
|
|
128
|
+
|
|
129
|
+
Set user context early in the request lifecycle (e.g., via a middleware or interceptor) so all captured events include user information:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { Injectable, NestMiddleware } from '@nestjs/common';
|
|
133
|
+
import { Request, Response, NextFunction } from 'express';
|
|
134
|
+
import { AnalyticsClientPort } from '@breadstone/archipel-platform-analytics';
|
|
135
|
+
import type { IAuthSubject } from '@breadstone/archipel-platform-authentication';
|
|
136
|
+
|
|
137
|
+
@Injectable()
|
|
138
|
+
export class AnalyticsUserMiddleware implements NestMiddleware {
|
|
139
|
+
private readonly _analytics: AnalyticsClientPort;
|
|
140
|
+
|
|
141
|
+
constructor(analytics: AnalyticsClientPort) {
|
|
142
|
+
this._analytics = analytics;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public use(req: Request, _res: Response, next: NextFunction): void {
|
|
146
|
+
const user = req.user as IAuthSubject | undefined;
|
|
147
|
+
|
|
148
|
+
if (user) {
|
|
149
|
+
this._analytics.setUser({
|
|
150
|
+
id: user.id,
|
|
151
|
+
email: user.email ?? undefined,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
next();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Breadcrumbs
|
|
163
|
+
|
|
164
|
+
Breadcrumbs are a trail of events leading up to an error. They help you understand what happened before a crash:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
this._analytics.addBreadcrumb({
|
|
168
|
+
category: 'payment',
|
|
169
|
+
message: 'Checkout session created',
|
|
170
|
+
level: 'info',
|
|
171
|
+
data: { orderId, provider: 'stripe' },
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Development Tips
|
|
178
|
+
|
|
179
|
+
- Use the **Noop** provider during local development and testing to avoid sending events to production analytics.
|
|
180
|
+
- Set `isGlobal: true` in the module registration so `AnalyticsClientPort` is available everywhere without re-importing.
|
|
181
|
+
- Combine with `platform-telemetry` for metrics. Use analytics for error tracking and telemetry for performance monitoring.
|
|
182
|
+
- Map domain errors to known categories in your analytics context to group related issues.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Next Steps
|
|
187
|
+
|
|
188
|
+
- See the [Telemetry & Observability](/guides/telemetry-and-observability) guide for metrics and tracing
|
|
189
|
+
- Browse the [platform-analytics API reference](/packages/platform-analytics/api/) for complete method signatures
|