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.
Files changed (59) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +123 -5
  3. package/package.json +8 -4
  4. package/src/builders/route-decorators.builder.js +5 -1
  5. package/src/dynamic-api.module.d.ts +1 -1
  6. package/src/dynamic-api.module.js +37 -12
  7. package/src/helpers/config.helper.d.ts +61 -0
  8. package/src/helpers/config.helper.js +95 -0
  9. package/src/helpers/index.d.ts +1 -1
  10. package/src/helpers/index.js +1 -1
  11. package/src/interfaces/dynamic-api-options.interface.d.ts +5 -4
  12. package/src/interfaces/route-config.interface.d.ts +2 -1
  13. package/src/mixins/entity-presenter.mixin.d.ts +2 -33
  14. package/src/mixins/entity-presenter.mixin.js +3 -2
  15. package/src/modules/create-many/create-many-controller.interface.d.ts +3 -1
  16. package/src/modules/create-many/create-many-controller.mixin.js +8 -2
  17. package/src/modules/create-many/create-many.helper.d.ts +2 -2
  18. package/src/modules/create-many/create-many.helper.js +2 -6
  19. package/src/modules/create-many/create-many.module.d.ts +2 -2
  20. package/src/modules/create-many/create-many.module.js +2 -2
  21. package/src/modules/create-one/create-one-controller.mixin.js +1 -1
  22. package/src/modules/create-one/create-one.helper.d.ts +2 -2
  23. package/src/modules/create-one/create-one.helper.js +2 -6
  24. package/src/modules/create-one/create-one.module.d.ts +2 -2
  25. package/src/modules/create-one/create-one.module.js +2 -2
  26. package/src/modules/delete-one/delete-one.helper.d.ts +2 -2
  27. package/src/modules/delete-one/delete-one.helper.js +2 -6
  28. package/src/modules/delete-one/delete-one.module.d.ts +2 -2
  29. package/src/modules/delete-one/delete-one.module.js +2 -2
  30. package/src/modules/duplicate-one/base-duplicate-one.service.d.ts +1 -1
  31. package/src/modules/duplicate-one/duplicate-one-controller.interface.d.ts +1 -1
  32. package/src/modules/duplicate-one/duplicate-one-controller.mixin.js +1 -1
  33. package/src/modules/duplicate-one/duplicate-one-service.interface.d.ts +1 -1
  34. package/src/modules/duplicate-one/duplicate-one.helper.d.ts +2 -2
  35. package/src/modules/duplicate-one/duplicate-one.helper.js +2 -6
  36. package/src/modules/duplicate-one/duplicate-one.module.d.ts +2 -2
  37. package/src/modules/duplicate-one/duplicate-one.module.js +2 -2
  38. package/src/modules/get-many/get-many.helper.d.ts +2 -2
  39. package/src/modules/get-many/get-many.helper.js +2 -6
  40. package/src/modules/get-many/get-many.module.d.ts +2 -2
  41. package/src/modules/get-many/get-many.module.js +2 -2
  42. package/src/modules/get-one/get-one.helper.d.ts +2 -2
  43. package/src/modules/get-one/get-one.helper.js +2 -6
  44. package/src/modules/get-one/get-one.module.d.ts +2 -2
  45. package/src/modules/get-one/get-one.module.js +2 -2
  46. package/src/modules/replace-one/replace-one-controller.mixin.js +1 -1
  47. package/src/modules/replace-one/replace-one.helper.d.ts +2 -2
  48. package/src/modules/replace-one/replace-one.helper.js +2 -6
  49. package/src/modules/replace-one/replace-one.module.d.ts +2 -2
  50. package/src/modules/replace-one/replace-one.module.js +2 -2
  51. package/src/modules/update-one/update-one-controller.mixin.js +1 -1
  52. package/src/modules/update-one/update-one.helper.d.ts +2 -2
  53. package/src/modules/update-one/update-one.helper.js +2 -6
  54. package/src/modules/update-one/update-one.module.d.ts +2 -2
  55. package/src/modules/update-one/update-one.module.js +2 -2
  56. package/src/version.json +1 -1
  57. package/tsconfig.tsbuildinfo +1 -1
  58. package/src/helpers/swagger.helper.d.ts +0 -12
  59. 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
- `npm i -S mongodb-dynamic-api`
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
+ ![User API](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README/images/dynamic-api-user-full.Jpeg?raw=true "User API")
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-beta.6",
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)({ type: this.body })] : []),
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: apiVersion }, routes, }: DynamicApiOptions<Entity>): DynamicModule;
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: apiVersion }, routes, }) {
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 ?? apiVersion;
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
- return modules_1.CreateManyModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
65
+ module = modules_1.CreateManyModule;
66
+ break;
50
67
  case 'CreateOne':
51
- return modules_1.CreateOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
68
+ module = modules_1.CreateOneModule;
69
+ break;
52
70
  case 'DeleteOne':
53
- return modules_1.DeleteOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
71
+ module = modules_1.DeleteOneModule;
72
+ break;
54
73
  case 'DuplicateOne':
55
- return modules_1.DuplicateOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
74
+ module = modules_1.DuplicateOneModule;
75
+ break;
56
76
  case 'GetMany':
57
- return modules_1.GetManyModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
77
+ module = modules_1.GetManyModule;
78
+ break;
58
79
  case 'GetOne':
59
- return modules_1.GetOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
80
+ module = modules_1.GetOneModule;
81
+ break;
60
82
  case 'ReplaceOne':
61
- return modules_1.ReplaceOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
83
+ module = modules_1.ReplaceOneModule;
84
+ break;
62
85
  case 'UpdateOne':
63
- return modules_1.UpdateOneModule.forFeature(databaseModule, entity, path, apiTag, version, description, dTOs);
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;
@@ -1,2 +1,2 @@
1
+ export * from './config.helper';
1
2
  export * from './route-decorators.helper';
2
- export * from './swagger.helper';
@@ -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
- export interface DynamicApiOptions<Entity extends BaseEntity> {
10
+ interface DynamicApiOptions<Entity extends BaseEntity> {
10
11
  entity: Type<Entity>;
11
12
  controllerOptions: ControllerOptions;
12
- routes: RouteConfig<Entity>[];
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
- function EntityPresenterMixin(entity) {
5
- class EntityPresenter extends entity {
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<Body>(body: Body): Promise<Entity[]>;
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}Body`,
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
  }