@breadstone/archipel-mcp 0.0.16 → 0.0.18

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.
@@ -9,13 +9,17 @@ Practical guides for working with Archipel packages in your NestJS application.
9
9
 
10
10
  ## Foundations
11
11
 
12
- | Guide | What you'll learn |
13
- | ------------------------------------------- | -------------------------------------------------------------------------------------- |
14
- | [Getting Started](./getting-started) | Install packages, register your first module, implement ports, and run the app. |
15
- | [Configuration Management](./configuration) | Type-safe config keys, strategy-based resolution, central registry, and validation. |
16
- | [Implementing Ports](./implementing-ports) | How the port/adapter pattern works, how to write adapters, and how to test them. |
17
- | [Testing](./testing) | Unit testing services, testing port adapters, integration testing with real databases. |
18
- | [TSDoc Guidelines](./tsdoc-guidelines) | Documentation standards for public APIs and generated reference pages. |
12
+ | Guide | What you'll learn |
13
+ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
14
+ | [Getting Started](./getting-started) | Install packages, register your first module, implement ports, and run the app. |
15
+ | [Configuration Management](./configuration) | Type-safe config keys, strategy-based resolution, central registry, and validation. |
16
+ | [Implementing Ports](./implementing-ports) | How the port/adapter pattern works, how to write adapters, and how to test them. |
17
+ | [Controller Best Practices](./controller-best-practices) | Structure, annotate, and implement controllers — regions, DI, ResponseReturn, guards, and the @Api decorator. |
18
+ | [Request & Response DTOs](./request-response-dtos) | DTO naming conventions, validation decorators, cross-field validation, and class-transformer integration. |
19
+ | [Testing](./testing) | Unit testing services, testing port adapters, integration testing with real databases. |
20
+ | [TSDoc Guidelines](./tsdoc-guidelines) | Documentation standards for public APIs and generated reference pages. ld validation, and class-transformer integration. |
21
+ | [Testing](./testing) | Unit testing services, testing port adapters, integration testing with real databases. |
22
+ | [TSDoc Guidelines](./tsdoc-guidelines) | Documentation standards for public APIs and generated reference pages. |
19
23
 
20
24
  ## Security & Identity
21
25
 
