mongodb-dynamic-api 2.1.10 → 2.2.1

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 (79) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +1 -1
  3. package/src/decorators/index.d.ts +1 -0
  4. package/src/decorators/index.js +1 -0
  5. package/src/decorators/validator-pipe.decorator.d.ts +3 -0
  6. package/src/decorators/validator-pipe.decorator.js +8 -0
  7. package/src/dynamic-api.module.d.ts +2 -2
  8. package/src/dynamic-api.module.js +26 -32
  9. package/src/helpers/format.helper.d.ts +2 -2
  10. package/src/helpers/format.helper.js +5 -2
  11. package/src/helpers/schema.helper.js +2 -3
  12. package/src/interfaces/dynamic-api-controller-options.interface.d.ts +2 -0
  13. package/src/interfaces/dynamic-api-global-state.interface.d.ts +35 -3
  14. package/src/interfaces/dynamic-api-options.interface.d.ts +4 -2
  15. package/src/interfaces/dynamic-api-route-config.interface.d.ts +2 -0
  16. package/src/interfaces/dynamic-api-service-callback.interface.d.ts +28 -0
  17. package/src/interfaces/dynamic-api-service-callback.interface.js +2 -0
  18. package/src/interfaces/index.d.ts +1 -0
  19. package/src/interfaces/index.js +1 -0
  20. package/src/mixins/create-policies-guard.mixin.js +2 -2
  21. package/src/modules/auth/auth.helper.d.ts +4 -4
  22. package/src/modules/auth/auth.helper.js +6 -5
  23. package/src/modules/auth/auth.module.d.ts +1 -1
  24. package/src/modules/auth/auth.module.js +3 -3
  25. package/src/modules/auth/interfaces/auth-options.interface.d.ts +22 -14
  26. package/src/modules/auth/services/base-auth.service.d.ts +4 -3
  27. package/src/modules/auth/services/base-auth.service.js +16 -5
  28. package/src/routes/create-many/base-create-many.service.d.ts +2 -0
  29. package/src/routes/create-many/base-create-many.service.js +7 -2
  30. package/src/routes/create-many/create-many.helper.d.ts +2 -2
  31. package/src/routes/create-many/create-many.helper.js +7 -9
  32. package/src/routes/create-many/create-many.module.js +1 -1
  33. package/src/routes/create-one/base-create-one.service.d.ts +2 -0
  34. package/src/routes/create-one/base-create-one.service.js +3 -1
  35. package/src/routes/create-one/create-one.helper.d.ts +2 -2
  36. package/src/routes/create-one/create-one.helper.js +7 -9
  37. package/src/routes/create-one/create-one.module.js +1 -1
  38. package/src/routes/delete-many/delete-many.helper.js +6 -8
  39. package/src/routes/delete-one/delete-one.helper.js +6 -8
  40. package/src/routes/duplicate-many/base-duplicate-many.service.d.ts +2 -0
  41. package/src/routes/duplicate-many/base-duplicate-many.service.js +3 -1
  42. package/src/routes/duplicate-many/duplicate-many.helper.d.ts +2 -2
  43. package/src/routes/duplicate-many/duplicate-many.helper.js +8 -9
  44. package/src/routes/duplicate-many/duplicate-many.module.js +1 -1
  45. package/src/routes/duplicate-one/base-duplicate-one.service.d.ts +2 -0
  46. package/src/routes/duplicate-one/base-duplicate-one.service.js +3 -1
  47. package/src/routes/duplicate-one/duplicate-one.helper.d.ts +2 -2
  48. package/src/routes/duplicate-one/duplicate-one.helper.js +8 -9
  49. package/src/routes/duplicate-one/duplicate-one.module.js +1 -1
  50. package/src/routes/get-many/base-get-many.service.d.ts +2 -0
  51. package/src/routes/get-many/base-get-many.service.js +3 -0
  52. package/src/routes/get-many/get-many.helper.d.ts +2 -2
  53. package/src/routes/get-many/get-many.helper.js +8 -9
  54. package/src/routes/get-many/get-many.module.js +1 -1
  55. package/src/routes/get-one/base-get-one.service.d.ts +2 -0
  56. package/src/routes/get-one/base-get-one.service.js +3 -0
  57. package/src/routes/get-one/get-one.helper.d.ts +2 -2
  58. package/src/routes/get-one/get-one.helper.js +8 -9
  59. package/src/routes/get-one/get-one.module.js +1 -1
  60. package/src/routes/replace-one/base-replace-one.service.d.ts +2 -0
  61. package/src/routes/replace-one/base-replace-one.service.js +3 -1
  62. package/src/routes/replace-one/replace-one.helper.d.ts +2 -2
  63. package/src/routes/replace-one/replace-one.helper.js +8 -9
  64. package/src/routes/replace-one/replace-one.module.js +1 -1
  65. package/src/routes/update-many/base-update-many.service.d.ts +2 -0
  66. package/src/routes/update-many/base-update-many.service.js +3 -1
  67. package/src/routes/update-many/update-many.helper.d.ts +2 -2
  68. package/src/routes/update-many/update-many.helper.js +8 -9
  69. package/src/routes/update-many/update-many.module.js +1 -1
  70. package/src/routes/update-one/base-update-one.service.d.ts +2 -0
  71. package/src/routes/update-one/base-update-one.service.js +3 -1
  72. package/src/routes/update-one/update-one.helper.d.ts +2 -2
  73. package/src/routes/update-one/update-one.helper.js +8 -9
  74. package/src/routes/update-one/update-one.module.js +1 -1
  75. package/src/services/base/base.service.js +3 -1
  76. package/src/services/dynamic-api-global-state/dynamic-api-global-state.service.d.ts +30 -1
  77. package/src/services/dynamic-api-global-state/dynamic-api-global-state.service.js +37 -4
  78. package/src/version.json +1 -1
  79. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  Changelog
