nesties 1.1.15 → 1.1.17

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Nest.js utilities**
4
4
 
5
- Nesties is a utility library for Nest.js applications, designed to simplify and enhance common patterns such as decorators, response structures, and request validation. This library provides a set of utilities to streamline your development workflow and improve code reuse and clarity when working with Nest.js.
5
+ Nesties is a utility library for Nest.js applications, designed to simplify and enhance common patterns such as decorators, response structures, request validation, and HTTP-level concerns such as tokens and i18n. This library provides a set of utilities to streamline your development workflow and improve code reuse and clarity when working with Nest.js.
6
6
 
7
7
  ## Features
8
8
 
@@ -10,7 +10,10 @@ Nesties is a utility library for Nest.js applications, designed to simplify and
10
10
  - **Predefined API Responses**: Simplified and consistent response structures for APIs.
11
11
  - **Data Validation Pipes**: Validation pipe utilities to handle query and body validation effortlessly.
12
12
  - **Custom Guards**: Easily implement token-based guards and API header validation.
13
+ - **ParamResolver utilities**: Strongly-typed access to headers and query parameters, including dynamic and request-scoped resolvers.
13
14
  - **Pagination and Return DTOs**: DTOs for standard and paginated API responses.
15
+ - **AbortableModule**: Request-lifetime-aware abort signals for long-running work.
16
+ - **I18nModule**: Locale-aware translation for response DTOs and strings.
14
17
 
15
18
  ## Installation
16
19
 