@@ -149,18 +149,26 @@ export class TipController {
149
149
 
150
150
  ### `@Api()` Options Reference
151
151
 
152
- | Option | Type | Description |
153
- | ------------ | --------------------------------------------- | ---------------------------------------------------- |
154
- | `auth` | `'bearer' \| 'basic' \| 'oauth2' \| 'cookie'` | Adds the corresponding auth decorator. |
155
- | `tags` | `string \| string[]` | OpenAPI tag(s) for the operation. |
156
- | `operation` | `ApiOperationOptions` | Summary, description, deprecation flag, etc. |
157
- | `responses` | `ApiResponseOptions \| ApiResponseOptions[]` | One or more response definitions. |
158
- | `headers` | `ApiHeaderOptions[]` | Expected request headers. |
159
- | `params` | `ApiParamOptions \| ApiParamOptions[]` | Path parameter definitions. |
160
- | `query` | `ApiQueryOptions \| ApiQueryOptions[]` | Query parameter definitions. |
161
- | `body` | `ApiBodyOptions` | Request body definition. |
162
- | `scopes` | `string[]` | OAuth2 scopes (only relevant when `auth: 'oauth2'`). |
163
- | `extensions` | `Record<string, string \| number \| boolean>` | Custom OpenAPI extension properties (`x-*`). |
152
+ | Option | Type | Description |
153
+ | ------------ | ----------------------------------------------------------------- | -------------------------------------------------------------------- |
154
+ | `auth` | `ApiAuthOption \| ApiAuthOption[]` | Auth scheme(s). Simple string (`'bearer'`) or named (`{ type: 'bearer', name: 'jwt' }`). Supports multiple simultaneous schemes. |
155
+ | `tags` | `string \| string[]` | OpenAPI tag(s) for the operation. |
156
+ | `operation` | `ApiOperationOptions` | Summary, description, operationId, deprecation flag, etc. |
157
+ | `summary` | `string` | Shorthand for `operation.summary`. Takes precedence when both are set. |
158
+ | `deprecated` | `boolean` | Shorthand to mark the endpoint as deprecated. Merged into `operation`. |
159
+ | `responses` | `ApiResponseOptions \| ApiResponseOptions[]` | One or more response definitions. |
160
+ | `headers` | `ApiHeaderOptions[]` | Expected request headers. |
161
+ | `params` | `ApiParamOptions \| ApiParamOptions[]` | Path parameter definitions. |
162
+ | `query` | `ApiQueryOptions \| ApiQueryOptions[]` | Query parameter definitions. |
163
+ | `body` | `ApiBodyOptions` | Request body definition. |
164
+ | `scopes` | `string[]` | OAuth2 scopes (only relevant when `auth` includes `'oauth2'`). |
165
+ | `extensions` | `Record<string, unknown>` | Custom OpenAPI extension properties (`x-*`). |
166
+ | `consumes` | `string \| string[]` | MIME type(s) the endpoint consumes (e.g. `'multipart/form-data'`). |
167
+ | `produces` | `string \| string[]` | MIME type(s) the endpoint produces (e.g. `'application/pdf'`). |
168
+ | `extraModels`| `Function \| Function[]` | Extra model classes for polymorphic / discriminated-union schemas. |
169
+ | `security` | `IApiSecurityOption \| IApiSecurityOption[]` | Generic security scheme(s) for custom API keys or non-standard auth. |
170
+ | `exclude` | `boolean` | Excludes this endpoint from the Swagger documentation when `true`. |
171
+ | `callbacks` | `ApiCallbacksOptions` | OpenAPI callback / webhook definitions. |
164
172
 
165
173
  ---
166
174
 
@@ -0,0 +1,411 @@
1
+ ---
2
+ title: Request & Response DTOs
3
+ description: Naming conventions, validation decorators, and class-transformer integration for request and response data transfer objects in Archipel NestJS applications.
4
+ order: 4
5
+ ---
6
+
7
+ # Request & Response DTOs
8
+
9
+ This guide covers how to define, validate, and transform request and response DTOs in an Archipel-powered NestJS application. DTOs are the contract between your API and its consumers — they define what goes in and what comes out.
10
+
11
+ For how controllers use DTOs together with `ResponseReturn`, see the [Controller Best Practices](/guides/controller-best-practices) guide.
12
+
13
+ ---
14
+
15
+ ## Naming Conventions
16
+
17
+ DTOs follow a strict naming pattern:
18
+
19
+ | Type | Pattern | Example |
20
+ |------|---------|---------|
21
+ | Create request | `Create{Resource}Request` | `CreateOrderRequest` |
22
+ | Update request | `Update{Resource}Request` | `UpdateProfileRequest` |
23
+ | Action request | `{Action}{Resource}Request` | `AuthLoginRequest`, `AuthVerifyPinRequest` |
24
+ | Single response | `{Resource}Response` | `UserResponse`, `OrderResponse` |
25
+ | List response | `{Resource}ListResponse` | `OrderListResponse` |
26
+ | Action response | `{Action}{Resource}Response` | `AuthLoginResponse`, `AuthRefreshResponse` |
27
+ | Availability / status | `{Resource}{Status}Response` | `AuthUsernameAvailabilityResponse` |
28
+
29
+ ### Grouping by Feature
30
+
31
+ When a controller has many DTOs, prefix them with the feature name to keep imports clean:
32
+
33
+ ```typescript
34
+ // Auth feature DTOs
35
+ AuthLoginRequest
36
+ AuthLoginResponse
37
+ AuthRegisterRequest
38
+ AuthRefreshResponse
39
+ AuthChangePasswordRequest
40
+ AuthChangeEmailRequest
41
+ AuthForgotPasswordRequest
42
+ AuthVerifyPinRequest
43
+ AuthVerifyResponse
44
+ AuthResendVerificationRequest
45
+ AuthUsernameSuggestionsResponse
46
+ AuthUsernameAvailabilityResponse
47
+ AuthAvatarSuggestionResponse
48
+ ```
49
+
50
+ All DTOs for a feature are exported from a `models/` barrel file:
51
+
52
+ ```typescript
53
+ // models/index.ts
54
+ export { AuthLoginRequest } from './AuthLoginRequest';
55
+ export { AuthLoginResponse } from './AuthLoginResponse';
56
+ export { AuthRegisterRequest } from './AuthRegisterRequest';
57
+ // ...
58
+ ```
59
+
60
+ ---
61
+
62
+ ## File Organization
63
+
64
+ **One public export per file.** Each DTO class gets its own file, named after the class.
65
+
66
+ ```
67
+ src/
68
+ auth/
69
+ models/
70
+ AuthLoginRequest.ts
71
+ AuthLoginResponse.ts
72
+ AuthRegisterRequest.ts
73
+ AuthRefreshResponse.ts
74
+ UserResponse.ts
75
+ index.ts
76
+ AuthController.ts
77
+ AuthModule.ts
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Request DTOs (Validation)
83
+
84
+ Request DTOs are classes decorated with `class-validator` and `@ApiProperty` from `@nestjs/swagger`.
85
+
86
+ ### Basic Request
87
+
88
+ ```typescript
89
+ import { ApiProperty } from '@nestjs/swagger';
90
+ import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
91
+
92
+ export class AuthLoginRequest {
93
+
94
+ /**
95
+ * The user's email address or username.
96
+ *
97
+ * @public
98
+ */
99
+ @ApiProperty({ description: 'Email address or username.' })
100
+ @IsNotEmpty()
101
+ @IsString()
102
+ public login!: string;
103
+
104
+ /**
105
+ * The user's password.
106
+ *
107
+ * @public
108
+ */
109
+ @ApiProperty({ description: 'Account password.' })
110
+ @IsNotEmpty()
111
+ @IsString()
112
+ @MinLength(8)
113
+ public password!: string;
114
+
115
+ }
116
+ ```
117
+
118
+ ### Request with Optional Fields
119
+
120
+ ```typescript
121
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
122
+ import { IsEmail, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
123
+ import { Type } from 'class-transformer';
124
+
125
+ export class AuthRegisterRequest {
126
+
127
+ @ApiProperty({ description: 'Email address for the new account.' })
128
+ @IsNotEmpty()
129
+ @IsEmail()
130
+ public email!: string;
131
+
132
+ @ApiProperty({ description: 'Password for the new account.', minLength: 8 })
133
+ @IsNotEmpty()
134
+ @IsString()
135
+ @MinLength(8)
136
+ public password!: string;
137
+
138
+ @ApiProperty({ description: 'Account type.', example: 'personal' })
139
+ @IsNotEmpty()
140
+ @IsString()
141
+ public type!: string;
142
+
143
+ @ApiPropertyOptional({ description: 'Optional profile information.' })
144
+ @IsOptional()
145
+ @ValidateNested()
146
+ @Type(() => ProfilePayload)
147
+ public profile?: ProfilePayload;
148
+
149
+ }
150
+ ```
151
+
152
+ ### Nested Payloads
153
+
154
+ When a request contains nested objects, define them as separate classes with `@ValidateNested()` and `@Type()`:
155
+
156
+ ```typescript
157
+ import { ApiPropertyOptional } from '@nestjs/swagger';
158
+ import { IsOptional, IsString } from 'class-validator';
159
+
160
+ export class ProfilePayload {
161
+
162
+ @ApiPropertyOptional()
163
+ @IsOptional()
164
+ @IsString()
165
+ public avatar?: string;
166
+
167
+ @ApiPropertyOptional()
168
+ @IsOptional()
169
+ @IsString()
170
+ public firstName?: string;
171
+
172
+ @ApiPropertyOptional()
173
+ @IsOptional()
174
+ @IsString()
175
+ public lastName?: string;
176
+
177
+ @ApiPropertyOptional()
178
+ @IsOptional()
179
+ @IsString()
180
+ public userName?: string;
181
+
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Response DTOs (Transformation)
188
+
189
+ Response DTOs use `@ApiProperty` for documentation and `@Expose()` from `class-transformer` for serialization control.
190
+
191
+ ### Basic Response
192
+
193
+ ```typescript
194
+ import { ApiProperty } from '@nestjs/swagger';
195
+ import { Expose } from 'class-transformer';
196
+
197
+ export class AuthLoginResponse {
198
+
199
+ @ApiProperty({ description: 'JWT access token.' })
200
+ @Expose()
201
+ public accessToken!: string;
202
+
203
+ @ApiProperty({ description: 'Whether multi-factor authentication is required.' })
204
+ @Expose()
205
+ public mfaRequired!: boolean;
206
+
207
+ }
208
+ ```
209
+
210
+ ### Response with Optional Fields
211
+
212
+ ```typescript
213
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
214
+ import { Expose } from 'class-transformer';
215
+
216
+ export class AuthLoginResponse {
217
+
218
+ @ApiProperty({ description: 'JWT access token.' })
219
+ @Expose()
220
+ public accessToken!: string;
221
+
222
+ @ApiProperty({ description: 'Whether MFA is required.' })
223
+ @Expose()
224
+ public mfaRequired!: boolean;
225
+
226
+ @ApiProperty({ description: 'Whether email verification is required.' })
227
+ @Expose()
228
+ public verificationRequired!: boolean;
229
+
230
+ @ApiPropertyOptional({ description: 'MFA challenge identifier.' })
231
+ @Expose()
232
+ public challengeId?: string;
233
+
234
+ @ApiPropertyOptional({ description: 'Available MFA methods.', type: [String] })
235
+ @Expose()
236
+ public methods?: Array<string>;
237
+
238
+ @ApiPropertyOptional({ description: 'Preferred MFA method.' })
239
+ @Expose()
240
+ public preferredMethod?: string;
241
+
242
+ }
243
+ ```
244
+
245
+ ### User / Entity Response
246
+
247
+ ```typescript
248
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
249
+ import { Expose } from 'class-transformer';
250
+
251
+ export class UserResponse {
252
+
253
+ @ApiProperty({ description: 'Unique user identifier.' })
254
+ @Expose()
255
+ public id!: string;
256
+
257
+ @ApiProperty({ description: 'Email address.' })
258
+ @Expose()
259
+ public email!: string;
260
+
261
+ @ApiPropertyOptional({ description: 'Display username.' })
262
+ @Expose()
263
+ public userName?: string;
264
+
265
+ @ApiPropertyOptional({ description: 'First name.' })
266
+ @Expose()
267
+ public firstName?: string;
268
+
269
+ @ApiPropertyOptional({ description: 'Last name.' })
270
+ @Expose()
271
+ public lastName?: string;
272
+
273
+ @ApiPropertyOptional({ description: 'Avatar URL or base64 image.' })
274
+ @Expose()
275
+ public avatar?: string;
276
+
277
+ @ApiProperty({ description: 'Whether the email is verified.' })
278
+ @Expose()
279
+ public isVerified!: boolean;
280
+
281
+ }
282
+ ```
283
+
284
+ ---
285
+
286
+ ## How ResponseReturn Uses DTOs
287
+
288
+ When a controller calls `ResponseReturn.ok(AuthLoginResponse, data)`, the response pipeline:
289
+
290
+ 1. Instantiates `AuthLoginResponse` via `class-transformer`'s `plainToInstance()`
291
+ 2. Applies `@Expose()` / `@Exclude()` rules — only explicitly exposed fields appear in the output
292
+ 3. Wraps the result in the standard envelope: `{ success, status, data, timestamp }`
293
+
294
+ This means the DTO class **controls what the client sees**. Even if the service returns extra fields, they won't leak unless the DTO exposes them.
295
+
296
+ ```typescript
297
+ // Service returns: { id, email, password, internalFlag, ... }
298
+ // DTO only exposes: { id, email, userName }
299
+ // Client receives: { success: true, status: 200, data: { id, email, userName }, timestamp: ... }
300
+ ```
301
+
302
+ ---
303
+
304
+ ## Validation Pipeline
305
+
306
+ Archipel applications use a global `ValidationPipe` with strict settings:
307
+
308
+ ```typescript
309
+ app.useGlobalPipes(new ValidationPipe({
310
+ whitelist: true, // Strip properties not in the DTO
311
+ forbidNonWhitelisted: true, // Throw if unknown properties are sent
312
+ transform: true, // Auto-transform payloads to DTO instances
313
+ }));
314
+ ```
315
+
316
+ This means:
317
+ - Properties without decorators are **silently removed** (`whitelist`)
318
+ - Unknown properties cause a **400 Bad Request** (`forbidNonWhitelisted`)
319
+ - Request bodies are automatically transformed to class instances (`transform`)
320
+
321
+ ---
322
+
323
+ ## Cross-Field Validation
324
+
325
+ When fields depend on each other (e.g., either `email` or `phone` is required, but not both), implement a custom class-level validator:
326
+
327
+ ```typescript
328
+ import { ValidatorConstraint, ValidatorConstraintInterface, Validate, ValidationArguments } from 'class-validator';
329
+
330
+ @ValidatorConstraint({ name: 'eitherEmailOrPhone', async: false })
331
+ export class EitherEmailOrPhoneConstraint implements ValidatorConstraintInterface {
332
+
333
+ public validate(_: unknown, args: ValidationArguments): boolean {
334
+ const obj = args.object as { email?: string; phone?: string };
335
+ return Boolean(obj.email) !== Boolean(obj.phone);
336
+ }
337
+
338
+ public defaultMessage(): string {
339
+ return 'Exactly one of email or phone must be provided.';
340
+ }
341
+
342
+ }
343
+
344
+ @Validate(EitherEmailOrPhoneConstraint)
345
+ export class ContactRequest {
346
+
347
+ @ApiPropertyOptional()
348
+ @IsOptional()
349
+ @IsEmail()
350
+ public email?: string;
351
+
352
+ @ApiPropertyOptional()
353
+ @IsOptional()
354
+ @IsString()
355
+ public phone?: string;
356
+
357
+ }
358
+ ```
359
+
360
+ **Never** do cross-field validation in controllers or services — always use class-level validators so it's reusable and testable.
361
+
362
+ ---
363
+
364
+ ## Constants for Limits
365
+
366
+ Define and reuse constants for bounds that appear in validation and pagination:
367
+
368
+ ```typescript
369
+ // constants.ts
370
+ export const MAX_PAGE_SIZE = 100;
371
+ export const MAX_SEARCH_LIMIT = 50;
372
+ export const DEFAULT_PAGE_SIZE = 20;
373
+ ```
374
+
375
+ ```typescript
376
+ import { Max, Min, IsOptional, IsInt } from 'class-validator';
377
+ import { MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE } from '../constants';
378
+
379
+ export class PaginationQuery {
380
+
381
+ @ApiPropertyOptional({ default: DEFAULT_PAGE_SIZE, maximum: MAX_PAGE_SIZE })
382
+ @IsOptional()
383
+ @IsInt()
384
+ @Min(1)
385
+ @Max(MAX_PAGE_SIZE)
386
+ public limit?: number = DEFAULT_PAGE_SIZE;
387
+
388
+ @ApiPropertyOptional({ default: 0 })
389
+ @IsOptional()
390
+ @IsInt()
391
+ @Min(0)
392
+ public offset?: number = 0;
393
+
394
+ }
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Checklist
400
+
401
+ Before submitting DTOs, verify:
402
+
403
+ - [ ] One DTO class per file, named after the class
404
+ - [ ] Request DTOs have `class-validator` decorators on every property
405
+ - [ ] Response DTOs have `@Expose()` on every public property
406
+ - [ ] Nested objects use `@ValidateNested()` + `@Type()`
407
+ - [ ] All properties have `@ApiProperty` or `@ApiPropertyOptional`
408
+ - [ ] No `any` types — use `unknown` or specific types
409
+ - [ ] Cross-field validation uses class-level validators, not imperative checks
410
+ - [ ] Pagination limits use shared constants with `@Max()`
411
+ - [ ] DTOs exported from a `models/index.ts` barrel
@@ -32,7 +32,9 @@ For Redis-backed caching:
32
32
  import { RedisLayeredCache } from '@breadstone/archipel-platform-caching/redis';
33
33
 
34
34
  const cache = new RedisLayeredCache<string, IProduct>(redisClient, async (key) => productRepository.findById(key), {
35
- ttlMs: 300_000,
35
+ url: 'redis://localhost:6379',
36
+ keyPrefix: 'products:',
37
+ ttlSeconds: 300,
36
38
  cacheName: 'products',
37
39
  });
38
40
  ```
@@ -72,12 +74,13 @@ Both implementations share this contract:
72
74
 
73
75
  | Property | Type | Default | Description |
74
76
  | ---------------------- | ----------------------- | ---------------- | ------------------------------------------------------- |
75
- | `ttlMs` | `number` | | Time-to-live in milliseconds. |
76
- | `staleWhileRevalidate` | `boolean` | `false` | Serve stale entries while refreshing in the background. |
77
- | `metricsRecorder` | `ICacheMetricsRecorder` | Noop | Pluggable metrics hook. |
78
- | `cacheName` | `string` | `'redis'` | Label used in metrics and logging. |
77
+ | `url` | `string` | | Redis connection URL (e.g. `redis://localhost:6379`). |
78
+ | `keyPrefix` | `string` | | Key prefix applied to all Redis keys. |
79
+ | `ttlSeconds` | `number` | | Time-to-live in seconds. |
79
80
  | `serialize` | `(value) => string` | `JSON.stringify` | Custom serializer for cache values. |
80
81
  | `deserialize` | `(raw) => value` | `JSON.parse` | Custom deserializer for cache entries. |
82
+ | `metricsRecorder` | `ICacheMetricsRecorder` | Noop | Pluggable metrics hook. |
83
+ | `cacheName` | `string` | `'redis'` | Label used in metrics and logging. |
81
84
 
82
85
  ---
83
86
 
@@ -15,12 +15,10 @@ Cryptographic building blocks for NestJS applications: bcrypt password hashing,
15
15
  ## Quick Start
16
16
 
17
17
  ```typescript
18
- import {
19
- BcryptService,
20
- CryptoService,
21
- OtpService,
22
- OTP_SERVICE_TOKEN,
23
- } from '@breadstone/archipel-platform-cryptography';
18
+ import { BcryptService, CryptoService } from '@breadstone/archipel-platform-cryptography';
19
+
20
+ // OTP is a tree-shakable sub-export
21
+ import { OtpService, OTP_SERVICE_TOKEN } from '@breadstone/archipel-platform-cryptography/otp';
24
22
  ```
25
23
 
26
24
  ---
@@ -83,7 +81,7 @@ TOTP enrollment and verification backed by otplib v13, injected via the `OTP_SER
83
81
 
84
82
  ```typescript
85
83
  import { Module } from '@nestjs/common';
86
- import { OtpService, OTP_SERVICE_TOKEN } from '@breadstone/archipel-platform-cryptography';
84
+ import { OtpService, OTP_SERVICE_TOKEN } from '@breadstone/archipel-platform-cryptography/otp';
87
85
 
88
86
  @Module({
89
87
  providers: [{ provide: OTP_SERVICE_TOKEN, useClass: OtpService }],
@@ -96,7 +94,7 @@ export class SecurityModule {}
96
94
 
97
95
  ```typescript
98
96
  import { Inject, Injectable } from '@nestjs/common';
99
- import { OTP_SERVICE_TOKEN, IOtpService } from '@breadstone/archipel-platform-cryptography';
97
+ import { OTP_SERVICE_TOKEN, IOtpService } from '@breadstone/archipel-platform-cryptography/otp';
100
98
 
101
99
  @Injectable()
102
100
  export class MfaService {
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  title: platform-logging
3
- description: Sentry integration for error tracking and analytics.
3
+ description: Configurable logging module for NestJS with log-level management.
4
4
  order: 6
5
- tags: [logging, sentry, error-tracking, analytics]
5
+ tags: [logging, log-level, nestjs]
6
6
  package: '@breadstone/archipel-platform-logging'
7
7
  ---
8
8
 
9
9
  # platform-logging
10
10
 
11
- Sentry integration for centralized error tracking and analytics. Provides structured error reporting with context enrichment.
11
+ Configurable logging module for NestJS applications with application-wide log-level management. Wraps the built-in NestJS `Logger` and configures it via the central `ConfigModule`.
12
12
 
13
13
  **Package:** `@breadstone/archipel-platform-logging`
14
14
 
@@ -24,28 +24,24 @@ import { LoggerModule } from '@breadstone/archipel-platform-logging';
24
24
  export class AppModule {}
25
25
  ```
26
26
 
27
+ The module is `@Global()` — once imported, `Logger` is available for injection across the entire application.
28
+
27
29
  ---
28
30
 
29
- ## AnalyticsService
31
+ ## Using the Logger
30
32
 
31
- Central service for error and event reporting to Sentry.
33
+ Inject the standard NestJS `Logger` provided by `LoggerModule`:
32
34
 
33
35
  ```typescript
34
- import { AnalyticsService } from '@breadstone/archipel-platform-logging';
36
+ import { Injectable, Logger } from '@nestjs/common';
35
37
 
36
38
  @Injectable()
37
39
  export class PaymentService {
38
- constructor(private readonly _analytics: AnalyticsService) {}
40
+ constructor(private readonly _logger: Logger) {}
39
41
 
40
42
  public async processPayment(orderId: string): Promise<void> {
41
- try {
42
- // ... payment logic
43
- } catch (error) {
44
- this._analytics.captureException(error, {
45
- tags: { module: 'payments', orderId },
46
- });
47
- throw error;
48
- }
43
+ this._logger.log(`Processing payment for order ${orderId}`);
44
+ // ...
49
45
  }
50
46
  }
51
47
  ```
@@ -54,39 +50,15 @@ export class PaymentService {
54
50
 
55
51
  ## Environment Variables
56
52
 
57
- | Variable | Description | Required |
58
- | --------------------------- | ---------------------------------------------------- | -------- |
59
- | `SENTRY_DSN` | Sentry Data Source Name | Yes |
60
- | `SENTRY_ENVIRONMENT` | Environment label (e.g. `'production'`, `'staging'`) | No |
61
- | `SENTRY_TRACES_SAMPLE_RATE` | Sampling rate for performance traces (0.0–1.0) | No |
62
-
63
- ---
64
-
65
- ## Real-World Example: Global Error Filter
66
-
67
- ```typescript
68
- import { Catch, type ExceptionFilter, type ArgumentsHost } from '@nestjs/common';
69
- import { AnalyticsService } from '@breadstone/archipel-platform-logging';
70
-
71
- @Catch()
72
- export class GlobalExceptionFilter implements ExceptionFilter {
73
- constructor(private readonly _analytics: AnalyticsService) {}
74
-
75
- public catch(exception: unknown, host: ArgumentsHost): void {
76
- this._analytics.captureException(exception);
77
-
78
- const ctx = host.switchToHttp();
79
- const response = ctx.getResponse();
80
- response.status(500).json({ error: 'Internal Server Error' });
81
- }
82
- }
83
- ```
53
+ | Variable | Description | Required | Default |
54
+ | --------------- | -------------------------------------------------------------- | -------- | ------- |
55
+ | `APP_LOG_LEVEL` | Application log level (`'debug'`, `'info'`, `'warn'`, `'error'`) | No | `warn` |
84
56
 
85
57
  ---
86
58
 
87
59
  ## Exports Summary
88
60
 
89
- | Export | Type | Description |
90
- | ------------------ | ------------- | -------------------------------- |
91
- | `LoggerModule` | NestJS Module | Global Sentry integration |
92
- | `AnalyticsService` | Service | Error capture and event tracking |
61
+ | Export | Type | Description |
62
+ | -------------- | ------------- | -------------------------------------------- |
63
+ | `LoggerModule` | NestJS Module | Global logging module with log-level control |
64
+ | `Logger` | Provider | NestJS Logger configured with `APP_LOG_LEVEL`|