@nest-extended/core 0.0.2-beta-14 → 0.0.2-beta-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 +105 -6
- package/package.json +2 -1
- package/src/lib/nest-extended.module.d.ts +7 -2
- package/src/lib/nest-extended.module.js +25 -1
- package/src/lib/nest-extended.module.js.map +1 -1
- package/src/types/nest-extended.config.d.ts +15 -0
- package/src/types/nest-extended.config.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,74 @@
|
|
|
1
1
|
# @nest-extended/core
|
|
2
2
|
|
|
3
|
-
This package provides the core building blocks for NestJS applications built with the **NestExtended** ecosystem. It includes generic controllers,
|
|
3
|
+
This package provides the core building blocks for NestJS applications built with the **NestExtended** ecosystem. It includes generic controllers, a dynamic configuration module, interceptors, CLS helpers, and type interfaces designed to work seamlessly with `@nest-extended/mongoose`.
|
|
4
4
|
|
|
5
5
|
## Key Features
|
|
6
6
|
|
|
7
|
-
- **Generic Controller (`NestController`)**: A base controller class that handles common CRUD operations (`find`, `get`, `create`, `patch`, `delete`) by delegating to a service implementing `ServiceOptions`.
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
7
|
+
- **Generic Controller (`NestController`)**: A base controller class that handles common CRUD operations (`find`, `get`, `create`, `patch`, `delete`) by delegating to a service implementing `ServiceOptions`. Auto-wires `@Public()`, `@ModifyBody(setCreatedBy())`, and `@User()` decorators.
|
|
8
|
+
- **Dynamic Module (`NestExtendedModule`)**: A global dynamic module configured via `NestExtendedModule.forRoot(config)` that provides app-wide soft delete configuration and automatic `qs` query parser setup. Injects `NEST_EXTENDED_CONFIG` token.
|
|
9
|
+
- **CLS Helpers**: Utilities for `nestjs-cls` (Continuation Local Storage):
|
|
10
|
+
- `getCurrentUser<T>()` — retrieve the authenticated user from CLS context (set by AuthGuard).
|
|
11
|
+
- `CLS_KEYS.USER` — constant for the CLS user key.
|
|
12
|
+
- **Interceptors**:
|
|
13
|
+
- `NullResponseInterceptor` — throws `NotFoundException` on `null`/`undefined` GET responses.
|
|
14
|
+
- **Configuration Types**:
|
|
15
|
+
- `NestExtendedConfig` — root config with `softDelete` and `queryParser` settings.
|
|
16
|
+
- `SoftDeleteConfig` — `getQuery()` and `getData(user)` for soft delete behavior.
|
|
17
|
+
- `QueryParserConfig` — `depth`, `arrayLimit`, `allowDots` for `qs` query parser.
|
|
18
|
+
- `NEST_EXTENDED_CONFIG` — injection token (`Symbol`).
|
|
19
|
+
- **Type Interfaces**:
|
|
20
|
+
- `ServiceOptions<T>` — interface for `_find`, `_get`, `_create`, `_patch`, `_remove`.
|
|
21
|
+
- `NestServiceOptions` — options for `multi`, `softDelete`, `pagination`.
|
|
22
|
+
- `PaginatedResponse<D>` — typed response with `total`, `$limit`, `$skip`, `data`.
|
|
23
|
+
- `RequestBody` — re-export from `@nest-extended/decorators`.
|
|
24
|
+
- **Default Options**: Configurable defaults for `deleteKey` (`'deleted'`), `defaultPagination` (`true`), `defaultLimit` (`20`), `defaultSkip` (`0`), `multi` (`false`).
|
|
25
|
+
- **Constants**: `WeekDays` enum and `EachSlotDurationInMinutes` (30).
|
|
26
|
+
- **Decorators**: Moved to `@nest-extended/decorators` — use `@User()`, `@Public()`, `@ModifyBody()`, `setCreatedBy()`.
|
|
12
27
|
|
|
13
28
|
## Usage
|
|
14
29
|
|
|
30
|
+
### NestExtendedModule
|
|
31
|
+
|
|
32
|
+
Configure soft delete behavior and query parser globally:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { NestExtendedModule } from '@nest-extended/core';
|
|
36
|
+
|
|
37
|
+
@Module({
|
|
38
|
+
imports: [
|
|
39
|
+
NestExtendedModule.forRoot({
|
|
40
|
+
softDelete: {
|
|
41
|
+
getQuery: () => ({ deleted: { $ne: true } }),
|
|
42
|
+
getData: (user) => ({
|
|
43
|
+
deleted: true,
|
|
44
|
+
deletedBy: user?._id,
|
|
45
|
+
deletedAt: new Date(),
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
// Query parser is enabled by default with qs (depth: 20, arrayLimit: 100)
|
|
49
|
+
// Customize or disable:
|
|
50
|
+
// queryParser: { depth: 10, arrayLimit: 50, allowDots: true },
|
|
51
|
+
// queryParser: false, // disable qs, use Express default
|
|
52
|
+
}),
|
|
53
|
+
],
|
|
54
|
+
})
|
|
55
|
+
export class AppModule {}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Query Parser
|
|
59
|
+
|
|
60
|
+
The module automatically configures `qs` as the Express query parser on application bootstrap. This enables proper parsing of deeply nested query objects and arrays (required by `@nest-extended/mongoose` query features like `$populate`, `$sort`, etc.).
|
|
61
|
+
|
|
62
|
+
| Option | Type | Default | Description |
|
|
63
|
+
|---|---|---|---|
|
|
64
|
+
| `depth` | `number` | `20` | Maximum nesting depth for query objects |
|
|
65
|
+
| `arrayLimit` | `number` | `100` | Maximum number of array elements |
|
|
66
|
+
| `allowDots` | `boolean` | `false` | Allow dot notation in query keys |
|
|
67
|
+
|
|
68
|
+
- **Enabled by default**: No configuration needed — just use `NestExtendedModule.forRoot()`.
|
|
69
|
+
- **Custom options**: Pass a `QueryParserConfig` object to `queryParser`.
|
|
70
|
+
- **Disable**: Set `queryParser: false` to use Express's default query parser.
|
|
71
|
+
|
|
15
72
|
### NestController
|
|
16
73
|
|
|
17
74
|
Extend `NestController` to automatically expose standard CRUD endpoints.
|
|
@@ -28,6 +85,29 @@ export class MyController extends NestController<MyResource> {
|
|
|
28
85
|
}
|
|
29
86
|
```
|
|
30
87
|
|
|
88
|
+
### NullResponseInterceptor
|
|
89
|
+
|
|
90
|
+
Register globally to auto-throw 404 on null GET responses:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { NullResponseInterceptor } from '@nest-extended/core';
|
|
94
|
+
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
95
|
+
|
|
96
|
+
providers: [
|
|
97
|
+
{ provide: APP_INTERCEPTOR, useClass: NullResponseInterceptor },
|
|
98
|
+
]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### CLS Helper
|
|
102
|
+
|
|
103
|
+
Retrieve the authenticated user from CLS context (useful in services):
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { getCurrentUser } from '@nest-extended/core';
|
|
107
|
+
|
|
108
|
+
const user = getCurrentUser();
|
|
109
|
+
```
|
|
110
|
+
|
|
31
111
|
### Decorators
|
|
32
112
|
|
|
33
113
|
Decorators have been moved to their own package.
|
|
@@ -35,3 +115,22 @@ Decorators have been moved to their own package.
|
|
|
35
115
|
```typescript
|
|
36
116
|
import { User, Public, ModifyBody, setCreatedBy } from '@nest-extended/decorators';
|
|
37
117
|
```
|
|
118
|
+
|
|
119
|
+
## Exported API
|
|
120
|
+
|
|
121
|
+
| Export | Type | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `NestController` | Class | Generic CRUD controller base class |
|
|
124
|
+
| `NestExtendedModule` | Module | Dynamic config module (`.forRoot()`) |
|
|
125
|
+
| `options` | Object | Default options (deleteKey, pagination, limits) |
|
|
126
|
+
| `getCurrentUser` | Function | Get user from CLS context |
|
|
127
|
+
| `CLS_KEYS` | Const | CLS key constants |
|
|
128
|
+
| `NullResponseInterceptor` | Interceptor | 404 on null GET responses |
|
|
129
|
+
| `NestExtendedConfig` | Interface | Root configuration type |
|
|
130
|
+
| `SoftDeleteConfig` | Interface | Soft delete config type |
|
|
131
|
+
| `QueryParserConfig` | Interface | Query parser options (depth, arrayLimit, allowDots) |
|
|
132
|
+
| `NEST_EXTENDED_CONFIG` | Symbol | DI injection token |
|
|
133
|
+
| `ServiceOptions<T>` | Interface | Service method contract |
|
|
134
|
+
| `NestServiceOptions` | Type | Service behavior options |
|
|
135
|
+
| `PaginatedResponse<D>` | Interface | Paginated response type |
|
|
136
|
+
| `RequestBody` | Type | Re-exported typed request body |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nest-extended/core",
|
|
3
|
-
"version": "0.0.2-beta-
|
|
3
|
+
"version": "0.0.2-beta-15",
|
|
4
4
|
"private": false,
|
|
5
5
|
"contributors": [
|
|
6
6
|
{
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"main": "./src/index.js",
|
|
19
19
|
"types": "./src/index.d.ts",
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"qs": "^6.13.0",
|
|
21
22
|
"tslib": "^2.3.0"
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { DynamicModule } from '@nestjs/common';
|
|
1
|
+
import { DynamicModule, OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapterHost } from '@nestjs/core';
|
|
2
3
|
import { NestExtendedConfig } from '../types/nest-extended.config';
|
|
3
|
-
export declare class NestExtendedModule {
|
|
4
|
+
export declare class NestExtendedModule implements OnApplicationBootstrap {
|
|
5
|
+
private readonly config;
|
|
6
|
+
private readonly httpAdapterHost;
|
|
7
|
+
constructor(config: NestExtendedConfig, httpAdapterHost: HttpAdapterHost);
|
|
8
|
+
onApplicationBootstrap(): void;
|
|
4
9
|
static forRoot(config?: NestExtendedConfig): DynamicModule;
|
|
5
10
|
}
|
|
@@ -4,8 +4,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.NestExtendedModule = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const common_1 = require("@nestjs/common");
|
|
7
|
+
const core_1 = require("@nestjs/core");
|
|
7
8
|
const nest_extended_config_1 = require("../types/nest-extended.config");
|
|
9
|
+
const qs = require("qs");
|
|
8
10
|
let NestExtendedModule = NestExtendedModule_1 = class NestExtendedModule {
|
|
11
|
+
constructor(config, httpAdapterHost) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.httpAdapterHost = httpAdapterHost;
|
|
14
|
+
}
|
|
15
|
+
onApplicationBootstrap() {
|
|
16
|
+
var _a, _b, _c, _d;
|
|
17
|
+
const queryParserConfig = this.config.queryParser;
|
|
18
|
+
if (queryParserConfig === false)
|
|
19
|
+
return;
|
|
20
|
+
// Apply qs query parser to the Express app
|
|
21
|
+
const httpAdapter = (_a = this.httpAdapterHost) === null || _a === void 0 ? void 0 : _a.httpAdapter;
|
|
22
|
+
if (httpAdapter) {
|
|
23
|
+
const app = httpAdapter.getInstance();
|
|
24
|
+
const options = typeof queryParserConfig === 'object' ? queryParserConfig : {};
|
|
25
|
+
const depth = (_b = options.depth) !== null && _b !== void 0 ? _b : 20;
|
|
26
|
+
const arrayLimit = (_c = options.arrayLimit) !== null && _c !== void 0 ? _c : 100;
|
|
27
|
+
const allowDots = (_d = options.allowDots) !== null && _d !== void 0 ? _d : false;
|
|
28
|
+
app.set('query parser', (str) => qs.parse(str, { depth, arrayLimit, allowDots }));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
9
31
|
static forRoot(config = {}) {
|
|
10
32
|
return {
|
|
11
33
|
module: NestExtendedModule_1,
|
|
@@ -22,6 +44,8 @@ let NestExtendedModule = NestExtendedModule_1 = class NestExtendedModule {
|
|
|
22
44
|
};
|
|
23
45
|
exports.NestExtendedModule = NestExtendedModule;
|
|
24
46
|
exports.NestExtendedModule = NestExtendedModule = NestExtendedModule_1 = tslib_1.__decorate([
|
|
25
|
-
(0, common_1.Module)({})
|
|
47
|
+
(0, common_1.Module)({}),
|
|
48
|
+
tslib_1.__param(0, (0, common_1.Inject)(nest_extended_config_1.NEST_EXTENDED_CONFIG)),
|
|
49
|
+
tslib_1.__metadata("design:paramtypes", [Object, core_1.HttpAdapterHost])
|
|
26
50
|
], NestExtendedModule);
|
|
27
51
|
//# sourceMappingURL=nest-extended.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest-extended.module.js","sourceRoot":"","sources":["../../../../../packages/core/src/lib/nest-extended.module.ts"],"names":[],"mappings":";;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"nest-extended.module.js","sourceRoot":"","sources":["../../../../../packages/core/src/lib/nest-extended.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAAuF;AACvF,uCAA+C;AAC/C,wEAAyF;AACzF,yBAAyB;AAGlB,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IAC3B,YACmD,MAA0B,EACxD,eAAgC;QADF,WAAM,GAAN,MAAM,CAAoB;QACxD,oBAAe,GAAf,eAAe,CAAiB;IAClD,CAAC;IAEJ,sBAAsB;;QAClB,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAClD,IAAI,iBAAiB,KAAK,KAAK;YAAE,OAAO;QAExC,2CAA2C;QAC3C,MAAM,WAAW,GAAG,MAAA,IAAI,CAAC,eAAe,0CAAE,WAAW,CAAC;QACtD,IAAI,WAAW,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,OAAO,iBAAiB,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,EAAE,CAAC;YAClC,MAAM,UAAU,GAAG,MAAA,OAAO,CAAC,UAAU,mCAAI,GAAG,CAAC;YAC7C,MAAM,SAAS,GAAG,MAAA,OAAO,CAAC,SAAS,mCAAI,KAAK,CAAC;YAE7C,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,GAAW,EAAE,EAAE,CACpC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAClD,CAAC;QACN,CAAC;IACL,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,SAA6B,EAAE;QAC1C,OAAO;YACH,MAAM,EAAE,oBAAkB;YAC1B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACP;oBACI,OAAO,EAAE,2CAAoB;oBAC7B,QAAQ,EAAE,MAAM;iBACnB;aACJ;YACD,OAAO,EAAE,CAAC,2CAAoB,CAAC;SAClC,CAAC;IACN,CAAC;CACJ,CAAA;AAtCY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,eAAM,EAAC,EAAE,CAAC;IAGF,mBAAA,IAAA,eAAM,EAAC,2CAAoB,CAAC,CAAA;qDACK,sBAAe;GAH5C,kBAAkB,CAsC9B"}
|
|
@@ -16,12 +16,27 @@ export interface SoftDeleteConfig {
|
|
|
16
16
|
*/
|
|
17
17
|
getData: (user: any) => Record<string, any>;
|
|
18
18
|
}
|
|
19
|
+
export interface QueryParserConfig {
|
|
20
|
+
/** Maximum depth for nested objects. Default: 20 */
|
|
21
|
+
depth?: number;
|
|
22
|
+
/** Maximum number of array elements. Default: 100 */
|
|
23
|
+
arrayLimit?: number;
|
|
24
|
+
/** Allow dot notation in query keys. Default: false */
|
|
25
|
+
allowDots?: boolean;
|
|
26
|
+
}
|
|
19
27
|
export interface NestExtendedConfig {
|
|
20
28
|
/**
|
|
21
29
|
* Soft delete configuration.
|
|
22
30
|
* If not provided, default soft delete behavior is used.
|
|
23
31
|
*/
|
|
24
32
|
softDelete?: SoftDeleteConfig;
|
|
33
|
+
/**
|
|
34
|
+
* Query parser configuration using `qs`.
|
|
35
|
+
* - `true` or `undefined` (default): enables qs with defaults (depth: 20, arrayLimit: 100, allowDots: false)
|
|
36
|
+
* - `QueryParserConfig` object: enables qs with custom options
|
|
37
|
+
* - `false`: disables the qs query parser (uses Express default)
|
|
38
|
+
*/
|
|
39
|
+
queryParser?: QueryParserConfig | boolean;
|
|
25
40
|
}
|
|
26
41
|
/**
|
|
27
42
|
* Injection token for NestExtended configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest-extended.config.js","sourceRoot":"","sources":["../../../../../packages/core/src/types/nest-extended.config.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"nest-extended.config.js","sourceRoot":"","sources":["../../../../../packages/core/src/types/nest-extended.config.ts"],"names":[],"mappings":";;;AA6CA;;;GAGG;AACU,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC"}
|