@@ -34,7 +37,7 @@ Nesties allows you to merge multiple decorators of the same type (property, meth
34
37
 
35
38
  - **Property Decorator**
36
39
 
37
- ```typescript
40
+ ```ts
38
41
  import { MergePropertyDecorators } from 'nesties';
39
42
 
40
43
  const CombinedPropertyDecorator = MergePropertyDecorators([Decorator1, Decorator2]);
@@ -42,7 +45,7 @@ const CombinedPropertyDecorator = MergePropertyDecorators([Decorator1, Decorator
42
45
 
43
46
  - **Method Decorator**
44
47
 
45
- ```typescript
48
+ ```ts
46
49
  import { MergeMethodDecorators } from 'nesties';
47
50
 
48
51
  const CombinedMethodDecorator = MergeMethodDecorators([Decorator1, Decorator2]);
@@ -50,7 +53,7 @@ const CombinedMethodDecorator = MergeMethodDecorators([Decorator1, Decorator2]);
50
53
 
51
54
  - **Class Decorator**
52
55
 
53
- ```typescript
56
+ ```ts
54
57
  import { MergeClassDecorators } from 'nesties';
55
58
 
56
59
  const CombinedClassDecorator = MergeClassDecorators([Decorator1, Decorator2]);
@@ -58,7 +61,7 @@ const CombinedClassDecorator = MergeClassDecorators([Decorator1, Decorator2]);
58
61
 
59
62
  - **Parameter Decorator**
60
63
 
61
- ```typescript
64
+ ```ts
62
65
  import { MergeParameterDecorators } from 'nesties';
63
66
 
64
67
  const CombinedParameterDecorator = MergeParameterDecorators([Decorator1, Decorator2]);
@@ -68,7 +71,7 @@ const CombinedParameterDecorator = MergeParameterDecorators([Decorator1, Decorat
68
71
 
69
72
  Nesties includes a utility for defining API error responses conveniently.
70
73
 
71
- ```typescript
74
+ ```ts
72
75
  import { ApiError } from 'nesties';
73
76
 
74
77
  @ApiError(401, 'Unauthorized access')
@@ -80,7 +83,7 @@ Nesties provides utilities for creating validation pipes with automatic data tra
80
83
 
81
84
  - **Data Pipe**
82
85
 
83
- ```typescript
86
+ ```ts
84
87
  import { DataPipe } from 'nesties';
85
88
 
86
89
  const validationPipe = DataPipe();
@@ -88,13 +91,13 @@ const validationPipe = DataPipe();
88
91
 
89
92
  - **Decorators for Request Validation**
90
93
 
91
- ```typescript
94
+ ```ts
92
95
  import { DataQuery, DataBody } from 'nesties';
93
96
 
94
97
  class ExampleController {
95
- myMethod(@DataQuery() query: MyQueryDto, @DataBody() body: MyBodyDto) {
98
+ myMethod(@DataQuery() query: MyQueryDto, @DataBody() body: MyBodyDto) {
96
99
  // ...
97
- }
100
+ }
98
101
  }
99
102
  ```
100
103
 
@@ -107,10 +110,19 @@ Nesties provides a set of DTOs for consistent API response structures, and it al
107
110
  - **PaginatedReturnMessageDto**: For paginated responses, including metadata about pagination.
108
111
  - **ReturnMessageDto**: A utility function for generating DTOs based on a class type.
109
112
 
110
- ```typescript
111
- import { BlankReturnMessageDto, GenericReturnMessageDto, PaginatedReturnMessageDto, ReturnMessageDto } from 'nesties';
113
+ ```ts
114
+ import {
115
+ BlankReturnMessageDto,
116
+ GenericReturnMessageDto,
117
+ PaginatedReturnMessageDto,
118
+ ReturnMessageDto,
119
+ } from 'nesties';
112
120
 
113
- const response = new GenericReturnMessageDto(200, 'Operation successful', myData);
121
+ const response = new GenericReturnMessageDto(
122
+ 200,
123
+ 'Operation successful',
124
+ myData,
125
+ );
114
126
  ```
115
127
 
116
128
  #### Example Usage of `ReturnMessageDto`
@@ -119,45 +131,48 @@ const response = new GenericReturnMessageDto(200, 'Operation successful', myData
119
131
 
120
132
  Suppose we have a `User` class:
121
133
 
122
- ```typescript
134
+ ```ts
123
135
  import { ApiProperty } from '@nestjs/swagger';
124
136
 
125
137
  class User {
126
- @ApiProperty({ description: 'The unique ID of the user', type: Number })
127
- id: number;
138
+ @ApiProperty({ description: 'The unique ID of the user', type: Number })
139
+ id: number;
128
140
 
129
- @ApiProperty({ description: 'The name of the user', type: String })
130
- name: string;
141
+ @ApiProperty({ description: 'The name of the user', type: String })
142
+ name: string;
131
143
 
132
- @ApiProperty({ description: 'The email address of the user', type: String })
133
- email: string;
144
+ @ApiProperty({ description: 'The email address of the user', type: String })
145
+ email: string;
134
146
  }
135
147
  ```
136
148
 
137
149
  You can create a return message DTO for this class:
138
150
 
139
- ```typescript
151
+ ```ts
140
152
  import { ReturnMessageDto } from 'nesties';
141
153
 
142
154
  class UserReturnMessageDto extends ReturnMessageDto(User) {}
143
155
 
144
- const response = new UserReturnMessageDto(200, 'Success', { id: 1, name: 'John Doe', email: 'john.doe@example.com' });
156
+ const response = new UserReturnMessageDto(200, 'Success', {
157
+ id: 1,
158
+ name: 'John Doe',
159
+ email: 'john.doe@example.com',
160
+ });
145
161
  ```
146
162
 
147
- This approach automatically creates a DTO structure with the properties of `User` integrated as the data field, ensuring consistency and reusability in your API responses.
148
-
149
-
150
- ```
163
+ This approach automatically creates a DTO structure with the properties of `User` integrated as the `data` field, ensuring consistency and reusability in your API responses.
151
164
 
152
165
  ### 5. Token Guard
153
166
 
154
167
  `TokenGuard` validates a single “server token” before invoking a controller method. By default it reads `SERVER_TOKEN` from `ConfigService` and compares it with the `x-server-token` header, returning a `401` when they differ.
155
168
 
169
+ Internally, `TokenGuard` uses the same resolver primitives as `ParamResolver`, so you can read tokens from headers, query parameters, or custom logic that depends on the request and `ModuleRef`.
170
+
156
171
  #### Quick start (defaults only)
157
172
 
158
173
  1. **Load the config module**
159
174
 
160
- ```typescript
175
+ ```ts
161
176
  import { ConfigModule } from '@nestjs/config';
162
177
 
163
178
  @Module({
@@ -168,13 +183,13 @@ This approach automatically creates a DTO structure with the properties of `User
168
183
 
169
184
  2. **Set the secret**
170
185
 
171
- ```
186
+ ```text
172
187
  SERVER_TOKEN=your-secure-token
173
188
  ```
174
189
 
175
190
  3. **Decorate the route**
176
191
 
177
- ```typescript
192
+ ```ts
178
193
  import { Controller, Get } from '@nestjs/common';
179
194
  import { RequireToken } from 'nesties';
180
195
 
@@ -194,11 +209,16 @@ This approach automatically creates a DTO structure with the properties of `User
194
209
 
195
210
  When you need to override the defaults, pass options into `RequireToken`:
196
211
 
197
- - `resolver` (default: `{ paramType: 'header', paramName: 'x-server-token' }`): where to read the **client** token from. Accepts any `ResolverDual`, so query/header resolvers are all supported.
198
- - `tokenSource` (default: `'SERVER_TOKEN'`): how to read the **server** token. Provide another config key or an async resolver `(ctx, moduleRef) => Promise<string>` for dynamic sources.
212
+ - `resolver` (default: `{ paramType: 'header', paramName: 'x-server-token' }`): where to read the **client** token from. Accepts any **ParamResolver input**:
213
+ - a static header/query descriptor: `{ paramType: 'header' | 'query', paramName: string }`
214
+ - a `ParamResolver` instance
215
+ - `tokenSource` (default: `'SERVER_TOKEN'`): how to read the **server** token. Provide another config key or an async resolver `(req, moduleRef) => Promise<string | undefined>` for dynamic sources.
199
216
  - `errorCode` (default: `401`): HTTP status when tokens do not match.
200
217
 
201
- ```typescript
218
+ ```ts
219
+ import { Controller, Get } from '@nestjs/common';
220
+ import { RequireToken } from 'nesties';
221
+
202
222
  @Controller('api')
203
223
  export class ApiController {
204
224
  @Get('protected')
@@ -213,34 +233,42 @@ export class ApiController {
213
233
  }
214
234
  ```
215
235
 
216
- Multi-tenant secrets are just another `tokenSource` resolver:
236
+ Multi-tenant secrets are just another `tokenSource` resolver. You can compose them using `ParamResolver`:
217
237
 
218
- ```typescript
238
+ ```ts
219
239
  import { ConfigService } from '@nestjs/config';
220
- import { createResolver } from 'nesties';
240
+ import { ParamResolver } from 'nesties';
221
241
 
222
- const headerResolver = { paramType: 'header', paramName: 'x-tenant-token' };
242
+ const tenantIdResolver = new ParamResolver({
243
+ paramType: 'header',
244
+ paramName: 'x-tenant-id',
245
+ });
223
246
 
224
247
  @RequireToken({
225
- resolver: headerResolver,
226
- tokenSource: async (ctx, moduleRef) => {
227
- const tenantId = await createResolver({
228
- paramType: 'header',
229
- paramName: 'x-tenant-id',
230
- })(ctx, moduleRef);
248
+ resolver: { paramType: 'header', paramName: 'x-tenant-token' },
249
+ tokenSource: async (req, moduleRef) => {
250
+ // reuse the same ParamResolver primitives
251
+ const getTenantId = tenantIdResolver.toResolverFunction();
252
+ const tenantId = await getTenantId(req, moduleRef);
253
+
231
254
  const config = moduleRef.get(ConfigService);
232
- return config.get<string>(`TENANT_${tenantId}_TOKEN`);
255
+ return tenantId
256
+ ? config.get<string>(`TENANT_${tenantId}_TOKEN`)
257
+ : undefined;
233
258
  },
234
259
  })
260
+ export class TenantController {
261
+ // ...
262
+ }
235
263
  ```
236
264
 
237
265
  `TokenGuard` only throws when both values exist and differ, so clearing the config value temporarily disables the guard without a code change.
238
266
 
239
267
  ### 6. AbortableModule
240
268
 
241
- Use `AbortableModule` when you want longrunning providers to respect the lifetime of the HTTP request. The module exposes a requestscoped `AbortSignal` and wraps existing providers with [`nfkit`](https://www.npmjs.com/package/nfkit)'s `abortable` helper so that work can be canceled automatically when the client disconnects.
269
+ Use `AbortableModule` when you want long-running providers to respect the lifetime of the HTTP request. The module exposes a request-scoped `AbortSignal` and wraps existing providers with [`nfkit`](https://www.npmjs.com/package/nfkit)'s `abortable` helper so that work can be canceled automatically when the client disconnects.
242
270
 
243
- ```typescript
271
+ ```ts
244
272
  import { AbortableModule, InjectAbortable } from 'nesties';
245
273
 
246
274
  @Module({
@@ -264,7 +292,7 @@ export class DemoModule {
264
292
 
265
293
  #### Injecting `AbortSignal` with `@nestjs/axios`
266
294
 
267
- ```typescript
295
+ ```ts
268
296
  import { HttpModule, HttpService } from '@nestjs/axios';
269
297
  import {
270
298
  AbortableModule,
@@ -295,13 +323,15 @@ export class WeatherModule {
295
323
  }
296
324
  ```
297
325
 
298
- The wrapped `HttpService` observes the same abort signal as the request, so inflight HTTP calls will be canceled as soon as the client disconnects or Nest aborts the request scope.
326
+ The wrapped `HttpService` observes the same abort signal as the request, so in-flight HTTP calls will be canceled as soon as the client disconnects or Nest aborts the request scope.
299
327
 
300
328
  ### 7. I18nModule
301
329
 
302
330
  Nesties also ships an opinionated but flexible internationalization module. The typical workflow is to call `createI18n` to obtain `I18nModule` plus the `UseI18n` decorator, register locale lookup middleware (e.g., `I18nLookupMiddleware`), and then return DTOs that contain placeholders like `#{key}`—the interceptor installed by `@UseI18n()` will translate those placeholders automatically before the response leaves the server.
303
331
 
304
- ```typescript
332
+ Internally, locale resolution uses the same resolver primitives as `ParamResolver`, so you can read the locale from headers, query parameters, or a custom `(req, moduleRef) => Promise<string | undefined>` function.
333
+
334
+ ```ts
305
335
  import {
306
336
  createI18n,
307
337
  I18nService,
@@ -312,6 +342,7 @@ import {
312
342
  const { I18nModule, UseI18n } = createI18n({
313
343
  locales: ['en-US', 'zh-CN'],
314
344
  defaultLocale: 'en-US',
345
+ // resolver: { paramType: 'header', paramName: 'accept-language' } by default
315
346
  });
316
347
 
317
348
  @Module({
@@ -338,12 +369,19 @@ export class GreetingController {
338
369
  });
339
370
  }
340
371
  }
372
+ ```
341
373
 
342
374
  #### `@PutLocale()` Per-handler Overrides
343
375
 
344
- `@PutLocale()` lets you override how the locale is resolved for a specific handler or parameter. Pass a custom resolver (any shape supported by `ResolverDual`) when you want to read the locale from a query param, body field, or even headers different from the global resolver.
376
+ `@PutLocale()` lets you override how the locale is resolved for a specific handler or parameter. It accepts the same inputs as `ParamResolver`:
377
+
378
+ - a static header/query descriptor: `{ paramType: 'header' | 'query', paramName: string }`
379
+ - a `ParamResolver` instance
380
+ - a dynamic resolver `(req, moduleRef) => Promise<string | undefined>`
345
381
 
346
- ```typescript
382
+ When you pass a static descriptor, a `ParamResolver` is created under the hood:
383
+
384
+ ```ts
347
385
  import { GenericReturnMessageDto, PutLocale } from 'nesties';
348
386
 
349
387
  @Controller('reports')
@@ -361,11 +399,37 @@ export class ReportController {
361
399
  }
362
400
  ```
363
401
 
402
+ You can also plug in dynamic logic using a `ParamResolver` instance:
403
+
404
+ ```ts
405
+ import { ParamResolver, PutLocale } from 'nesties';
406
+ import { ContextIdFactory, ModuleRef } from '@nestjs/core';
407
+ import { LocaleService } from './locale.service';
408
+
409
+ const dynamicLocaleResolver = new ParamResolver(async (req, ref: ModuleRef) => {
410
+ // example: delegate to a request-scoped LocaleService
411
+ const contextId = ContextIdFactory.getByRequest(req);
412
+ const svc = await ref.resolve(LocaleService, contextId, { strict: false });
413
+ return svc.detectLocale(req);
414
+ });
415
+
416
+ @Controller('dynamic-reports')
417
+ @UseI18n()
418
+ export class DynamicReportController {
419
+ @Get()
420
+ async summary(@PutLocale(dynamicLocaleResolver) locale: string) {
421
+ return new GenericReturnMessageDto(200, 'OK', {
422
+ summary: 'dynamic.report.summary',
423
+ });
424
+ }
425
+ }
426
+ ```
427
+
364
428
  #### Custom Middleware with TypeORM
365
429
 
366
430
  You can register any number of middlewares that resolve placeholders. The example below queries a TypeORM repository to fetch translations stored in a database and falls back to the next middleware when no record is found.
367
431
 
368
- ```typescript
432
+ ```ts
369
433
  import { ExecutionContext, Injectable } from '@nestjs/common';
370
434
  import { InjectRepository } from '@nestjs/typeorm';
371
435
  import {
@@ -426,28 +490,218 @@ By composing multiple middlewares (dictionaries, database lookups, remote APIs),
426
490
  - `LocalePipe`/`PutLocale` provide ergonomic access to the resolved locale inside route handlers, and you can override the resolver per parameter when necessary.
427
491
  - `I18nService.translate` and `translateString` remain available for advanced manual flows (generating strings outside of interceptor scope, building static assets, etc.).
428
492
 
429
- ## DTO Classes
493
+ ### 8. ParamResolver
494
+
495
+ `ParamResolver` and `CombinedParamResolver` provide a small, composable abstraction over headers and query parameters. They are used internally by `TokenGuard`, the i18n utilities, and can also be used directly in controllers, pipes, and guards.
496
+
497
+ #### Static header / query resolvers
498
+
499
+ The simplest usage is to read a single header or query parameter:
500
+
501
+ ```ts
502
+ import { Controller, Get } from '@nestjs/common';
503
+ import { ParamResolver } from 'nesties';
504
+
505
+ const langHeaderResolver = new ParamResolver({
506
+ paramType: 'header',
507
+ paramName: 'accept-language',
508
+ });
509
+
510
+ const LangHeader = langHeaderResolver.toParamDecorator();
511
+ const ApiLangHeader = langHeaderResolver.toApiPropertyDecorator();
512
+
513
+ @Controller()
514
+ export class LocaleController {
515
+ @Get('header-locale')
516
+ @ApiLangHeader() // documents the header in Swagger
517
+ getLocale(@LangHeader() locale: string | undefined) {
518
+ return { locale };
519
+ }
520
+ }
521
+ ```
522
+
523
+ For query parameters:
524
+
525
+ ```ts
526
+ const langQueryResolver = new ParamResolver({
527
+ paramType: 'query',
528
+ paramName: 'locale',
529
+ });
530
+
531
+ const LangQuery = langQueryResolver.toParamDecorator();
532
+
533
+ @Controller()
534
+ export class QueryLocaleController {
535
+ @Get('query-locale')
536
+ getLocale(@LangQuery() locale: string | undefined) {
537
+ return { locale };
538
+ }
539
+ }
540
+ ```
541
+
542
+ Static header resolvers normalize header names to lowercase and perform a best-effort lookup across `req.headers` and common Express-style helpers (`req.get`, `req.header`, `req.getHeader`). Query resolvers first consult `req.query`, then fall back to parsing the current URL when needed.
543
+
544
+ #### Dynamic resolvers with `ModuleRef`
545
+
546
+ When you need more control, `ParamResolver` also accepts a dynamic function `(req, moduleRef) => Promise<string | undefined>`. This is ideal for request-scoped dependencies or multi-step lookups.
547
+
548
+ ```ts
549
+ import { ParamResolver } from 'nesties';
550
+ import { ContextIdFactory, ModuleRef } from '@nestjs/core';
551
+ import { RequestScopedLocaleService } from './locale.service';
552
+
553
+ const dynamicLocaleResolver = new ParamResolver(
554
+ async (req, ref: ModuleRef) => {
555
+ const contextId = ContextIdFactory.getByRequest(req);
556
+ const svc = await ref.resolve(RequestScopedLocaleService, contextId, {
557
+ strict: false,
558
+ });
559
+ return svc.detectLocale(req);
560
+ },
561
+ );
562
+
563
+ const DynamicLocale = dynamicLocaleResolver.toParamDecorator();
564
+
565
+ @Controller()
566
+ export class DynamicLocaleController {
567
+ @Get('dynamic-locale')
568
+ getLocale(@DynamicLocale() locale: string | undefined) {
569
+ return { locale };
570
+ }
571
+ }
572
+ ```
573
+
574
+ You can also call dynamic resolvers manually via `toResolverFunction()`:
575
+
576
+ ```ts
577
+ import type { Request } from 'express';
578
+
579
+ @Injectable()
580
+ export class LocaleConsumerService {
581
+ constructor(private readonly moduleRef: ModuleRef) {}
582
+
583
+ async getLocale(req: Request) {
584
+ const fn = dynamicLocaleResolver.toResolverFunction();
585
+ return fn(req, this.moduleRef);
586
+ }
587
+ }
588
+ ```
589
+
590
+ #### Combining multiple resolvers
591
+
592
+ `CombinedParamResolver` lets you compose several resolvers into a single object result and merges their Swagger decorators.
593
+
594
+ ```ts
595
+ import {
596
+ CombinedParamResolver,
597
+ ParamResolver,
598
+ TypeFromParamResolver,
599
+ } from 'nesties';
600
+
601
+ const langResolver = new ParamResolver({
602
+ paramType: 'header',
603
+ paramName: 'accept-language',
604
+ });
605
+
606
+ const tokenResolver = new ParamResolver({
607
+ paramType: 'header',
608
+ paramName: 'x-access-token',
609
+ });
610
+
611
+ const combinedResolver = new CombinedParamResolver({
612
+ lang: langResolver,
613
+ token: tokenResolver,
614
+ });
615
+
616
+ type CombinedResult = TypeFromParamResolver<typeof combinedResolver>;
617
+ // CombinedResult = { lang: string | undefined; token: string | undefined }
618
+
619
+ const CombinedParam = combinedResolver.toParamDecorator();
620
+ const ApiCombined = combinedResolver.toApiPropertyDecorator();
621
+
622
+ @Controller()
623
+ export class CombinedController {
624
+ @Get('combined')
625
+ @ApiCombined()
626
+ inspect(@CombinedParam() params: CombinedResult) {
627
+ return params; // { lang, token }
628
+ }
629
+ }
630
+ ```
631
+
632
+ When used as a decorator, the combined resolver:
633
+
634
+ - Executes each underlying resolver in parallel (`Promise.all`)
635
+ - Returns a typed object where each key corresponds to the original resolver
636
+ - Emits merged Swagger metadata for all headers / queries involved
637
+
638
+ #### Request-scoped providers from resolvers
639
+
640
+ Sometimes you want to treat the resolved value itself as an injectable request-scoped provider. You can derive such a provider from any `ParamResolver` or `CombinedParamResolver` using `toRequestScopedProvider()`:
641
+
642
+ ```ts
643
+ import { Module } from '@nestjs/common';
644
+ import { ParamResolver } from 'nesties';
645
+
646
+ const userIdResolver = new ParamResolver({
647
+ paramType: 'header',
648
+ paramName: 'x-user-id',
649
+ });
650
+
651
+ const userIdProviderMeta = userIdResolver.toRequestScopedProvider();
652
+
653
+ @Module({
654
+ providers: [userIdProviderMeta.provider],
655
+ })
656
+ export class UserModule {
657
+ constructor(
658
+ @userIdProviderMeta.inject()
659
+ private readonly userId: string | undefined,
660
+ ) {}
661
+
662
+ // userId is now resolved once per request and injectable anywhere in scope
663
+ }
664
+ ```
665
+
666
+ This pattern is useful when you want to reuse the same resolver logic in guards, interceptors, and services without manually passing around the `Request` object.
667
+
668
+ #### Helper functions and deprecations
669
+
670
+ - `getParamResolver(input: ParamResolverInput)`
671
+ Normalizes either a static descriptor or a `ParamResolver` instance into a resolver instance.
672
+
673
+ - `createResolver(input: ParamResolverInput)`
674
+ Returns `ParamResolver.toResolverFunction()` for quick inline usage. This is kept for backwards compatibility and may be deprecated in favor of constructing `new ParamResolver(input)` directly.
675
+
676
+ - `ApiFromResolver(input: ParamResolverInput, extras?: ApiHeaderOptions | ApiQueryOptions)`
677
+ Convenience helper to generate Swagger decorators from resolver inputs.
678
+
679
+ ### 9. DTO Classes
430
680
 
431
681
  - **BlankReturnMessageDto**: A basic DTO for standardized API responses.
432
682
  - **BlankPaginatedReturnMessageDto**: A DTO for paginated API responses.
433
683
  - **GenericReturnMessageDto**: A generic DTO for returning data of any type.
434
684
  - **StringReturnMessageDto**: A simple DTO for string responses.
435
685
 
436
- ```typescript
686
+ ```ts
437
687
  import { StringReturnMessageDto } from 'nesties';
438
688
 
439
- const response = new StringReturnMessageDto(200, 'Success', 'This is a string response');
689
+ const response = new StringReturnMessageDto(
690
+ 200,
691
+ 'Success',
692
+ 'This is a string response',
693
+ );
440
694
  ```
441
695
 
442
696
  ## Configuration
443
697
 
444
698
  The `TokenGuard` class uses the `ConfigService` from `@nestjs/config` to access configuration values, such as the `SERVER_TOKEN`. Make sure you have `@nestjs/config` installed and configured in your Nest.js project.
445
699
 
446
- ```typescript
700
+ ```ts
447
701
  import { ConfigModule } from '@nestjs/config';
448
702
 
449
703
  @Module({
450
- imports: [ConfigModule.forRoot()],
704
+ imports: [ConfigModule.forRoot()],
451
705
  })
452
706
  export class AppModule {}
453
707
  ```