2
2
 
3
+ ## [2.2.1](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.2.0...v2.2.1) (2024-04-30)
4
+
5
+ ## [2.2.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.10...v2.2.0) (2024-04-30)
6
+
7
+
8
+ ### api
9
+
10
+ * **api:** add routes service callback ([bb233fe](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/bb233fe79565863fe2191b224176accaf1725907))
11
+ * **api:** add the possibility to configure default or excluded routes ([ef501df](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/ef501df7c453352b16056fc2766f3bf2cbefb532))
12
+
13
+
14
+ ### auth
15
+
16
+ * **auth:** add service callbacks ([d93ad01](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/d93ad01589099c92757922dc3e9320332c563e82))
17
+
18
+
19
+ ### validation
20
+
21
+ * **validation:** add custom pipe and update default auth to avoid request errors if not configured ([f75fca7](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/f75fca7cdb1bfc5d0fcd72ea1acf75179b22d69c))
22
+
3
23
  ## [2.1.10](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.9...v2.1.10) (2024-04-29)
4
24
 
5
25
  ## [2.1.9](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.8...v2.1.9) (2024-04-01)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb-dynamic-api",
3
- "version": "2.1.10",
3
+ "version": "2.2.1",
4
4
  "description": "Auto generated CRUD API for MongoDB using NestJS",
5
5
  "readmeFilename": "README.md",
6
6
  "main": "index.js",
@@ -1,2 +1,3 @@
1
1
  export * from './public.decorator';
2
2
  export * from './schema-options.decorator';
3
+ export * from './validator-pipe.decorator';
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./public.decorator"), exports);
18
18
  __exportStar(require("./schema-options.decorator"), exports);
19
+ __exportStar(require("./validator-pipe.decorator"), exports);
@@ -0,0 +1,3 @@
1
+ import { ValidationPipeOptions } from '@nestjs/common';
2
+ declare function ValidatorPipe(validationPipeOptions?: ValidationPipeOptions): ClassDecorator;
3
+ export { ValidatorPipe };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidatorPipe = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ function ValidatorPipe(validationPipeOptions) {
6
+ return validationPipeOptions ? (0, common_1.applyDecorators)((0, common_1.UsePipes)(new common_1.ValidationPipe(validationPipeOptions))) : (_) => undefined;
7
+ }
8
+ exports.ValidatorPipe = ValidatorPipe;
@@ -4,9 +4,9 @@ import { BaseEntity } from './models';
4
4
  import { DynamicApiGlobalStateService } from './services';
5
5
  export declare class DynamicApiModule {
6
6
  static readonly state: DynamicApiGlobalStateService;
7
- static forRoot(uri: string, { useGlobalCache, cacheOptions, useAuth, }?: DynamicApiForRootOptions): DynamicModule;
7
+ static forRoot<Entity extends BaseEntity = any>(uri: string, { useGlobalCache, cacheOptions, useAuth, routesConfig, }?: DynamicApiForRootOptions<Entity>): DynamicModule;
8
8
  static forFeature<Entity extends BaseEntity>({ entity, controllerOptions, routes, }: DynamicApiForFeatureOptions<Entity>): Promise<DynamicModule>;
9
9
  private static buildStateFromOptions;
10
10
  private static initializeAuthOptions;
11
- private static setDefaultRoutesIfNotConfigured;
11
+ private static setDefaultRoutes;
12
12
  }
@@ -22,13 +22,13 @@ const modules_1 = require("./modules");
22
22
  const routes_1 = require("./routes");
23
23
  const services_1 = require("./services");
24
24
  let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
