@bts-soft/core 2.3.3 → 2.3.6
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 +63 -175
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -36,178 +36,61 @@ The ecosystem is built on three core pillars:
|
|
|
36
36
|
|
|
37
37
|
## Deep Dive: `@bts-soft/validation`
|
|
38
38
|
|
|
39
|
-
The validation module is the
|
|
39
|
+
The validation module is the primary security layer for BTS Soft applications. It implements a "Validation-at-the-Edge" philosophy, where data is validated, sanitized, and transformed before it reaches the service layer.
|
|
40
40
|
|
|
41
|
-
###
|
|
41
|
+
### Key Features
|
|
42
42
|
|
|
43
|
-
Every text-based decorator
|
|
43
|
+
1. **Declarative Security**: Every text-based decorator integrates the `SQL_INJECTION_REGEX` to filter malicious patterns.
|
|
44
|
+
2. **Smart Transformations**: Leverages `class-transformer` for automatic data normalization (e.g., auto-capitalization of names, lowercase emails, and digit-only national IDs).
|
|
45
|
+
3. **Protocol Agnostic**: Native support for both REST (Express) and GraphQL (Apollo), allowing a single DTO to serve both architectures via the `isGraphql` flag.
|
|
46
|
+
4. **Policy-Driven Passwords**: Comprehensive password validation with three configurable complexity levels.
|
|
44
47
|
|
|
45
48
|
---
|
|
46
49
|
|
|
47
|
-
###
|
|
50
|
+
### Core Decorators
|
|
48
51
|
|
|
49
|
-
#### 1.
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
- **Usage (REST)**:
|
|
54
|
-
```typescript
|
|
55
|
-
class LoginDto {
|
|
56
|
-
@EmailField()
|
|
57
|
-
email: string;
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
- **Usage (GraphQL)**:
|
|
61
|
-
```typescript
|
|
62
|
-
@InputType()
|
|
63
|
-
class RegisterInput {
|
|
64
|
-
@EmailField(false, true)
|
|
65
|
-
email: string;
|
|
66
|
-
}
|
|
67
|
-
```
|
|
52
|
+
#### 1. Identity & Security
|
|
53
|
+
- **`@PasswordField`**: Supports `ALPHANUMERIC`, `SYMBOLIC`, and `COMPREHENSIVE` complexity scenarios.
|
|
54
|
+
- **`@NationalIdField`**: Specialized for Egyptian National IDs (14 digits) with auto-stripping of non-digits.
|
|
55
|
+
- **`@IdField`**: Flexible validation for generic IDs (ULID, UUID, etc) with length enforcement.
|
|
68
56
|
|
|
69
|
-
#### 2.
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
class ChangePasswordDto {
|
|
76
|
-
@PasswordField(12, 32)
|
|
77
|
-
newPassword: string;
|
|
78
|
-
}
|
|
79
|
-
```
|
|
57
|
+
#### 2. Text & Content
|
|
58
|
+
- **`@NameField`**: Validates names and automatically applies title-case (e.g., "omar sabry" → "Omar Sabry").
|
|
59
|
+
- **`@CapitalTextField`**: Generic text field with auto-capitalization for proper nouns like cities.
|
|
60
|
+
- **`@TextField`**: Standard input field with length limits and strict SQL injection checks.
|
|
61
|
+
- **`@DescriptionField`**: Designed for long-form content with support for newlines and special punctuation.
|
|
62
|
+
- **`@UsernameField`**: Enforces system-level handle rules (3-30 chars, starts with a letter).
|
|
80
63
|
|
|
81
|
-
#### 3.
|
|
82
|
-
Validates and
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@PhoneField('SA')
|
|
89
|
-
whatsappNumber: string;
|
|
90
|
-
}
|
|
91
|
-
```
|
|
64
|
+
#### 3. Contact & Primitives
|
|
65
|
+
- **`@EmailField`**: Validates email format and normalizes input to lowercase.
|
|
66
|
+
- **`@PhoneField`**: Validates international phone numbers using `libphonenumber-js` with regional support.
|
|
67
|
+
- **`@UrlField`**: Validates web addresses and ensures lowercase normalization.
|
|
68
|
+
- **`@NumberField`**: Supports integers and floats with flexible min/max constraints.
|
|
69
|
+
- **`@BooleanField`**: Strict boolean checking for logic flags.
|
|
70
|
+
- **`@DateField`**: Handles date strings and Date objects with automatic type conversion.
|
|
92
71
|
|
|
93
|
-
|
|
94
|
-
Strict validation for Egyptian National IDs.
|
|
95
|
-
- **Rules**: Exactly 14 digits, must start with 2 or 3.
|
|
96
|
-
- **Cleaning**: Removes any non-digit input automatically.
|
|
97
|
-
- **Usage**:
|
|
98
|
-
```typescript
|
|
99
|
-
class IdentityDto {
|
|
100
|
-
@NationalIdField()
|
|
101
|
-
nationalId: string;
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
#### 5. `@NameField(nullable?: boolean, isGraphql?: boolean)`
|
|
106
|
-
Validates personal names with automatic title-case capitalization.
|
|
107
|
-
- **Logic**: Capitalizes the first letter of every name segment.
|
|
108
|
-
- **Constraints**: 2-100 characters.
|
|
109
|
-
- **Usage**:
|
|
110
|
-
```typescript
|
|
111
|
-
class UpdateUserDto {
|
|
112
|
-
@NameField()
|
|
113
|
-
fullName: string; // "omar sabry" -> "Omar Sabry"
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
#### 6. `@DescriptionField(nullable?: boolean, isGraphql?: boolean)`
|
|
118
|
-
Designed for long-form text content like biographies or comments.
|
|
119
|
-
- **Constraints**: 10-2000 characters.
|
|
120
|
-
- **Logic**: Allows more characters than `TextField` (includes newlines and specialized punctuation).
|
|
121
|
-
- **Usage**:
|
|
122
|
-
```typescript
|
|
123
|
-
class UpdateBioDto {
|
|
124
|
-
@DescriptionField()
|
|
125
|
-
biography: string;
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
#### 7. `@NumberField(isInteger?: boolean, min?: number, max?: number, nullable?: boolean, isGraphql?: boolean)`
|
|
130
|
-
Versatile numeric validation.
|
|
131
|
-
- **Options**: Toggle between integer and float.
|
|
132
|
-
- **Usage**:
|
|
133
|
-
```typescript
|
|
134
|
-
class ProductDto {
|
|
135
|
-
@NumberField(true, 1, 1000)
|
|
136
|
-
stockCount: number;
|
|
137
|
-
|
|
138
|
-
@NumberField(false, 0.01)
|
|
139
|
-
price: number;
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
#### 8. `@UsernameField(nullable?: boolean, isGraphql?: boolean)`
|
|
144
|
-
Validates standard system usernames.
|
|
145
|
-
- **Rules**: 3-30 characters, Alphanumeric + Underscore, must start with a letter.
|
|
146
|
-
- **Usage**:
|
|
147
|
-
```typescript
|
|
148
|
-
class SetUsernameDto {
|
|
149
|
-
@UsernameField()
|
|
150
|
-
username: string;
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
#### 9. `@TextField(text: string, min?: number, max?: number, nullable?: boolean, isGraphql?: boolean)`
|
|
155
|
-
The "Swiss Army Knife" for general text inputs.
|
|
156
|
-
- **Features**: Customizable error messages, length limits, and SQLi protection.
|
|
157
|
-
- **Default**: Min 1, Max 255.
|
|
158
|
-
- **Usage**:
|
|
159
|
-
```typescript
|
|
160
|
-
class SearchDto {
|
|
161
|
-
@TextField('Search Query', 3, 50)
|
|
162
|
-
q: string;
|
|
163
|
-
}
|
|
164
|
-
```
|
|
72
|
+
---
|
|
165
73
|
|
|
166
|
-
|
|
167
|
-
Similar to `TextField` but enforces capitalization on every word.
|
|
168
|
-
- **Usage**: Useful for City names, Country names, or Titles.
|
|
74
|
+
### Implementation Example
|
|
169
75
|
|
|
170
|
-
#### 11. `@DateField(nullable?: boolean, isGraphql?: boolean)`
|
|
171
|
-
Validates and converts input into a JavaScript `Date` object.
|
|
172
|
-
- **Usage**:
|
|
173
76
|
```typescript
|
|
174
|
-
|
|
175
|
-
@DateField()
|
|
176
|
-
startDate: Date;
|
|
177
|
-
}
|
|
178
|
-
```
|
|
77
|
+
import { NameField, EmailField, PasswordField, PasswordComplexity } from '@bts-soft/validation';
|
|
179
78
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
class PreferencesDto {
|
|
185
|
-
@BooleanField()
|
|
186
|
-
isPublic: boolean;
|
|
187
|
-
}
|
|
188
|
-
```
|
|
79
|
+
export class RegisterUserDto {
|
|
80
|
+
@NameField('Full Name')
|
|
81
|
+
name: string;
|
|
189
82
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
- **Usage**:
|
|
193
|
-
```typescript
|
|
194
|
-
enum UserRole { ADMIN = 'admin', USER = 'user' }
|
|
83
|
+
@EmailField()
|
|
84
|
+
email: string;
|
|
195
85
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
role: UserRole;
|
|
86
|
+
@PasswordField(12, 32, PasswordComplexity.COMPREHENSIVE)
|
|
87
|
+
password: string;
|
|
199
88
|
}
|
|
200
89
|
```
|
|
201
90
|
|
|
202
|
-
#### 14. `@UrlField(nullable?: boolean, isGraphql?: boolean)`
|
|
203
|
-
Validates complete web URLs.
|
|
204
|
-
- **Logic**: Enforces protocol and converts host to lowercase.
|
|
205
|
-
|
|
206
|
-
#### 15. `@IdField(length?: number, nullable?: boolean, isGraphql?: boolean)`
|
|
207
|
-
Generic length-based ID validation (useful for ULID/UUID patterns).
|
|
208
|
-
|
|
209
91
|
---
|
|
210
92
|
|
|
93
|
+
|
|
211
94
|
### Utility Exports
|
|
212
95
|
|
|
213
96
|
The validation package also exports the underlying transformation functions for manual use:
|
|
@@ -410,45 +293,50 @@ await notificationService.send(ChannelType.MESSENGER, {
|
|
|
410
293
|
|
|
411
294
|
## Deep Dive: `@bts-soft/upload`
|
|
412
295
|
|
|
413
|
-
The upload module is a production-hardened media orchestration service
|
|
296
|
+
The upload module is a production-hardened media orchestration service designed to handle the complexities of multi-part streams, file validation, and cross-provider storage management.
|
|
414
297
|
|
|
415
|
-
### Architecture
|
|
298
|
+
### Multi-Provider Architecture
|
|
416
299
|
|
|
417
|
-
The service
|
|
300
|
+
The service leverages the **Strategy Pattern** to support multiple storage backends without changing the application logic:
|
|
418
301
|
|
|
419
|
-
1. **Strategy
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
2. **Command Pattern**:
|
|
423
|
-
Each upload type (Image, Video, Audio, Raw File) is encapsulated in a command. This allows the system to apply specific optimizations (like chunked video upload) without cluttering the main service.
|
|
302
|
+
1. **Cloudinary Strategy**: Default for production, providing on-the-fly optimization, transcoding, and CDN delivery.
|
|
303
|
+
2. **Local Disk Strategy**: Ideal for development or high-security environments where files must remain on the internal network.
|
|
424
304
|
|
|
425
|
-
|
|
426
|
-
Successful and failed uploads trigger events that `IUploadObserver` instances can listen to. This is used for global logging, analytics, and cleanup tasks.
|
|
305
|
+
Switching providers is handled via the `UPLOAD_PROVIDER` environment variable.
|
|
427
306
|
|
|
428
|
-
|
|
307
|
+
### Design Patterns
|
|
429
308
|
|
|
430
|
-
|
|
309
|
+
The module is built on three pillars of software engineering:
|
|
431
310
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
| **Videos** | `mp4`, `webm`, `avi`, `mov` | 100 MB | Chunked upload (6MB chunks), Duration extraction |
|
|
436
|
-
| **Audio** | `mp3`, `wav`, `ogg`, `m4a` | 50 MB | Treated as a "video" resource for waveform generation |
|
|
437
|
-
| **Raw Files** | `pdf`, `doc`, `zip`, `txt` | 10 MB | Stored as 'raw' resources with original headers |
|
|
311
|
+
- **Strategy Pattern**: The `IUploadStrategy` and `IDeleteStrategy` interfaces decouple the service from the underlying storage technology.
|
|
312
|
+
- **Command Pattern**: Each operation (Upload, Delete) is encapsulated in a command object, ensuring consistent execution and error handling.
|
|
313
|
+
- **Observer Pattern**: Triggers events on success or failure, enabling centralized logging and auditing via `IUploadObserver`.
|
|
438
314
|
|
|
439
|
-
|
|
315
|
+
### Media Specifications & Validation
|
|
440
316
|
|
|
441
|
-
|
|
317
|
+
The system enforces strict validation for file extensions and sizes. Limits can be customized via environment variables.
|
|
442
318
|
|
|
443
|
-
|
|
319
|
+
| Media Type | File Extensions | Default Limit | Storage Logic |
|
|
320
|
+
| :--- | :--- | :--- | :--- |
|
|
321
|
+
| **Images** | `jpg`, `png`, `webp`, `gif` | 5 MB | Auto-optimization and non-destructive resizing. |
|
|
322
|
+
| **Videos** | `mp4`, `webm`, `avi`, `mov` | 100 MB | Chunked upload support with duration extraction. |
|
|
323
|
+
| **Audio** | `mp3`, `wav`, `ogg`, `m4a` | 50 MB | Optimized for playback and metadata extraction. |
|
|
324
|
+
| **Raw Files** | `pdf`, `doc`, `zip`, `txt` | 10 MB | Stored as 'raw' binary with original headers. |
|
|
325
|
+
|
|
326
|
+
### Configuration Reference
|
|
444
327
|
|
|
445
328
|
```env
|
|
329
|
+
# Provider Selection
|
|
330
|
+
UPLOAD_PROVIDER=cloudinary # or 'local'
|
|
331
|
+
|
|
332
|
+
# Cloudinary Credentials (if provider=cloudinary)
|
|
446
333
|
CLOUDINARY_CLOUD_NAME=your_name
|
|
447
334
|
CLOUDINARY_API_KEY=your_key
|
|
448
335
|
CLOUDINARY_API_SECRET=your_secret
|
|
449
|
-
```
|
|
450
336
|
|
|
451
|
-
|
|
337
|
+
# Local Settings (if provider=local)
|
|
338
|
+
UPLOAD_LOCAL_PATH=./uploads
|
|
339
|
+
```
|
|
452
340
|
|
|
453
341
|
---
|
|
454
342
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bts-soft/core",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.6",
|
|
4
4
|
"author": "Omar Sabry",
|
|
5
5
|
"description": "All bts-soft packages - meta-package bundling common, cache, validation, upload, and notifications for NestJS.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"@bts-soft/notifications": "1.4.5",
|
|
18
18
|
"@bts-soft/common": "1.2.8",
|
|
19
19
|
"@bts-soft/cache": "1.0.9",
|
|
20
|
-
"@bts-soft/validation": "1.1.
|
|
21
|
-
"@bts-soft/upload": "1.4.
|
|
20
|
+
"@bts-soft/validation": "1.1.4",
|
|
21
|
+
"@bts-soft/upload": "1.4.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"@nestjs/common": ">=11.0.0",
|