mongodb-dynamic-api 1.2.0-beta.6 → 1.2.0
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/CHANGELOG.md +6 -0
- package/README.md +123 -5
- package/package.json +8 -4
- package/src/builders/route-decorators.builder.js +5 -1
- package/src/dynamic-api.module.d.ts +1 -1
- package/src/dynamic-api.module.js +37 -12
- package/src/helpers/config.helper.d.ts +61 -0
- package/src/helpers/config.helper.js +95 -0
- package/src/helpers/index.d.ts +1 -1
- package/src/helpers/index.js +1 -1
- package/src/interfaces/dynamic-api-options.interface.d.ts +5 -4
- package/src/interfaces/route-config.interface.d.ts +2 -1
- package/src/mixins/entity-presenter.mixin.d.ts +2 -33
- package/src/mixins/entity-presenter.mixin.js +3 -2
- package/src/modules/create-many/create-many-controller.interface.d.ts +3 -1
- package/src/modules/create-many/create-many-controller.mixin.js +8 -2
- package/src/modules/create-many/create-many.helper.d.ts +2 -2
- package/src/modules/create-many/create-many.helper.js +2 -6
- package/src/modules/create-many/create-many.module.d.ts +2 -2
- package/src/modules/create-many/create-many.module.js +2 -2
- package/src/modules/create-one/create-one-controller.mixin.js +1 -1
- package/src/modules/create-one/create-one.helper.d.ts +2 -2
- package/src/modules/create-one/create-one.helper.js +2 -6
- package/src/modules/create-one/create-one.module.d.ts +2 -2
- package/src/modules/create-one/create-one.module.js +2 -2
- package/src/modules/delete-one/delete-one.helper.d.ts +2 -2
- package/src/modules/delete-one/delete-one.helper.js +2 -6
- package/src/modules/delete-one/delete-one.module.d.ts +2 -2
- package/src/modules/delete-one/delete-one.module.js +2 -2
- package/src/modules/duplicate-one/base-duplicate-one.service.d.ts +1 -1
- package/src/modules/duplicate-one/duplicate-one-controller.interface.d.ts +1 -1
- package/src/modules/duplicate-one/duplicate-one-controller.mixin.js +1 -1
- package/src/modules/duplicate-one/duplicate-one-service.interface.d.ts +1 -1
- package/src/modules/duplicate-one/duplicate-one.helper.d.ts +2 -2
- package/src/modules/duplicate-one/duplicate-one.helper.js +2 -6
- package/src/modules/duplicate-one/duplicate-one.module.d.ts +2 -2
- package/src/modules/duplicate-one/duplicate-one.module.js +2 -2
- package/src/modules/get-many/get-many.helper.d.ts +2 -2
- package/src/modules/get-many/get-many.helper.js +2 -6
- package/src/modules/get-many/get-many.module.d.ts +2 -2
- package/src/modules/get-many/get-many.module.js +2 -2
- package/src/modules/get-one/get-one.helper.d.ts +2 -2
- package/src/modules/get-one/get-one.helper.js +2 -6
- package/src/modules/get-one/get-one.module.d.ts +2 -2
- package/src/modules/get-one/get-one.module.js +2 -2
- package/src/modules/replace-one/replace-one-controller.mixin.js +1 -1
- package/src/modules/replace-one/replace-one.helper.d.ts +2 -2
- package/src/modules/replace-one/replace-one.helper.js +2 -6
- package/src/modules/replace-one/replace-one.module.d.ts +2 -2
- package/src/modules/replace-one/replace-one.module.js +2 -2
- package/src/modules/update-one/update-one-controller.mixin.js +1 -1
- package/src/modules/update-one/update-one.helper.d.ts +2 -2
- package/src/modules/update-one/update-one.helper.js +2 -6
- package/src/modules/update-one/update-one.module.d.ts +2 -2
- package/src/modules/update-one/update-one.module.js +2 -2
- package/src/version.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/helpers/swagger.helper.d.ts +0 -12
- package/src/helpers/swagger.helper.js +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/1.2.0-beta.8...1.2.0) (2024-03-02)
|
|
4
|
+
|
|
5
|
+
## [1.2.0-beta.8](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/release...1.2.0-beta.8) (2024-03-02)
|
|
6
|
+
|
|
7
|
+
## [1.2.0-beta.7](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/prerelease...1.2.0-beta.7) (2024-03-02)
|
|
8
|
+
|
|
3
9
|
## [1.2.0-beta.6](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/prerelease...1.2.0-beta.6) (2024-03-01)
|
|
4
10
|
|
|
5
11
|
## [1.2.0-beta.5](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/prerelease...1.2.0-beta.5) (2024-03-01)
|
package/README.md
CHANGED
|
@@ -56,17 +56,135 @@
|
|
|
56
56
|
|
|
57
57
|
<p style="text-align: justify; width: 100%;font-size: 15px;">
|
|
58
58
|
|
|
59
|
-
**mongodb-dynamic-api** is an auto generated CRUD API for MongoDB using NestJS.
|
|
59
|
+
**mongodb-dynamic-api** is an auto generated CRUD API for MongoDB using NestJS 10.
|
|
60
60
|
|
|
61
61
|
</p>
|
|
62
62
|
|
|
63
63
|
---
|
|
64
64
|
|
|
65
65
|
## npm package <img src="https://pbs.twimg.com/media/EDoWJbUXYAArclg.png" width="24" height="24" />
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
```text
|
|
67
|
+
npm install --save mongodb-dynamic-api
|
|
68
|
+
```
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
---
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
### HOW TO ENJOY IT
|
|
73
|
+
|
|
74
|
+
- Start a new [nest](https://docs.nestjs.com/) project with **typescript** (use the `--strict` option)
|
|
75
|
+
```text
|
|
76
|
+
nest new --strict your-project-name
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- Go to your project root and install the [mongodb-dynamic-api](https://www.npmjs.com/package/mongodb-dynamic-api) package
|
|
80
|
+
```text
|
|
81
|
+
npm i -S mongodb-dynamic-api
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- Add DynamicApiModule to your app.module.ts and pass the MongoDB connection string to the `forRoot` method
|
|
85
|
+
```typescript
|
|
86
|
+
@Module({
|
|
87
|
+
imports: [
|
|
88
|
+
// ...
|
|
89
|
+
DynamicApiModule.forRoot(
|
|
90
|
+
// <- pass the MongoDB connection string here
|
|
91
|
+
),
|
|
92
|
+
// ...
|
|
93
|
+
],
|
|
94
|
+
controllers: [AppController],
|
|
95
|
+
providers: [AppService],
|
|
96
|
+
})
|
|
97
|
+
export class AppModule {}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- Ok, now let's add our first content. This content will be a simple `User` with a `name` and an `email` field.
|
|
101
|
+
```typescript
|
|
102
|
+
// user.ts
|
|
103
|
+
@Schema({ collection: 'users' })
|
|
104
|
+
export class User extends BaseEntity { // <- you must extend BaseEntity
|
|
105
|
+
@Prop({ type: String })
|
|
106
|
+
name: string;
|
|
107
|
+
|
|
108
|
+
@Prop({ type: String })
|
|
109
|
+
email: string;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
```typescript
|
|
113
|
+
// users.module.ts
|
|
114
|
+
@Module({
|
|
115
|
+
imports: [
|
|
116
|
+
DynamicApiModule.forFeature({ // <- use the forFeature method to add the User content
|
|
117
|
+
entity: User,
|
|
118
|
+
controllerOptions: {
|
|
119
|
+
path: 'users',
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
],
|
|
123
|
+
})
|
|
124
|
+
export class UsersModule {}
|
|
125
|
+
```
|
|
126
|
+
```typescript
|
|
127
|
+
// app.module.ts
|
|
128
|
+
@Module({
|
|
129
|
+
imports: [
|
|
130
|
+
// ...
|
|
131
|
+
DynamicApiModule.forRoot('...'),
|
|
132
|
+
UsersModule, // <- add the module to the imports after the DynamicApiModule
|
|
133
|
+
],
|
|
134
|
+
controllers: [AppController],
|
|
135
|
+
providers: [AppService],
|
|
136
|
+
})
|
|
137
|
+
export class AppModule {}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**That's all !** *You now have a fully functional CRUD API for the `User` content at the `/users` path.*
|
|
141
|
+
|
|
142
|
+
___
|
|
143
|
+
### Swagger (optional but recommended)
|
|
144
|
+
```typescript
|
|
145
|
+
async function bootstrap() {
|
|
146
|
+
const app = await NestFactory.create(AppModule);
|
|
147
|
+
// ...
|
|
148
|
+
enableDynamicAPISwagger(app); // <- add this line in your main.ts file
|
|
149
|
+
|
|
150
|
+
await app.listen(3000);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
The `enableDynamicAPISwagger` function will automatically build the swagger documentation.
|
|
154
|
+
This method can be called with optional parameters to specify more documentation options.
|
|
155
|
+
|
|
156
|
+
Do not forget to add the `@ApiProperty` decorator to your entity properties to have a better swagger documentation.
|
|
157
|
+
```typescript
|
|
158
|
+
// user.entity.ts
|
|
159
|
+
@Schema({ collection: 'users' })
|
|
160
|
+
export class UserEntity extends BaseEntity {
|
|
161
|
+
@ApiProperty() // <- add this line
|
|
162
|
+
@Prop({ type: String })
|
|
163
|
+
name: string;
|
|
164
|
+
|
|
165
|
+
@ApiProperty() // <- add this line
|
|
166
|
+
@Prop({ type: String })
|
|
167
|
+
email: string;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
go to the swagger API path (default to `/openapi`) and you will see the auto generated API
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+

|
|
175
|
+
|
|
176
|
+
[more screenshots](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README/swagger.md)
|
|
177
|
+
|
|
178
|
+
___
|
|
179
|
+
### Versioning (optional)
|
|
180
|
+
```typescript
|
|
181
|
+
async function bootstrap() {
|
|
182
|
+
const app = await NestFactory.create(AppModule);
|
|
183
|
+
// ...
|
|
184
|
+
enableDynamicAPIVersioning(app); // <- add this line in your main.ts file
|
|
185
|
+
|
|
186
|
+
await app.listen(3000);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
The `enableDynamicAPIVersioning` function will automatically add versioning to the API. By default it will use the URI versioning type.
|
|
190
|
+
This method can be called with a second optional parameter to specify more options.
|
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongodb-dynamic-api",
|
|
3
|
-
"version": "1.2.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Auto generated CRUD API for MongoDB using NestJS",
|
|
5
|
-
"author": "Mickaël NODANCHE <mikeonline75@gmail.com> (https://cv-mikeonline.web.app)",
|
|
6
|
-
"homepage": "https://mikedev75015.github.io",
|
|
7
|
-
"license": "MIT",
|
|
8
5
|
"readmeFilename": "README.md",
|
|
9
6
|
"main": "index.js",
|
|
10
7
|
"types": "index.d.ts",
|
|
@@ -18,6 +15,7 @@
|
|
|
18
15
|
"test:ci:junit": "jest --ci --runInBand --coverage --testResultsProcessor=jest-junit",
|
|
19
16
|
"test:ci:sonar": "jest --ci --runInBand --coverage --testResultsProcessor=jest-sonar-reporter",
|
|
20
17
|
"pre-release-tag": "git tag -f prerelease && git push -f origin prerelease",
|
|
18
|
+
"release-tag": "git tag -f release && git push -f origin release",
|
|
21
19
|
"prerelease": "release-it --ci --preRelease=beta --no-git.requireUpstream",
|
|
22
20
|
"release": "release-it --ci",
|
|
23
21
|
"publish-prerelease": "npm publish ./dist --tag prerelease",
|
|
@@ -33,6 +31,12 @@
|
|
|
33
31
|
"dynamic-api",
|
|
34
32
|
"crud"
|
|
35
33
|
],
|
|
34
|
+
"author": "Mickaël NODANCHE <mikeonline75@gmail.com> (https://cv-mikeonline.web.app)",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/MikeDev75015/mongodb-dynamic-api/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://mikedev75015.github.io",
|
|
36
40
|
"dependencies": {
|
|
37
41
|
"@nestjs/common": "^10.3.2",
|
|
38
42
|
"@nestjs/core": "^10.3.2",
|
|
@@ -15,6 +15,7 @@ class RouteDecoratorsBuilder {
|
|
|
15
15
|
this.presenter = presenter;
|
|
16
16
|
this.responseRouteTypeIsArray = [
|
|
17
17
|
'GetMany',
|
|
18
|
+
'CreateMany',
|
|
18
19
|
];
|
|
19
20
|
}
|
|
20
21
|
build() {
|
|
@@ -57,7 +58,10 @@ class RouteDecoratorsBuilder {
|
|
|
57
58
|
type: this.presenter ?? this.entity,
|
|
58
59
|
isArray: this.responseRouteTypeIsArray.includes(this.routeType),
|
|
59
60
|
}),
|
|
60
|
-
...(this.body ? [(0, swagger_1.ApiBody)({
|
|
61
|
+
...(this.body ? [(0, swagger_1.ApiBody)({
|
|
62
|
+
type: this.body,
|
|
63
|
+
...(this.routeType === 'DuplicateOne' ? { required: false } : {})
|
|
64
|
+
})] : []),
|
|
61
65
|
...(this.param && paramKey
|
|
62
66
|
? [
|
|
63
67
|
(0, swagger_1.ApiParam)({
|
|
@@ -4,5 +4,5 @@ import { BaseEntity } from './models';
|
|
|
4
4
|
export declare class DynamicApiModule {
|
|
5
5
|
static connectionName: string;
|
|
6
6
|
static forRoot(uri: string): DynamicModule;
|
|
7
|
-
static forFeature<Entity extends BaseEntity>({ entity, controllerOptions: { path, apiTag, version:
|
|
7
|
+
static forFeature<Entity extends BaseEntity>({ entity, controllerOptions: { path, apiTag, version: controllerVersion, validationPipeOptions: controllerValidationPipeOptions, }, routes, }: DynamicApiOptions<Entity>): DynamicModule;
|
|
8
8
|
}
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.DynamicApiModule = void 0;
|
|
11
11
|
const common_1 = require("@nestjs/common");
|
|
12
12
|
const mongoose_1 = require("@nestjs/mongoose");
|
|
13
|
+
const lodash_1 = require("lodash");
|
|
13
14
|
const decorators_1 = require("./decorators");
|
|
14
15
|
const modules_1 = require("./modules");
|
|
15
16
|
let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
|
|
@@ -24,9 +25,10 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
|
|
|
24
25
|
],
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
|
-
static forFeature({ entity, controllerOptions: { path, apiTag, version:
|
|
28
|
-
const { indexes, hooks } = Reflect.getOwnMetadata(decorators_1.DYNAMIC_API_SCHEMA_OPTIONS_METADATA, entity);
|
|
28
|
+
static forFeature({ entity, controllerOptions: { path, apiTag, version: controllerVersion, validationPipeOptions: controllerValidationPipeOptions, }, routes = [], }) {
|
|
29
|
+
const { indexes, hooks } = Reflect.getOwnMetadata(decorators_1.DYNAMIC_API_SCHEMA_OPTIONS_METADATA, entity) ?? {};
|
|
29
30
|
const schema = mongoose_1.SchemaFactory.createForClass(entity);
|
|
31
|
+
schema.set('timestamps', true);
|
|
30
32
|
if (indexes) {
|
|
31
33
|
indexes.forEach(({ fields, options }) => {
|
|
32
34
|
schema.index(fields, options);
|
|
@@ -38,32 +40,55 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
|
|
|
38
40
|
});
|
|
39
41
|
}
|
|
40
42
|
const databaseModule = mongoose_1.MongooseModule.forFeature([{ name: entity.name, schema }], DynamicApiModule_1.connectionName);
|
|
43
|
+
if (!routes.length) {
|
|
44
|
+
const contentName = (0, lodash_1.lowerCase)(entity.name);
|
|
45
|
+
routes = [
|
|
46
|
+
{ type: 'GetMany', description: `Get many ${contentName}` },
|
|
47
|
+
{ type: 'GetOne', description: `Get one ${contentName} by id` },
|
|
48
|
+
{ type: 'CreateMany', description: `Create many ${contentName}` },
|
|
49
|
+
{ type: 'CreateOne', description: `Create one ${contentName}` },
|
|
50
|
+
{ type: 'ReplaceOne', description: `Replace one ${contentName}` },
|
|
51
|
+
{ type: 'UpdateOne', description: `Update one ${contentName}` },
|
|
52
|
+
{ type: 'DuplicateOne', description: `Duplicate one ${contentName}` },
|
|
53
|
+
{ type: 'DeleteOne', description: `Delete one ${contentName}` },
|
|
54
|
+
];
|
|
55
|
+
}
|
|
41
56
|
return {
|
|
42
57
|
module: DynamicApiModule_1,
|
|
43
58
|
imports: [
|
|
44
59
|
...routes
|
|
45
|
-
.map(({ type, description, version: routeVersion, dTOs }) => {
|
|
46
|
-
const version = routeVersion ??
|
|
60
|
+
.map(({ type, description, version: routeVersion, dTOs, validationPipeOptions: routeValidationPipeOptions, }) => {
|
|
61
|
+
const version = routeVersion ?? controllerVersion;
|
|
62
|
+
let module;
|
|
47
63
|
switch (type) {
|
|
48
64
|
case 'CreateMany':
|
|
49
|
-
|
|
65
|
+
module = modules_1.CreateManyModule;
|
|
66
|
+
break;
|
|
50
67
|
case 'CreateOne':
|
|
51
|
-
|
|
68
|
+
module = modules_1.CreateOneModule;
|
|
69
|
+
break;
|
|
52
70
|
case 'DeleteOne':
|
|
53
|
-
|
|
71
|
+
module = modules_1.DeleteOneModule;
|
|
72
|
+
break;
|
|
54
73
|
case 'DuplicateOne':
|
|
55
|
-
|
|
74
|
+
module = modules_1.DuplicateOneModule;
|
|
75
|
+
break;
|
|
56
76
|
case 'GetMany':
|
|
57
|
-
|
|
77
|
+
module = modules_1.GetManyModule;
|
|
78
|
+
break;
|
|
58
79
|
case 'GetOne':
|
|
59
|
-
|
|
80
|
+
module = modules_1.GetOneModule;
|
|
81
|
+
break;
|
|
60
82
|
case 'ReplaceOne':
|
|
61
|
-
|
|
83
|
+
module = modules_1.ReplaceOneModule;
|
|
84
|
+
break;
|
|
62
85
|
case 'UpdateOne':
|
|
63
|
-
|
|
86
|
+
module = modules_1.UpdateOneModule;
|
|
87
|
+
break;
|
|
64
88
|
default:
|
|
65
89
|
throw new Error(`Route for ${type} is not implemented`);
|
|
66
90
|
}
|
|
91
|
+
return module.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs, routeValidationPipeOptions ?? controllerValidationPipeOptions);
|
|
67
92
|
})
|
|
68
93
|
.filter((module) => module),
|
|
69
94
|
],
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { INestApplication, ValidationPipeOptions, VersioningOptions } from '@nestjs/common';
|
|
2
|
+
import { SwaggerDocumentOptions } from '@nestjs/swagger';
|
|
3
|
+
import { ExternalDocumentationObject, ParameterObject, SecuritySchemeObject, ServerVariableObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';
|
|
4
|
+
type DynamicAPISwaggerExtraConfig = {
|
|
5
|
+
termsOfService?: string;
|
|
6
|
+
contact?: {
|
|
7
|
+
name: string;
|
|
8
|
+
url: string;
|
|
9
|
+
email: string;
|
|
10
|
+
};
|
|
11
|
+
license?: {
|
|
12
|
+
name: string;
|
|
13
|
+
url: string;
|
|
14
|
+
};
|
|
15
|
+
servers?: {
|
|
16
|
+
url: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
variables?: Record<string, ServerVariableObject>;
|
|
19
|
+
}[];
|
|
20
|
+
externalDocs?: {
|
|
21
|
+
description: string;
|
|
22
|
+
url: string;
|
|
23
|
+
};
|
|
24
|
+
basePath?: string;
|
|
25
|
+
tags?: {
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
externalDocs?: ExternalDocumentationObject;
|
|
29
|
+
}[];
|
|
30
|
+
extensions?: {
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
};
|
|
33
|
+
security?: {
|
|
34
|
+
[key: string]: SecuritySchemeObject;
|
|
35
|
+
};
|
|
36
|
+
globalParameters?: ParameterObject[];
|
|
37
|
+
securityRequirements?: {
|
|
38
|
+
[key: string]: string[];
|
|
39
|
+
};
|
|
40
|
+
bearerAuth?: SecuritySchemeObject;
|
|
41
|
+
oAuth2?: SecuritySchemeObject;
|
|
42
|
+
apiKey?: SecuritySchemeObject;
|
|
43
|
+
basicAuth?: SecuritySchemeObject;
|
|
44
|
+
cookieAuth?: {
|
|
45
|
+
cookieName: string;
|
|
46
|
+
options: SecuritySchemeObject;
|
|
47
|
+
securityName: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
type DynamicAPISwaggerOptions = {
|
|
51
|
+
title?: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
version?: string;
|
|
54
|
+
path?: string;
|
|
55
|
+
swaggerConfig?: DynamicAPISwaggerExtraConfig;
|
|
56
|
+
swaggerOptions?: SwaggerDocumentOptions;
|
|
57
|
+
};
|
|
58
|
+
declare function enableDynamicAPISwagger(app: INestApplication, options?: DynamicAPISwaggerOptions): void;
|
|
59
|
+
declare function enableDynamicAPIVersioning(app: INestApplication, options?: VersioningOptions): void;
|
|
60
|
+
declare function enableDynamicAPIValidation(app: INestApplication, options?: ValidationPipeOptions): void;
|
|
61
|
+
export { enableDynamicAPISwagger, enableDynamicAPIVersioning, enableDynamicAPIValidation, DynamicAPISwaggerOptions, DynamicAPISwaggerExtraConfig, };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enableDynamicAPIValidation = exports.enableDynamicAPIVersioning = exports.enableDynamicAPISwagger = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
6
|
+
const version_json_1 = require("../version.json");
|
|
7
|
+
function buildExtraConfig(config, swaggerConfig) {
|
|
8
|
+
Object.keys(swaggerConfig).forEach((key) => {
|
|
9
|
+
const value = swaggerConfig[key];
|
|
10
|
+
switch (key) {
|
|
11
|
+
case 'termsOfService':
|
|
12
|
+
config.setTermsOfService(value);
|
|
13
|
+
break;
|
|
14
|
+
case 'contact':
|
|
15
|
+
config.setContact(value.name, value.url, value.email);
|
|
16
|
+
break;
|
|
17
|
+
case 'license':
|
|
18
|
+
config.setLicense(value.name, value.url);
|
|
19
|
+
break;
|
|
20
|
+
case 'servers':
|
|
21
|
+
value.forEach((server) => {
|
|
22
|
+
config.addServer(server.url, server.description, server.variables);
|
|
23
|
+
});
|
|
24
|
+
break;
|
|
25
|
+
case 'externalDocs':
|
|
26
|
+
config.setExternalDoc(value.description, value.url);
|
|
27
|
+
break;
|
|
28
|
+
case 'basePath':
|
|
29
|
+
config.setBasePath(value);
|
|
30
|
+
break;
|
|
31
|
+
case 'tags':
|
|
32
|
+
value.forEach((tag) => {
|
|
33
|
+
config.addTag(tag.name, tag.description, tag.externalDocs);
|
|
34
|
+
});
|
|
35
|
+
break;
|
|
36
|
+
case 'extensions':
|
|
37
|
+
Object.keys(value).forEach((extensionKey) => {
|
|
38
|
+
config.addExtension(extensionKey, value[extensionKey]);
|
|
39
|
+
});
|
|
40
|
+
break;
|
|
41
|
+
case 'security':
|
|
42
|
+
Object.keys(value).forEach((securityKey) => {
|
|
43
|
+
config.addSecurity(securityKey, value[securityKey]);
|
|
44
|
+
});
|
|
45
|
+
break;
|
|
46
|
+
case 'globalParameters':
|
|
47
|
+
config.addGlobalParameters(...value);
|
|
48
|
+
break;
|
|
49
|
+
case 'securityRequirements':
|
|
50
|
+
Object.keys(value).forEach((securityKey) => {
|
|
51
|
+
config.addSecurityRequirements(securityKey, value[securityKey]);
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
case 'bearerAuth':
|
|
55
|
+
config.addBearerAuth(value);
|
|
56
|
+
break;
|
|
57
|
+
case 'oAuth2':
|
|
58
|
+
config.addOAuth2(value);
|
|
59
|
+
break;
|
|
60
|
+
case 'apiKey':
|
|
61
|
+
config.addApiKey(value);
|
|
62
|
+
break;
|
|
63
|
+
case 'basicAuth':
|
|
64
|
+
config.addBasicAuth(value);
|
|
65
|
+
break;
|
|
66
|
+
case 'cookieAuth':
|
|
67
|
+
config.addCookieAuth(value.cookieName, value.options, value.securityName);
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function enableDynamicAPISwagger(app, options = {}) {
|
|
75
|
+
const { title = 'MongoDB Dynamic API', description = 'Auto generated CRUD for MongoDB', version = version_json_1.default?.version?.split('-beta')[0], path = '/openapi', swaggerConfig, swaggerOptions, } = options ?? {};
|
|
76
|
+
const config = new swagger_1.DocumentBuilder()
|
|
77
|
+
.setTitle(title)
|
|
78
|
+
.setDescription(description)
|
|
79
|
+
.setVersion(version);
|
|
80
|
+
buildExtraConfig(config, swaggerConfig ?? {});
|
|
81
|
+
const document = swagger_1.SwaggerModule.createDocument(app, config.build(), swaggerOptions);
|
|
82
|
+
swagger_1.SwaggerModule.setup(path, app, document);
|
|
83
|
+
}
|
|
84
|
+
exports.enableDynamicAPISwagger = enableDynamicAPISwagger;
|
|
85
|
+
function enableDynamicAPIVersioning(app, options) {
|
|
86
|
+
app.enableVersioning({
|
|
87
|
+
type: common_1.VersioningType.URI,
|
|
88
|
+
...options,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
exports.enableDynamicAPIVersioning = enableDynamicAPIVersioning;
|
|
92
|
+
function enableDynamicAPIValidation(app, options = {}) {
|
|
93
|
+
app.useGlobalPipes(new common_1.ValidationPipe(options));
|
|
94
|
+
}
|
|
95
|
+
exports.enableDynamicAPIValidation = enableDynamicAPIValidation;
|
package/src/helpers/index.d.ts
CHANGED
package/src/helpers/index.js
CHANGED
|
@@ -14,5 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./config.helper"), exports);
|
|
17
18
|
__exportStar(require("./route-decorators.helper"), exports);
|
|
18
|
-
__exportStar(require("./swagger.helper"), exports);
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Type } from '@nestjs/common';
|
|
1
|
+
import { Type, ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { BaseEntity } from '../models';
|
|
3
3
|
import { RouteConfig } from './route-config.interface';
|
|
4
4
|
interface ControllerOptions {
|
|
5
5
|
path: string;
|
|
6
6
|
apiTag?: string;
|
|
7
7
|
version?: string;
|
|
8
|
+
validationPipeOptions?: ValidationPipeOptions;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
+
interface DynamicApiOptions<Entity extends BaseEntity> {
|
|
10
11
|
entity: Type<Entity>;
|
|
11
12
|
controllerOptions: ControllerOptions;
|
|
12
|
-
routes
|
|
13
|
+
routes?: RouteConfig<Entity>[];
|
|
13
14
|
}
|
|
14
|
-
export {};
|
|
15
|
+
export { DynamicApiOptions, ControllerOptions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Type } from '@nestjs/common';
|
|
1
|
+
import { Type, ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { BaseEntity } from '../models';
|
|
3
3
|
type RouteType = 'GetMany' | 'GetOne' | 'CreateOne' | 'CreateMany' | 'UpdateOne' | 'ReplaceOne' | 'DeleteOne' | 'DuplicateOne';
|
|
4
4
|
type DTOsBundle = {
|
|
@@ -12,5 +12,6 @@ interface RouteConfig<Entity extends BaseEntity> {
|
|
|
12
12
|
description?: string;
|
|
13
13
|
version?: string;
|
|
14
14
|
dTOs?: DTOsBundle;
|
|
15
|
+
validationPipeOptions?: ValidationPipeOptions;
|
|
15
16
|
}
|
|
16
17
|
export { DTOsBundle, RouteType, RouteConfig };
|
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
/// <reference types="mongoose/types/aggregate" />
|
|
2
|
-
/// <reference types="mongoose/types/callback" />
|
|
3
|
-
/// <reference types="mongoose/types/collection" />
|
|
4
|
-
/// <reference types="mongoose/types/connection" />
|
|
5
|
-
/// <reference types="mongoose/types/cursor" />
|
|
6
|
-
/// <reference types="mongoose/types/document" />
|
|
7
|
-
/// <reference types="mongoose/types/error" />
|
|
8
|
-
/// <reference types="mongoose/types/expressions" />
|
|
9
|
-
/// <reference types="mongoose/types/helpers" />
|
|
10
|
-
/// <reference types="mongoose/types/middlewares" />
|
|
11
|
-
/// <reference types="mongoose/types/indexes" />
|
|
12
|
-
/// <reference types="mongoose/types/models" />
|
|
13
|
-
/// <reference types="mongoose/types/mongooseoptions" />
|
|
14
|
-
/// <reference types="mongoose/types/pipelinestage" />
|
|
15
|
-
/// <reference types="mongoose/types/populate" />
|
|
16
|
-
/// <reference types="mongoose/types/query" />
|
|
17
|
-
/// <reference types="mongoose/types/schemaoptions" />
|
|
18
|
-
/// <reference types="mongoose/types/schematypes" />
|
|
19
|
-
/// <reference types="mongoose/types/session" />
|
|
20
|
-
/// <reference types="mongoose/types/types" />
|
|
21
|
-
/// <reference types="mongoose/types/utility" />
|
|
22
|
-
/// <reference types="mongoose/types/validation" />
|
|
23
|
-
/// <reference types="mongoose/types/virtuals" />
|
|
24
|
-
/// <reference types="mongoose" />
|
|
25
|
-
/// <reference types="mongoose/types/inferschematype" />
|
|
26
1
|
import { Type } from '@nestjs/common';
|
|
27
2
|
import { BaseEntity } from '../models';
|
|
28
|
-
declare function EntityPresenterMixin<Entity extends BaseEntity>(entity: Type<Entity
|
|
29
|
-
new (...args: any[]): {
|
|
30
|
-
_id: import("mongoose").Schema.Types.ObjectId;
|
|
31
|
-
__v: number;
|
|
32
|
-
id: string;
|
|
33
|
-
createdAt: Date;
|
|
34
|
-
updatedAt: Date;
|
|
35
|
-
};
|
|
3
|
+
declare function EntityPresenterMixin<Entity extends BaseEntity>(entity: Type<Entity>, keysToExclude?: (keyof Entity)[]): {
|
|
4
|
+
new (...args: any[]): {};
|
|
36
5
|
apply(this: Function, thisArg: any, argArray?: any): any;
|
|
37
6
|
call(this: Function, thisArg: any, ...argArray: any[]): any;
|
|
38
7
|
bind(this: Function, thisArg: any, ...argArray: any[]): any;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EntityPresenterMixin = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
5
|
+
function EntityPresenterMixin(entity, keysToExclude) {
|
|
6
|
+
class EntityPresenter extends (keysToExclude ? (0, swagger_1.OmitType)(entity, keysToExclude) : entity) {
|
|
6
7
|
}
|
|
7
8
|
return EntityPresenter;
|
|
8
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { BaseEntity } from '../../models';
|
|
2
2
|
import { CreateManyService } from './create-many-service.interface';
|
|
3
3
|
interface CreateManyController<Entity extends BaseEntity> {
|
|
4
|
-
createMany
|
|
4
|
+
createMany(body: {
|
|
5
|
+
list: any;
|
|
6
|
+
}): Promise<Entity[]>;
|
|
5
7
|
}
|
|
6
8
|
type CreateManyControllerConstructor<Entity extends BaseEntity> = new (service: CreateManyService<Entity>) => CreateManyController<Entity>;
|
|
7
9
|
export type { CreateManyController, CreateManyControllerConstructor };
|
|
@@ -16,6 +16,7 @@ exports.CreateManyControllerMixin = void 0;
|
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
18
|
const class_validator_1 = require("class-validator");
|
|
19
|
+
const class_transformer_1 = require("class-transformer");
|
|
19
20
|
const builders_1 = require("../../builders");
|
|
20
21
|
const helpers_1 = require("../../helpers");
|
|
21
22
|
const mixins_1 = require("../../mixins");
|
|
@@ -24,6 +25,10 @@ function CreateManyControllerMixin(entity, path, apiTag, version, description, D
|
|
|
24
25
|
const { body: CustomBody, presenter: CustomPresenter } = DTOs ?? {};
|
|
25
26
|
class DtoBody extends (0, mixins_1.EntityBodyMixin)(entity) {
|
|
26
27
|
}
|
|
28
|
+
Object.defineProperty(DtoBody, 'name', {
|
|
29
|
+
value: `${displayedName}Dto`,
|
|
30
|
+
writable: false,
|
|
31
|
+
});
|
|
27
32
|
class CreateManyBody {
|
|
28
33
|
}
|
|
29
34
|
__decorate([
|
|
@@ -31,13 +36,14 @@ function CreateManyControllerMixin(entity, path, apiTag, version, description, D
|
|
|
31
36
|
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
32
37
|
(0, class_validator_1.IsInstance)(DtoBody, { each: true }),
|
|
33
38
|
(0, class_validator_1.ArrayMinSize)(1),
|
|
39
|
+
(0, class_transformer_1.Type)(() => DtoBody),
|
|
34
40
|
__metadata("design:type", Array)
|
|
35
41
|
], CreateManyBody.prototype, "list", void 0);
|
|
36
|
-
class RouteBody extends (CustomBody ?? CreateManyBody) {
|
|
42
|
+
class RouteBody extends (0, swagger_1.PickType)(CustomBody ?? CreateManyBody, ['list']) {
|
|
37
43
|
}
|
|
38
44
|
if (!CustomBody) {
|
|
39
45
|
Object.defineProperty(RouteBody, 'name', {
|
|
40
|
-
value: `CreateMany${displayedName}
|
|
46
|
+
value: `CreateMany${displayedName}Dto`,
|
|
41
47
|
writable: false,
|
|
42
48
|
});
|
|
43
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Type } from '@nestjs/common';
|
|
1
|
+
import { Type, ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { DTOsBundle, ServiceProvider } from '../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../models';
|
|
4
4
|
import { CreateManyControllerConstructor } from './create-many-controller.interface';
|
|
5
5
|
declare function createCreateManyServiceProvider<Entity extends BaseEntity>(entity: Type<Entity>): ServiceProvider;
|
|
6
|
-
declare function createCreateManyController<Entity extends BaseEntity>(entity: Type<Entity>, path: string, apiTag?: string, version?: string, description?: string, DTOs?: DTOsBundle): CreateManyControllerConstructor<Entity>;
|
|
6
|
+
declare function createCreateManyController<Entity extends BaseEntity>(entity: Type<Entity>, path: string, apiTag?: string, version?: string, description?: string, DTOs?: DTOsBundle, validationPipeOptions?: ValidationPipeOptions): CreateManyControllerConstructor<Entity>;
|
|
7
7
|
export { createCreateManyController, createCreateManyServiceProvider };
|
|
@@ -45,7 +45,7 @@ function createCreateManyServiceProvider(entity) {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
exports.createCreateManyServiceProvider = createCreateManyServiceProvider;
|
|
48
|
-
function createCreateManyController(entity, path, apiTag, version, description, DTOs) {
|
|
48
|
+
function createCreateManyController(entity, path, apiTag, version, description, DTOs, validationPipeOptions) {
|
|
49
49
|
let CreateManyController = class CreateManyController extends (0, create_many_controller_mixin_1.CreateManyControllerMixin)(entity, path, apiTag, version, description, DTOs) {
|
|
50
50
|
constructor(service) {
|
|
51
51
|
super(service);
|
|
@@ -55,11 +55,7 @@ function createCreateManyController(entity, path, apiTag, version, description,
|
|
|
55
55
|
CreateManyController = __decorate([
|
|
56
56
|
(0, common_1.Controller)({ path, version }),
|
|
57
57
|
(0, swagger_1.ApiTags)(apiTag || entity.name),
|
|
58
|
-
(0, common_1.UsePipes)(new common_1.ValidationPipe({
|
|
59
|
-
forbidNonWhitelisted: true,
|
|
60
|
-
transform: true,
|
|
61
|
-
whitelist: true,
|
|
62
|
-
})),
|
|
58
|
+
(0, common_1.UsePipes)(new common_1.ValidationPipe(validationPipeOptions ?? { transform: true })),
|
|
63
59
|
__param(0, (0, common_1.Inject)(provideServiceName(entity.name))),
|
|
64
60
|
__metadata("design:paramtypes", [Object])
|
|
65
61
|
], CreateManyController);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DynamicModule, Type } from '@nestjs/common';
|
|
1
|
+
import { DynamicModule, Type, ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { DTOsBundle } from '../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../models';
|
|
4
4
|
export declare class CreateManyModule {
|
|
5
|
-
static forFeature<Entity extends BaseEntity>(databaseModule: DynamicModule, entity: Type<Entity>, path: string, apiTag?: string, version?: string, description?: string, DTOs?: DTOsBundle): DynamicModule;
|
|
5
|
+
static forFeature<Entity extends BaseEntity>(databaseModule: DynamicModule, entity: Type<Entity>, path: string, apiTag?: string, version?: string, description?: string, DTOs?: DTOsBundle, validationPipeOptions?: ValidationPipeOptions): DynamicModule;
|
|
6
6
|
}
|