25
- static forRoot(uri, { useGlobalCache = true, cacheOptions = {}, useAuth, } = {}) {
25
+ static forRoot(uri, { useGlobalCache = true, cacheOptions = {}, useAuth, routesConfig, } = {}) {
26
26
  if (!uri) {
27
27
  throw new Error('You must provide a valid mongodb uri in the forRoot method to use MongoDB Dynamic API');
28
28
  }
29
29
  this.state.set([
30
30
  'partial',
31
- this.buildStateFromOptions(useGlobalCache, cacheOptions, useAuth),
31
+ this.buildStateFromOptions(useGlobalCache, cacheOptions, useAuth, routesConfig),
32
32
  ]);
33
33
  return {
34
34
  module: DynamicApiModule_1,
@@ -44,11 +44,12 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
44
44
  };
45
45
  }
46
46
  static forFeature({ entity, controllerOptions, routes = [], }) {
47
- const databaseModule = mongoose_1.MongooseModule.forFeature([{ name: entity.name, schema: (0, helpers_1.buildSchemaFromEntity)(entity) }], this.state.get('connectionName'));
48
- routes = this.setDefaultRoutesIfNotConfigured([...routes]);
47
+ const schema = (0, helpers_1.buildSchemaFromEntity)(entity);
48
+ const databaseModule = mongoose_1.MongooseModule.forFeature([{ name: entity.name, schema }], this.state.get('connectionName'));
49
+ services_1.DynamicApiGlobalStateService.addEntitySchema(entity.name, schema);
49
50
  return new Promise((resolve, reject) => {
50
51
  const waitInitializedStateInterval = setInterval(async () => {
51
- const stateInitialized = await (0, rxjs_1.firstValueFrom)(this.state.get().onInitialized());
52
+ const stateInitialized = await (0, rxjs_1.firstValueFrom)(services_1.DynamicApiGlobalStateService.onInitialized());
52
53
  if (!stateInitialized) {
53
54
  return;
54
55
  }
@@ -56,7 +57,7 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
56
57
  clearTimeout(waitForState);
57
58
  }
58
59
  clearInterval(waitInitializedStateInterval);
59
- const { version: controllerVersion, validationPipeOptions: controllerValidationPipeOptions, } = controllerOptions;
60
+ const { version: controllerVersion, validationPipeOptions: controllerValidationPipeOptions, routesConfig: controllerRoutesConfig, } = controllerOptions;
60
61
  const castType = (t) => t;
61
62
  const castModule = (m) => m;
62
63
  const moduleByRouteType = new Map([
@@ -72,6 +73,7 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
72
73
  [castType('UpdateMany'), castModule(routes_1.UpdateManyModule)],
73
74
  [castType('UpdateOne'), castModule(routes_1.UpdateOneModule)],
74
75
  ]);
76
+ routes = this.setDefaultRoutes(this.state.get('routesConfig'), controllerRoutesConfig, routes);
75
77
  const apiModule = {
76
78
  module: DynamicApiModule_1,
77
79
  imports: [
@@ -118,7 +120,8 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
118
120
  }, 5000);
119
121
  });
120
122
  }
121
- static buildStateFromOptions(useGlobalCache, cacheOptions, useAuth) {
123
+ static buildStateFromOptions(useGlobalCache, cacheOptions, useAuth, routesConfig) {
124
+ const routesConfigState = this.state.get('routesConfig');
122
125
  return {
123
126
  initialized: true,
124
127
  isGlobalCacheEnabled: useGlobalCache,
@@ -131,6 +134,12 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
131
134
  },
132
135
  jwtSecret: useAuth.jwt?.secret ?? 'dynamic-api-jwt-secret',
133
136
  } : {}),
137
+ ...(routesConfig?.excluded?.length || routesConfig?.defaults.length ? {
138
+ routesConfig: {
139
+ defaults: routesConfig.defaults?.length ? routesConfig.defaults : routesConfigState.defaults,
140
+ excluded: routesConfig.excluded ?? [],
141
+ },
142
+ } : {}),
134
143
  };
135
144
  }
136
145
  static initializeAuthOptions(useAuth) {
@@ -152,36 +161,21 @@ let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule {
152
161
  protected: false,
153
162
  additionalFields: [],
154
163
  },
164
+ login: useAuth.login ?? {},
155
165
  };
156
166
  }
157
- static setDefaultRoutesIfNotConfigured(routes) {
158
- if (!routes.length) {
159
- return [
160
- { type: 'GetMany' },
161
- { type: 'GetOne' },
162
- { type: 'CreateMany' },
163
- { type: 'CreateOne' },
164
- { type: 'UpdateMany' },
165
- { type: 'UpdateOne' },
166
- { type: 'ReplaceOne' },
167
- { type: 'DuplicateMany' },
168
- { type: 'DuplicateOne' },
169
- { type: 'DeleteMany' },
170
- { type: 'DeleteOne' },
171
- ];
172
- }
173
- return routes;
167
+ static setDefaultRoutes(stateRoutesConfig, controllerRoutesConfig = {}, routes = []) {
168
+ const defaults = controllerRoutesConfig.defaults ?? stateRoutesConfig.defaults;
169
+ const excluded = controllerRoutesConfig.excluded ?? stateRoutesConfig.excluded;
170
+ return defaults.filter((type) => !excluded.includes(type))
171
+ .map((type) => {
172
+ const configuredRoute = routes.find((route) => route.type === type);
173
+ return configuredRoute ?? { type };
174
+ }).concat(routes.filter((route) => !defaults.includes(route.type)));
174
175
  }
175
176
  };
