@furkanogutcu/nest-common 1.0.0 → 1.0.1
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
@@ -12,6 +12,10 @@ This package is designed to standardize structures you repeatedly use in your Ne
|
|
12
12
|
- [Installation](#installation)
|
13
13
|
- [Features](#features)
|
14
14
|
- [Exceptions](#1-exceptions)
|
15
|
+
- [API Responses](#2-api-responses)
|
16
|
+
- [Validators and Pipes](#3-validators-and-pipes)
|
17
|
+
- [Decorators](#4-decorators)
|
18
|
+
- [Utilities](#5-utilities)
|
15
19
|
- [Development](#development)
|
16
20
|
- [License](#license)
|
17
21
|
|
@@ -39,25 +43,27 @@ No additional installation steps are needed beyond installing the package.
|
|
39
43
|
|
40
44
|
- **Custom Exception Classes**: Comprehensive set of HTTP-based exception classes for consistent error responses.
|
41
45
|
|
42
|
-
| Exception Class
|
43
|
-
|
44
|
-
| `AppException`
|
45
|
-
| `AppBadRequestException`
|
46
|
-
| `AppUnauthorizedException`
|
47
|
-
| `AppForbiddenException`
|
48
|
-
| `AppNotFoundException`
|
49
|
-
| `AppConflictException`
|
50
|
-
| `AppUnprocessableEntityException` | 422
|
51
|
-
| `AppInternalException`
|
52
|
-
| `AppTooManyRequestException`
|
53
|
-
| `AppValidationException`
|
46
|
+
| Exception Class | HTTP Status | Description |
|
47
|
+
| --------------------------------- | ----------- | -------------------------------------------------- |
|
48
|
+
| `AppException` | - | Base exception class for all custom exceptions |
|
49
|
+
| `AppBadRequestException` | 400 | For invalid input, malformed requests |
|
50
|
+
| `AppUnauthorizedException` | 401 | For authentication failures |
|
51
|
+
| `AppForbiddenException` | 403 | For authorization failures |
|
52
|
+
| `AppNotFoundException` | 404 | For resources that couldn't be found |
|
53
|
+
| `AppConflictException` | 409 | For conflicting requests (e.g., duplicate entries) |
|
54
|
+
| `AppUnprocessableEntityException` | 422 | For semantically incorrect requests |
|
55
|
+
| `AppInternalException` | 500 | For server-side errors |
|
56
|
+
| `AppTooManyRequestException` | 429 | For rate limiting scenarios |
|
57
|
+
| `AppValidationException` | 400 | Specifically for input validation errors |
|
54
58
|
|
55
59
|
- **Global Exception Filter**: Automatically catches and transforms exceptions throughout your application.
|
60
|
+
|
56
61
|
- Centralized error handling logic
|
57
62
|
- Consistent error response format
|
58
63
|
- Easy to configure through NestJS's dependency injection
|
59
64
|
|
60
65
|
- **Exception Transformers**: Converts various error types to standardized app exceptions.
|
66
|
+
|
61
67
|
- NestJS built-in exception transformer
|
62
68
|
- TypeORM exception transformer
|
63
69
|
|
@@ -155,6 +161,168 @@ The `type` field in validation error details can have the following values:
|
|
155
161
|
|
156
162
|
For more detailed information about the filters, transformers, and interfaces included in the exceptions package, please check the source code.
|
157
163
|
|
164
|
+
### 2. API Responses
|
165
|
+
|
166
|
+
#### Features
|
167
|
+
|
168
|
+
- **Standardized Response Types**: Comprehensive set of response interfaces for consistent API responses.
|
169
|
+
- `APIResponse`: Generic type for creating standardized responses
|
170
|
+
- `APIResponseOnlyMessage`: Simple message-only response
|
171
|
+
- `PaginatedAPIResponse`: Response format for paginated data with metadata
|
172
|
+
|
173
|
+
#### Usage
|
174
|
+
|
175
|
+
```typescript
|
176
|
+
import { Controller, Get, Post, Body, Param, Query } from '@nestjs/common';
|
177
|
+
import {
|
178
|
+
APIResponse,
|
179
|
+
APIResponseOnlyMessage,
|
180
|
+
PaginatedAPIResponse,
|
181
|
+
Pagination,
|
182
|
+
PaginationParams,
|
183
|
+
} from '@furkanogutcu/nest-common';
|
184
|
+
import { User } from './user.entity';
|
185
|
+
import { CreateUserDto } from './dto/create-user.dto';
|
186
|
+
|
187
|
+
@Controller('users')
|
188
|
+
export class UsersController {
|
189
|
+
constructor(private readonly usersService: UsersService) {}
|
190
|
+
|
191
|
+
@Get()
|
192
|
+
async findAll(@Pagination() { skip, take }: PaginationParams): Promise<PaginatedAPIResponse<User>> {
|
193
|
+
const { items, metadata } = await this.usersService.findAll({ skip, take });
|
194
|
+
|
195
|
+
return {
|
196
|
+
data: items,
|
197
|
+
metadata,
|
198
|
+
};
|
199
|
+
}
|
200
|
+
|
201
|
+
@Get(':id')
|
202
|
+
async findOne(@Param('id') id: string): Promise<APIResponse<'user', User>> {
|
203
|
+
const user = await this.usersService.findOne(id);
|
204
|
+
|
205
|
+
return {
|
206
|
+
user,
|
207
|
+
};
|
208
|
+
}
|
209
|
+
|
210
|
+
@Post()
|
211
|
+
async create(@Body() createUserDto: CreateUserDto): Promise<APIResponseOnlyMessage> {
|
212
|
+
await this.usersService.create(createUserDto);
|
213
|
+
|
214
|
+
return {
|
215
|
+
message: 'User created successfully',
|
216
|
+
};
|
217
|
+
}
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
### 3. Validators and Pipes
|
222
|
+
|
223
|
+
#### Features
|
224
|
+
|
225
|
+
- **Zod Validation Pipe**: Extended validation pipe for NestJS using Zod schema validation.
|
226
|
+
|
227
|
+
- Seamless integration with NestJS validation pipeline
|
228
|
+
- Throws consistent `AppValidationException` on validation errors
|
229
|
+
- Compatible with Zod schemas
|
230
|
+
|
231
|
+
- **Common Validation Schemas**:
|
232
|
+
- `paginationSchema`: For standardizing pagination parameters
|
233
|
+
- `orderBySchema`: For standardizing sorting/ordering parameters
|
234
|
+
- `searchSchema`: For standardizing search parameters
|
235
|
+
|
236
|
+
#### Usage
|
237
|
+
|
238
|
+
##### Setting up validation globally
|
239
|
+
|
240
|
+
```typescript
|
241
|
+
import { Module } from '@nestjs/common';
|
242
|
+
import { APP_PIPE } from '@nestjs/core';
|
243
|
+
import { AppZodValidationPipe } from '@furkanogutcu/nest-common';
|
244
|
+
|
245
|
+
@Module({
|
246
|
+
imports: [
|
247
|
+
// Your other modules
|
248
|
+
],
|
249
|
+
controllers: [
|
250
|
+
// Your controllers
|
251
|
+
],
|
252
|
+
providers: [
|
253
|
+
// Your other providers
|
254
|
+
{
|
255
|
+
provide: APP_PIPE,
|
256
|
+
useClass: AppZodValidationPipe,
|
257
|
+
},
|
258
|
+
],
|
259
|
+
})
|
260
|
+
export class AppModule {}
|
261
|
+
```
|
262
|
+
|
263
|
+
### 4. Decorators
|
264
|
+
|
265
|
+
#### Features
|
266
|
+
|
267
|
+
- **Parameter Decorators**: Decorators for common query parameter extraction and validation.
|
268
|
+
- `@Pagination()`: Extracts and validates pagination parameters
|
269
|
+
- `@OrderBy()`: Extracts and validates ordering parameters
|
270
|
+
- `@Search()`: Extracts and validates search parameters
|
271
|
+
|
272
|
+
#### Usage
|
273
|
+
|
274
|
+
```typescript
|
275
|
+
import { Controller, Get } from '@nestjs/common';
|
276
|
+
import { Pagination, OrderBy, Search, PaginationParams, OrderByParam, SearchParams } from '@furkanogutcu/nest-common';
|
277
|
+
|
278
|
+
@Controller('users')
|
279
|
+
export class UsersController {
|
280
|
+
@Get()
|
281
|
+
findAll(
|
282
|
+
@Pagination() { skip, take }: PaginationParams,
|
283
|
+
@OrderBy<User>(['created_at']) orderBy: OrderByParam<User>,
|
284
|
+
@Search<User>(['email']) search: SearchParams<User>,
|
285
|
+
) {
|
286
|
+
// Implement your service call with these validated parameters
|
287
|
+
return this.usersService.findAll({ skip, take, orderBy, where: search });
|
288
|
+
}
|
289
|
+
}
|
290
|
+
```
|
291
|
+
|
292
|
+
### 5. Utilities
|
293
|
+
|
294
|
+
#### Features
|
295
|
+
|
296
|
+
- **Asynchronous Utilities**:
|
297
|
+
- `exponentialRetry`: Retry a function with exponential backoff
|
298
|
+
- `sleep`: Simple promise-based delay utility
|
299
|
+
|
300
|
+
#### Usage
|
301
|
+
|
302
|
+
```typescript
|
303
|
+
import { exponentialRetry, sleep } from '@furkanogutcu/nest-common';
|
304
|
+
|
305
|
+
// Retry a function with exponential backoff
|
306
|
+
async function fetchWithRetry() {
|
307
|
+
return exponentialRetry(
|
308
|
+
async () => {
|
309
|
+
// Potentially failing operation (e.g., API call)
|
310
|
+
return await externalApiCall();
|
311
|
+
},
|
312
|
+
{
|
313
|
+
maxAttempts: 5, // Maximum of 5 attempts
|
314
|
+
baseDelayMs: 1000, // Starting delay of 1000ms (will grow exponentially)
|
315
|
+
},
|
316
|
+
);
|
317
|
+
}
|
318
|
+
|
319
|
+
// Simple delay utility
|
320
|
+
async function processWithDelay() {
|
321
|
+
await sleep(2000); // Wait for 2 seconds
|
322
|
+
// Continue execution
|
323
|
+
}
|
324
|
+
```
|
325
|
+
|
158
326
|
## Development
|
159
327
|
|
160
328
|
### Requirements
|
@@ -1 +1,5 @@
|
|
1
|
-
export
|
1
|
+
export interface ExponentialRetryOptions {
|
2
|
+
maxAttempts?: number;
|
3
|
+
baseDelayMs?: number;
|
4
|
+
}
|
5
|
+
export declare function exponentialRetry<T>(fn: () => Promise<T>, options?: ExponentialRetryOptions): Promise<T>;
|
@@ -2,7 +2,9 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.exponentialRetry = exponentialRetry;
|
4
4
|
const sleep_util_1 = require("./sleep.util");
|
5
|
-
async function exponentialRetry(fn,
|
5
|
+
async function exponentialRetry(fn, options) {
|
6
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
7
|
+
const baseDelayMs = options?.baseDelayMs ?? 2000;
|
6
8
|
let lastError = null;
|
7
9
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
8
10
|
try {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"exponential-retry.util.js","sourceRoot":"","sources":["../../src/utils/exponential-retry.util.ts"],"names":[],"mappings":";;
|
1
|
+
{"version":3,"file":"exponential-retry.util.js","sourceRoot":"","sources":["../../src/utils/exponential-retry.util.ts"],"names":[],"mappings":";;AAOA,4CAqBC;AA5BD,6CAAqC;AAO9B,KAAK,UAAU,gBAAgB,CAAI,EAAoB,EAAE,OAAiC;IAC/F,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC;IAEjD,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,IAAI,OAAO,KAAK,WAAW;gBAAE,MAAM,SAAS,CAAC;YAE7C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC;YAEjD,MAAM,IAAA,kBAAK,EAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;AAChD,CAAC"}
|