@nest-yalc-2/field-middleware 2.2.12 → 2.2.15
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 +155 -15
- package/package.json +22 -22
package/README.md
CHANGED
|
@@ -6,13 +6,6 @@
|
|
|
6
6
|
[](https://github.com/AI-Autistic-Intelligence)
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
|
-
## 📖 Overview
|
|
10
|
-
|
|
11
|
-
**@nest-yalc-2/field-middleware** is a core enterprise module of the [Ferrox Ecosystem](https://ferrox-rust.dev).
|
|
12
|
-
Core enterprise module for the @nest-yalc-2/field-middleware integration within the Ferrox/YALC ecosystem.
|
|
13
|
-
|
|
14
|
-
> ⚠️ **Note:** This package is a foundational component of the enterprise Ferrox/YALC microservice architecture. For comprehensive documentation, architecture patterns (including the 7-Layer Architecture), and ecosystem comparisons across Node, Rust, Python, and PHP, please visit the [Official Documentation Portal](https://ferrox-rust.dev).
|
|
15
|
-
|
|
16
9
|
## 🚀 Installation
|
|
17
10
|
|
|
18
11
|
```bash
|
|
@@ -23,18 +16,165 @@ yarn add @nest-yalc-2/field-middleware
|
|
|
23
16
|
pnpm add @nest-yalc-2/field-middleware
|
|
24
17
|
```
|
|
25
18
|
|
|
26
|
-
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# GraphQL Field Middleware & Dynamic Property Transformers
|
|
22
|
+
|
|
23
|
+
The `@nestjs-yalc/field-middleware` package provides fine-grained property-level access control, dynamic field encryption, value maskers, and runtime formatting transformers for GraphQL schemas and REST DTO entities.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. What It Is & Architectural Purpose
|
|
28
|
+
|
|
29
|
+
In GraphQL APIs and REST services, security and privacy requirements frequently demand hiding or transforming specific entity fields based on user permissions or compliance mandates (e.g., masking credit card numbers, masking email addresses for non-admins, decrypting PII data on read, or applying localized currency formatting).
|
|
30
|
+
|
|
31
|
+
`@nestjs-yalc/field-middleware` injects field middleware hooks into the NestJS execution context. It allows developers to attach declarative decorators (`@FieldMiddleware(...)`, `@MaskField()`, `@EncryptField()`) directly to GraphQL ObjectType fields or class DTO properties without polluting business domain services with inline security checks.
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
┌────────────────────────────────────────────────────────────────────────┐
|
|
35
|
+
│ GraphQL Query / DTO │
|
|
36
|
+
├────────────────────────────────────────────────────────────────────────┤
|
|
37
|
+
│ 1. Incoming Request Context (User Role: 'GUEST') │
|
|
38
|
+
│ 2. Resolving Field: 'user.email' │
|
|
39
|
+
└──────────────────────────────────┬─────────────────────────────────────┘
|
|
40
|
+
│
|
|
41
|
+
▼
|
|
42
|
+
┌────────────────────────────────────────────────────────────────────────┐
|
|
43
|
+
│ YalcFieldMiddleware Engine │
|
|
44
|
+
├────────────────────────────────────────────────────────────────────────┤
|
|
45
|
+
│ Evaluate Field Decorators (@MaskField({ type: 'EMAIL' })) │
|
|
46
|
+
│ User is GUEST -> Transform 'john.doe@example.com' │
|
|
47
|
+
│ -> Result: 'j***e@example.com' │
|
|
48
|
+
└──────────────────────────────────┬─────────────────────────────────────┘
|
|
49
|
+
│
|
|
50
|
+
▼
|
|
51
|
+
┌────────────────────────────────────────────────────────────────────────┐
|
|
52
|
+
│ Masked GraphQL / JSON Output │
|
|
53
|
+
└────────────────────────────────────────────────────────────────────────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 2. What It Does & Key Capabilities
|
|
59
|
+
|
|
60
|
+
- **Declarative Field Protection**: Attach middleware rules to fields using NestJS decorators.
|
|
61
|
+
- **Role-Based Property Masking**: Dynamically mask Sensitive Data (PII, SSN, Credit Cards) depending on the requestor's JWT roles/permissions.
|
|
62
|
+
- **Property-Level Encryption**: Transparently decrypt AES-256 encrypted database columns during GraphQL object resolution.
|
|
63
|
+
- **Computed Value Formatting**: Apply localized date, currency, or string case transformations dynamically on read operations.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 3. How It Works Under the Hood
|
|
68
|
+
|
|
69
|
+
### Execution Flow Sequence
|
|
70
|
+
|
|
71
|
+
```mermaid
|
|
72
|
+
sequenceDiagram
|
|
73
|
+
autonumber
|
|
74
|
+
participant Client as GraphQL Client
|
|
75
|
+
participant Resolver as Field Resolver
|
|
76
|
+
participant Middleware as FieldMiddleware Pipeline
|
|
77
|
+
participant Security as Auth Context Guard
|
|
78
|
+
participant Output as Transformed Value
|
|
79
|
+
|
|
80
|
+
Client->>Resolver: Query User { id, email, ssn }
|
|
81
|
+
Resolver->>Middleware: Resolve 'ssn' Field Value
|
|
82
|
+
Middleware->>Security: Inspect Request Context (User Roles)
|
|
83
|
+
alt User Has 'ADMIN' Role
|
|
84
|
+
Security-->>Middleware: Authorized
|
|
85
|
+
Middleware-->>Output: Return Unmasked SSN ("123-45-6789")
|
|
86
|
+
else User Has 'USER' / 'GUEST' Role
|
|
87
|
+
Security-->>Middleware: Unauthorized for Raw Value
|
|
88
|
+
Middleware->>Middleware: Apply SSN Mask ("***-**-6789")
|
|
89
|
+
Middleware-->>Output: Return Masked Value
|
|
90
|
+
end
|
|
91
|
+
Output-->>Client: Deliver GraphQL JSON Payload
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 4. Why It Was Designed This Way
|
|
27
97
|
|
|
28
|
-
|
|
98
|
+
| Feature | Standard Manual Field Checks | @nestjs-yalc/field-middleware |
|
|
99
|
+
| :--- | :--- | :--- |
|
|
100
|
+
| **Separation of Concerns** | Controllers/Services littered with `if (role === 'GUEST') mask()` logic. | Zero business service clutter; declarative `@Field()` decorators. |
|
|
101
|
+
| **GraphQL Parity** | Requires writing custom GraphQL field directives by hand. | Native NestJS field middleware integration with standard context. |
|
|
102
|
+
| **Consistency** | Risk of forgetting field masks in newly created API routes. | Centralized middleware pipeline guarantees compliance rules. |
|
|
29
103
|
|
|
30
|
-
|
|
104
|
+
---
|
|
31
105
|
|
|
32
|
-
|
|
106
|
+
## 5. Practical Usage Guide & Extended Code Examples
|
|
33
107
|
|
|
34
|
-
|
|
108
|
+
### 5.1 Masking Sensitive PII Fields in GraphQL
|
|
35
109
|
|
|
36
|
-
|
|
110
|
+
```typescript
|
|
111
|
+
import { Field, ObjectType } from '@nestjs/graphql';
|
|
112
|
+
import { MaskField, FieldMiddleware } from '@nestjs-yalc/field-middleware';
|
|
113
|
+
|
|
114
|
+
@ObjectType()
|
|
115
|
+
export class UserProfileType {
|
|
116
|
+
@Field()
|
|
117
|
+
id: string;
|
|
118
|
+
|
|
119
|
+
@Field()
|
|
120
|
+
@MaskField({ type: 'EMAIL', allowedRoles: ['ADMIN', 'SUPERUSER'] })
|
|
121
|
+
email: string;
|
|
122
|
+
|
|
123
|
+
@Field()
|
|
124
|
+
@MaskField({ type: 'SSN', allowedRoles: ['COMPLIANCE_OFFICER'] })
|
|
125
|
+
ssn: string;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 5.2 Creating Custom Field Middleware Transformers
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { FieldMiddleware, MiddlewareContext, NextFn } from '@nestjs-yalc/field-middleware';
|
|
133
|
+
|
|
134
|
+
export const CurrencyFormatterMiddleware: FieldMiddleware = async (
|
|
135
|
+
ctx: MiddlewareContext,
|
|
136
|
+
next: NextFn,
|
|
137
|
+
) => {
|
|
138
|
+
const value = await next();
|
|
139
|
+
if (typeof value !== 'number') return value;
|
|
140
|
+
|
|
141
|
+
const userLocale = ctx.context.req?.headers['accept-language'] || 'en-US';
|
|
142
|
+
return new Intl.NumberFormat(userLocale, { style: 'currency', currency: 'USD' }).format(value);
|
|
143
|
+
};
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 6. Anti-Patterns: How NOT to Use It
|
|
149
|
+
|
|
150
|
+
> [!CAUTION]
|
|
151
|
+
> **Anti-Pattern 1: Performing Heavy Async I/O in Field Middleware**
|
|
152
|
+
> Field middleware runs for *every resolved property instance* in a GraphQL query array. Executing database queries inside field middleware causes N+1 performance bottlenecks. Use DataLoaders for async field enrichment.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 7. Pro-Tips & Best Practices
|
|
157
|
+
|
|
158
|
+
> [!TIP]
|
|
159
|
+
> **Pro-Tip 1: Combining with NestJS Guards**
|
|
160
|
+
> Use Field Middleware for property-level transformation while keeping NestJS Guards responsible for overall endpoint routing access.
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 🔗 Cross-References
|
|
166
|
+
|
|
167
|
+
To see how this module integrates with the rest of the Ferrox architecture, refer to the following documentation:
|
|
168
|
+
|
|
169
|
+
- [Authentication & Auth](https://ferrox-rust.dev/docs/nestjs-yalc/node-yalc/docs/security/auth)
|
|
170
|
+
- [Database & TypeORM](https://ferrox-rust.dev/docs/nestjs-yalc/databases/database)
|
|
171
|
+
- [GraphQL Transport Module](https://ferrox-rust.dev/docs/nestjs-yalc/transports/graphql)
|
|
172
|
+
- [Sentinel Security Guards](https://ferrox-rust.dev/docs/nestjs-yalc/security/sentinel)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
## 📚 Ecosystem Documentation
|
|
37
177
|
|
|
38
|
-
|
|
178
|
+
This module is a core component of the Ferrox enterprise microservice architecture.
|
|
39
179
|
|
|
40
|
-
|
|
180
|
+
👉 **[Read the Full Documentation on Ferrox-Rust.dev](https://ferrox-rust.dev/docs/nestjs-yalc/abstractions/field-middleware)**
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
2
|
+
"name": "@nest-yalc-2/field-middleware",
|
|
3
|
+
"version": "2.2.15",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/src/index.js",
|
|
8
|
+
"./*": "./dist/src/*"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"author": "Autistic_Intelligence",
|
|
14
|
+
"license": "AGPL-3.0-or-later",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"nestjs",
|
|
17
|
+
"nestjs-yalc",
|
|
18
|
+
"yalc",
|
|
19
|
+
"field-middleware",
|
|
20
|
+
"framework",
|
|
21
|
+
"utility"
|
|
22
|
+
]
|
|
23
|
+
}
|