176
177
  exports.DynamicApiModule = DynamicApiModule;
177
- DynamicApiModule.state = new services_1.DynamicApiGlobalStateService({
178
- connectionName: 'dynamic-api-connection',
179
- isGlobalCacheEnabled: true,
180
- isAuthEnabled: false,
181
- credentials: null,
182
- jwtSecret: undefined,
183
- cacheExcludedPaths: [],
184
- });
178
+ DynamicApiModule.state = new services_1.DynamicApiGlobalStateService();
185
179
  exports.DynamicApiModule = DynamicApiModule = DynamicApiModule_1 = __decorate([
186
180
  (0, common_1.Module)({})
187
181
  ], DynamicApiModule);
@@ -1,5 +1,5 @@
1
1
  import { RouteType } from '../interfaces';
2
2
  export declare function pascalCase(str?: string): string;
3
3
  export declare function isValidVersion(version: string): boolean;
4
- export declare function getFormattedApiTag<Entity>(apiTag: string | undefined, entityName: string): string;
5
- export declare function getNamePrefix(routeType: RouteType, entityName: string, version: string | undefined): string;
4
+ export declare function getFormattedApiTag(apiTag: string | undefined, entityName: string): string;
5
+ export declare function provideName(routeType: RouteType, entityName: string, version: string | undefined, suffix: 'Service' | 'Controller' | 'PoliciesGuard'): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNamePrefix = exports.getFormattedApiTag = exports.isValidVersion = exports.pascalCase = void 0;
3
+ exports.provideName = exports.getFormattedApiTag = exports.isValidVersion = exports.pascalCase = void 0;
4
4
  const lodash_1 = require("lodash");
5
5
  const versioning_config_helper_1 = require("./versioning-config.helper");
6
6
  function pascalCase(str) {
@@ -18,4 +18,7 @@ exports.getFormattedApiTag = getFormattedApiTag;
18
18
  function getNamePrefix(routeType, entityName, version) {
19
19
  return `${routeType}${entityName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}`;
20
20
  }
21
- exports.getNamePrefix = getNamePrefix;
21
+ function provideName(routeType, entityName, version, suffix) {
22
+ return `${getNamePrefix(routeType, entityName, version)}${suffix}`;
23
+ }
24
+ exports.provideName = provideName;
@@ -7,9 +7,8 @@ const interfaces_1 = require("../interfaces");
7
7
  function buildSchemaFromEntity(entity) {
8
8
  const { indexes, hooks, customInit } = Reflect.getOwnMetadata(decorators_1.DYNAMIC_API_SCHEMA_OPTIONS_METADATA, entity) ?? {};
9
9
  const schema = mongoose_1.SchemaFactory.createForClass(entity);
10
- if (Object.getOwnPropertyNames(schema.paths).includes('createdAt')) {
11
- schema.set('timestamps', true);
12
- }
10
+ schema.set('timestamps', Object.getOwnPropertyNames(schema.paths).includes('createdAt') &&
11
+ Object.getOwnPropertyNames(schema.paths).includes('updatedAt'));
13
12
  if (indexes) {
14
13
  indexes.forEach(({ fields, options }) => {
15
14
  schema.index(fields, options);
@@ -1,6 +1,7 @@
1
1
  import { ValidationPipeOptions } from '@nestjs/common';
2
2
  import { BaseEntity } from '../models';
3
3
  import { ControllerAbilityPredicate } from './dynamic-api-ability.interface';
4
+ import { RoutesConfig } from './dynamic-api-global-state.interface';
4
5
  interface DynamicApiControllerOptions<Entity extends BaseEntity> {
5
6
  path: string;
6
7
  apiTag?: string;
@@ -8,5 +9,6 @@ interface DynamicApiControllerOptions<Entity extends BaseEntity> {
8
9
  isPublic?: boolean;
9
10
  validationPipeOptions?: ValidationPipeOptions;
10
11
  abilityPredicates?: ControllerAbilityPredicate<Entity>[];
12
+ routesConfig?: Partial<RoutesConfig>;
11
13
  }
12
14
  export { DynamicApiControllerOptions };
@@ -1,8 +1,40 @@
1
- import { BehaviorSubject } from 'rxjs';
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/types/inferschematype" />
25
+ import { Schema } from 'mongoose';
26
+ import { RouteType } from './dynamic-api-route-type.type';
2
27
  type Credentials = {
3
28
  loginField: string;
4
29
  passwordField: string;
5
30
  };
31
+ type EntitySchemas<T = any> = {
32
+ [name: string]: Schema<T>;
33
+ };
34
+ type RoutesConfig = {
35
+ excluded: RouteType[];
36
+ defaults: RouteType[];
37
+ };
6
38
  interface DynamicApiGlobalState {
7
39
  initialized: boolean;
8
40
  connectionName: string;
@@ -11,6 +43,6 @@ interface DynamicApiGlobalState {
11
43
  isAuthEnabled: boolean;
12
44
  credentials: Credentials;
13
45
  jwtSecret: string | undefined;
14
- onInitialized(): BehaviorSubject<boolean>;
46
+ routesConfig: RoutesConfig;
15
47
  }
16
- export { DynamicApiGlobalState, Credentials };
48
+ export { DynamicApiGlobalState, Credentials, EntitySchemas, RoutesConfig };
@@ -3,12 +3,14 @@ import { BaseEntity } from '../models';
3
3
  import { DynamicApiAuthOptions } from '../modules';
4
4
  import { DynamicApiControllerOptions } from './dynamic-api-controller-options.interface';
5
5
  import { DynamicApiCacheOptions } from './dynamic-api-cache-options.interface';
6
+ import { RoutesConfig } from './dynamic-api-global-state.interface';
6
7
  import { DynamicAPIRouteConfig } from './dynamic-api-route-config.interface';
7
8
  declare const DYNAMIC_API_GLOBAL_STATE: unique symbol;
8
- interface DynamicApiForRootOptions {
9
+ interface DynamicApiForRootOptions<Entity extends BaseEntity = any> {
9
10
  useGlobalCache?: boolean;
10
11
  cacheOptions?: DynamicApiCacheOptions;
11
- useAuth?: DynamicApiAuthOptions;
12
+ useAuth?: DynamicApiAuthOptions<Entity>;
13
+ routesConfig?: Partial<RoutesConfig>;
12
14
  }
13
15
  interface DynamicApiForFeatureOptions<Entity extends BaseEntity> {
14
16
  entity: Type<Entity>;
@@ -3,6 +3,7 @@ import { BaseEntity } from '../models';
3
3
  import { AbilityPredicate } from './dynamic-api-ability.interface';
4
4
  import { DTOsBundle } from './dynamic-api-route-dtos-bundle.type';
5
5
  import { RouteType } from './dynamic-api-route-type.type';
6
+ import { DynamicApiServiceCallback } from './dynamic-api-service-callback.interface';
6
7
  interface DynamicAPIRouteConfig<Entity extends BaseEntity> {
7
8
  type: RouteType;
8
9
  isPublic?: boolean;
@@ -11,5 +12,6 @@ interface DynamicAPIRouteConfig<Entity extends BaseEntity> {
11
12
  dTOs?: DTOsBundle;
12
13
  validationPipeOptions?: ValidationPipeOptions;
13
14
  abilityPredicate?: AbilityPredicate<Entity>;
15
+ callback?: DynamicApiServiceCallback<Entity>;
14
16
  }
15
17
  export { DynamicAPIRouteConfig };
@@ -0,0 +1,28 @@
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/types/inferschematype" />
25
+ import { Model } from 'mongoose';
26
+ import { BaseEntity } from '../models';
27
+ type DynamicApiServiceCallback<Entity extends BaseEntity> = (entity: Partial<Entity>, model: Model<Entity>) => Promise<void>;
28
+ export type { DynamicApiServiceCallback };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -11,5 +11,6 @@ export * from './dynamic-api-route-dtos-bundle.type';
11
11
  export * from './dynamic-api-route-module.type';
12
12
  export * from './dynamic-api-route-type.type';
13
13
  export * from './dynamic-api-schema-options.interface';
14
+ export * from './dynamic-api-service-callback.interface';
14
15
  export * from './dynamic-api-service-provider.interface';
15
16
  export * from './dynamic-api-swagger-options.type';
@@ -27,5 +27,6 @@ __exportStar(require("./dynamic-api-route-dtos-bundle.type"), exports);
27
27
  __exportStar(require("./dynamic-api-route-module.type"), exports);
28
28
  __exportStar(require("./dynamic-api-route-type.type"), exports);
29
29
  __exportStar(require("./dynamic-api-schema-options.interface"), exports);
30
+ __exportStar(require("./dynamic-api-service-callback.interface"), exports);
30
31
  __exportStar(require("./dynamic-api-service-provider.interface"), exports);
31
32
  __exportStar(require("./dynamic-api-swagger-options.type"), exports);
@@ -28,11 +28,11 @@ function CreatePoliciesGuardMixin(entity, routeType, version, abilityPredicate)
28
28
  };
29
29
  RoutePoliciesGuard = __decorate([
30
30
  (0, common_1.Injectable)(),
31
- __param(0, (0, common_1.Inject)(`${(0, helpers_1.getNamePrefix)(routeType, entity.name, version)}Service`)),
31
+ __param(0, (0, common_1.Inject)(`${(0, helpers_1.provideName)(routeType, entity.name, version, 'Service')}`)),
32
32
  __metadata("design:paramtypes", [Object])
33
33
  ], RoutePoliciesGuard);
34
34
  Object.defineProperty(RoutePoliciesGuard, 'name', {
35
- value: `${(0, helpers_1.getNamePrefix)(routeType, entity.name, version)}PoliciesGuard`,
35
+ value: `${(0, helpers_1.provideName)(routeType, entity.name, version, 'PoliciesGuard')}`,
36
36
  writable: false,
37
37
  });
38
38
  return RoutePoliciesGuard;
@@ -1,10 +1,10 @@
1
- import { Type } from '@nestjs/common';
2
- import { DynamicAPIServiceProvider } from '../../interfaces';
1
+ import { Type, ValidationPipeOptions } from '@nestjs/common';
2
+ import { DynamicApiServiceCallback, DynamicAPIServiceProvider } from '../../interfaces';
3
3
  import { BaseEntity } from '../../models';
4
4
  import { AuthControllerConstructor, DynamicApiRegisterOptions } from './interfaces';
5
5
  declare const authServiceProviderName = "DynamicApiAuthService";
6
6
  declare const localStrategyProviderName = "DynamicApiLocalStrategy";
7
7
  declare function createLocalStrategyProvider<Entity extends BaseEntity>(loginField: keyof Entity, passwordField: keyof Entity): DynamicAPIServiceProvider;
8
- declare function createAuthServiceProvider<Entity extends BaseEntity>(userEntity: Type<Entity>, loginField: keyof Entity, passwordField: keyof Entity, additionalFields: (keyof Entity)[] | undefined): DynamicAPIServiceProvider;
9
- declare function createAuthController<Entity extends BaseEntity>(userEntity: Type<Entity>, loginField: keyof Entity, passwordField: keyof Entity, additionalRequestFields: (keyof Entity)[] | undefined, registerOptions: DynamicApiRegisterOptions<Entity> | undefined): AuthControllerConstructor<Entity>;
8
+ declare function createAuthServiceProvider<Entity extends BaseEntity>(userEntity: Type<Entity>, loginField: keyof Entity, passwordField: keyof Entity, additionalFields: (keyof Entity)[] | undefined, registerCallback: DynamicApiServiceCallback<Entity> | undefined, loginCallback: DynamicApiServiceCallback<Entity> | undefined): DynamicAPIServiceProvider;
9
+ declare function createAuthController<Entity extends BaseEntity>(userEntity: Type<Entity>, loginField: keyof Entity, passwordField: keyof Entity, additionalRequestFields: (keyof Entity)[] | undefined, registerOptions: DynamicApiRegisterOptions<Entity> | undefined, validationPipeOptions: ValidationPipeOptions | undefined): AuthControllerConstructor<Entity>;
10
10
  export { authServiceProviderName, createAuthController, createAuthServiceProvider, createLocalStrategyProvider, localStrategyProviderName, };
@@ -56,7 +56,7 @@ function createLocalStrategyProvider(loginField, passwordField) {
56
56
  };
57
57
  }
58
58
  exports.createLocalStrategyProvider = createLocalStrategyProvider;
59
- function createAuthServiceProvider(userEntity, loginField, passwordField, additionalFields) {
59
+ function createAuthServiceProvider(userEntity, loginField, passwordField, additionalFields, registerCallback, loginCallback) {
60
60
  let AuthService = class AuthService extends services_2.BaseAuthService {
61
61
  constructor(model, jwtService, bcryptService) {
62
62
  super(model, jwtService, bcryptService);
@@ -66,6 +66,8 @@ function createAuthServiceProvider(userEntity, loginField, passwordField, additi
66
66
  this.additionalRequestFields = additionalFields ?? [];
67
67
  this.loginField = loginField;
68
68
  this.passwordField = passwordField;
69
+ this.registerCallback = registerCallback;
70
+ this.loginCallback = loginCallback;
69
71
  }
70
72
  };
71
73
  AuthService = __decorate([
@@ -80,7 +82,7 @@ function createAuthServiceProvider(userEntity, loginField, passwordField, additi
80
82
  };
81
83
  }
82
84
  exports.createAuthServiceProvider = createAuthServiceProvider;
83
- function createAuthController(userEntity, loginField, passwordField, additionalRequestFields, registerOptions) {
85
+ function createAuthController(userEntity, loginField, passwordField, additionalRequestFields, registerOptions, validationPipeOptions) {
84
86
  let AuthController = class AuthController extends (0, mixins_1.AuthControllerMixin)(userEntity, loginField, passwordField, additionalRequestFields, registerOptions ?? {}) {
85
87
  constructor(service) {
86
88
  super(service);
@@ -90,10 +92,9 @@ function createAuthController(userEntity, loginField, passwordField, additionalR
90
92
  AuthController = __decorate([
91
93
  (0, common_1.Controller)('auth'),
92
94
  (0, swagger_1.ApiTags)('Auth'),
93
- (0, common_1.UsePipes)(new common_1.ValidationPipe({
95
+ (0, common_1.UsePipes)(new common_1.ValidationPipe(validationPipeOptions ?? {
94
96
  transform: true,
95
- whitelist: true,
96
- forbidNonWhitelisted: true,
97
+ forbidUnknownValues: true,
97
98
  })),
98
99
  __param(0, (0, common_1.Inject)(authServiceProviderName)),
99
100
  __metadata("design:paramtypes", [Object])
@@ -3,7 +3,7 @@ import { BcryptService } from '../../services';
3
3
  import { DynamicApiAuthOptions } from './interfaces';
4
4
  import { JwtStrategy } from './strategies';
5
5
  export declare class AuthModule {
6
- static forRoot<Entity extends BaseEntity>({ user: { entity: userEntity, loginField, passwordField, requestAdditionalFields, }, jwt: { secret, expiresIn }, register, }: DynamicApiAuthOptions<Entity>, extraImports?: any[]): {
6
+ static forRoot<Entity extends BaseEntity>({ user: { entity: userEntity, loginField, passwordField, requestAdditionalFields, }, jwt: { secret, expiresIn }, register, login, validationPipeOptions, }: DynamicApiAuthOptions<Entity>, extraImports?: any[]): {
7
7
  module: typeof AuthModule;
8
8
  imports: any[];
9
9
  providers: (typeof BcryptService | import("../../interfaces/dynamic-api-service-provider.interface").DynamicAPIServiceProvider | typeof JwtStrategy)[];
@@ -18,9 +18,9 @@ const services_1 = require("../../services");
18
18
  const auth_helper_1 = require("./auth.helper");
19
19
  const strategies_1 = require("./strategies");
20
20
  let AuthModule = AuthModule_1 = class AuthModule {
21
- static forRoot({ user: { entity: userEntity, loginField, passwordField, requestAdditionalFields, }, jwt: { secret, expiresIn }, register, }, extraImports = []) {
22
- const AuthController = (0, auth_helper_1.createAuthController)(userEntity, loginField, passwordField, requestAdditionalFields, register);
23
- const AuthServiceProvider = (0, auth_helper_1.createAuthServiceProvider)(userEntity, loginField, passwordField, requestAdditionalFields);
21
+ static forRoot({ user: { entity: userEntity, loginField, passwordField, requestAdditionalFields, }, jwt: { secret, expiresIn }, register, login, validationPipeOptions, }, extraImports = []) {
22
+ const AuthController = (0, auth_helper_1.createAuthController)(userEntity, loginField, passwordField, requestAdditionalFields, register, validationPipeOptions);
23
+ const AuthServiceProvider = (0, auth_helper_1.createAuthServiceProvider)(userEntity, loginField, passwordField, requestAdditionalFields, register.callback, login.callback);
24
24
  const LocalStrategyProvider = (0, auth_helper_1.createLocalStrategyProvider)(loginField, passwordField);
25
25
  return {
26
26
  module: AuthModule_1,
@@ -1,7 +1,15 @@
1
- import { Type } from '@nestjs/common';
2
- import { RegisterAbilityPredicate } from '../../../interfaces';
1
+ import { Type, ValidationPipeOptions } from '@nestjs/common';
2
+ import { DynamicApiServiceCallback, RegisterAbilityPredicate } from '../../../interfaces';
3
3
  import { BaseEntity } from '../../../models';
4
+ type DynamicApiJWTOptions = {
5
+ secret: string;
6
+ expiresIn?: string | number;
7
+ };
8
+ type DynamicApiLoginOptions<Entity extends BaseEntity = any> = {
9
+ callback?: DynamicApiServiceCallback<Entity>;
10
+ };
4
11
  type DynamicApiRegisterOptions<Entity extends BaseEntity = any> = {
12
+ callback?: DynamicApiServiceCallback<Entity>;
5
13
  protected?: boolean;
6
14
  abilityPredicate?: RegisterAbilityPredicate;
7
15
  additionalFields?: (keyof Entity | {
@@ -9,17 +17,17 @@ type DynamicApiRegisterOptions<Entity extends BaseEntity = any> = {
9
17
  required?: boolean;
10
18
  })[];
11
19
  };
20
+ type DynamicApiUserOptions<Entity extends BaseEntity = any> = {
21
+ entity: Type<Entity>;
22
+ loginField?: keyof Entity;
23
+ passwordField?: keyof Entity;
24
+ requestAdditionalFields?: (keyof Entity)[];
25
+ };
12
26
  type DynamicApiAuthOptions<Entity extends BaseEntity = any> = {
13
- user: {
14
- entity: Type<Entity>;
15
- loginField?: keyof Entity;
16
- passwordField?: keyof Entity;
17
- requestAdditionalFields?: (keyof Entity)[];
18
- };
19
- register?: DynamicApiRegisterOptions;
20
- jwt?: {
21
- secret: string;
22
- expiresIn?: string | number;
23
- };
27
+ user: DynamicApiUserOptions<Entity>;
28
+ login?: DynamicApiLoginOptions<Entity>;
29
+ register?: DynamicApiRegisterOptions<Entity>;
30
+ jwt?: DynamicApiJWTOptions;
31
+ validationPipeOptions?: ValidationPipeOptions;
24
32
  };
25
- export type { DynamicApiAuthOptions, DynamicApiRegisterOptions };
33
+ export type { DynamicApiAuthOptions, DynamicApiRegisterOptions, DynamicApiUserOptions, DynamicApiJWTOptions, DynamicApiLoginOptions, };
@@ -22,9 +22,9 @@
22
22
  /// <reference types="mongoose/types/validation" />
23
23
  /// <reference types="mongoose/types/virtuals" />
24
24
  /// <reference types="mongoose/types/inferschematype" />
25
- import { Type } from '@nestjs/common';
26
25
  import { JwtService } from '@nestjs/jwt';
27
26
  import { Model } from 'mongoose';
27
+ import { DynamicApiServiceCallback } from '../../../interfaces';
28
28
  import { BaseEntity } from '../../../models';
29
29
  import { BaseService, BcryptService } from '../../../services';
30
30
  export declare abstract class BaseAuthService<Entity extends BaseEntity> extends BaseService<Entity> {
@@ -34,10 +34,11 @@ export declare abstract class BaseAuthService<Entity extends BaseEntity> extends
34
34
  protected loginField: keyof Entity;
35
35
  protected passwordField: keyof Entity;
36
36
  protected additionalRequestFields: (keyof Entity)[];
37
- protected entity: Type<Entity>;
37
+ protected registerCallback: DynamicApiServiceCallback<Entity> | undefined;
38
+ protected loginCallback: DynamicApiServiceCallback<Entity> | undefined;
38
39
  protected constructor(model: Model<Entity>, jwtService: JwtService, bcryptService: BcryptService);
39
40
  protected validateUser(login: string, pass: string): Promise<Entity>;
40
- protected login(user: Entity): Promise<{
41
+ protected login(user: Entity, fromMember?: boolean): Promise<{
41
42
  accessToken: string;
42
43
  }>;
43
44
  protected register(userToCreate: Partial<Entity>): Promise<{
@@ -24,7 +24,7 @@ class BaseAuthService extends services_1.BaseService {
24
24
  ];
25
25
  return this.buildUserFields(user, fieldsToBuild);
26
26
  }
27
- async login(user) {
27
+ async login(user, fromMember = false) {
28
28
  const fieldsToBuild = [
29
29
  '_id',
30
30
  'id',
@@ -32,15 +32,26 @@ class BaseAuthService extends services_1.BaseService {
32
32
  ...this.additionalRequestFields,
33
33
  ];
34
34
  const payload = this.buildUserFields(user, fieldsToBuild);
35
+ if (!fromMember && this.loginCallback) {
36
+ await this.loginCallback(payload, this.model);
37
+ }
35
38
  return {
36
39
  accessToken: this.jwtService.sign(payload),
37
40
  };
38
41
  }
39
42
  async register(userToCreate) {
40
43
  const hashedPassword = await this.bcryptService.hashPassword(userToCreate[this.passwordField]);
41
- const { _id } = await this.model.create({ ...userToCreate, [this.passwordField]: hashedPassword });
42
- const user = await this.findOneDocument(_id);
43
- return this.login(user);
44
+ try {
45
+ const { _id } = await this.model.create({ ...userToCreate, [this.passwordField]: hashedPassword });
46
+ const user = await this.findOneDocument(_id);
47
+ if (this.registerCallback) {
48
+ await this.registerCallback(user, this.model);
49
+ }
50
+ return this.login(user, true);
51
+ }
52
+ catch (error) {
53
+ this.handleDuplicateKeyError(error);
54
+ }
44
55
  }
45
56
  async getAccount({ id }) {
46
57
  const user = await this.findOneDocument(id);
@@ -55,7 +66,7 @@ class BaseAuthService extends services_1.BaseService {
55
66
  const hashedPassword = await this.bcryptService.hashPassword(newPassword);
56
67
  const { _id } = await this.model.findOneAndUpdate({ _id: userId }, { [this.passwordField]: hashedPassword }, { new: true });
57
68
  const user = await this.findOneDocument(_id);
58
- return this.login(user);
69
+ return this.login(user, true);
59
70
  }
60
71
  buildUserFields(user, fieldsToBuild) {
61
72
  return this.buildInstance(fieldsToBuild.reduce((acc, field) => (user[field] !== undefined ? { ...acc, [field]: user[field] } : acc), {}));
@@ -23,11 +23,13 @@
23
23
  /// <reference types="mongoose/types/virtuals" />
24
24
  /// <reference types="mongoose/types/inferschematype" />
25
25
  import { Model } from 'mongoose';
26
+ import { DynamicApiServiceCallback } from '../../interfaces';
26
27
  import { BaseEntity } from '../../models';
27
28
  import { BaseService } from '../../services';
28
29
  import { CreateManyService } from './create-many-service.interface';
29
30
  export declare abstract class BaseCreateManyService<Entity extends BaseEntity> extends BaseService<Entity> implements CreateManyService<Entity> {
30
31
  protected readonly model: Model<Entity>;
32
+ protected readonly callback: DynamicApiServiceCallback<Entity> | undefined;
31
33
  protected constructor(model: Model<Entity>);
32
34
  createMany(partials: Partial<Entity>[]): Promise<Entity[]>;
33
35
  }