UNPKG

mongodb-dynamic-api

Version:

Auto generated CRUD API for MongoDB using NestJS

159 lines 9.72 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var DynamicApiModule_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamicApiModule = void 0; const cache_manager_1 = require("@nestjs/cache-manager"); const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const http_adapter_host_1 = require("@nestjs/core/helpers/http-adapter-host"); const mongoose_1 = require("@nestjs/mongoose"); const guards_1 = require("./guards"); const helpers_1 = require("./helpers"); const interceptors_1 = require("./interceptors"); const interfaces_1 = require("./interfaces"); const modules_1 = require("./modules"); const routes_1 = require("./routes"); const services_1 = require("./services"); let DynamicApiModule = DynamicApiModule_1 = class DynamicApiModule { static forRoot(uri, { useGlobalCache = true, cacheOptions = {}, useAuth, routesConfig, webSocket, } = {}) { if (!uri) { throw new Error('You must provide a valid mongodb uri in the forRoot method to use MongoDB Dynamic API'); } this.state.set([ 'partial', this.buildStateFromOptions(uri, useGlobalCache, cacheOptions, useAuth, routesConfig, webSocket), ]); return { module: DynamicApiModule_1, imports: [ modules_1.DynamicApiConfigModule.register(this.state.get()), cache_manager_1.CacheModule.register({ isGlobal: true, ...cacheOptions }), mongoose_1.MongooseModule.forRoot(uri, { connectionName: this.state.get('connectionName') }), ...(useAuth?.userEntity ? [ modules_1.AuthModule.forRoot({ ...useAuth, webSocket: useAuth.webSocket ?? webSocket }), ] : []), ], exports: [modules_1.DynamicApiConfigModule], }; } static forFeature({ entity, controllerOptions, routes, webSocket: featureWebSocket, }) { const schema = (0, helpers_1.buildSchemaFromEntity)(entity); const databaseModule = mongoose_1.MongooseModule.forFeature([{ name: entity.name, schema }], this.state.get('connectionName')); services_1.DynamicApiGlobalStateService.addEntitySchema(entity, schema); return new Promise((resolve, reject) => { const waitForState = setTimeout(() => { reject(new Error('Dynamic API state could not be initialized. Please check your configuration.')); }, 5000); services_1.DynamicApiGlobalStateService.onInitialized().subscribe((stateInitialized) => { if (!stateInitialized) { return; } if (waitForState) { clearTimeout(waitForState); } const { version: controllerVersion, validationPipeOptions: controllerValidationPipeOptions, routesConfig: controllerRoutesConfig, } = controllerOptions; const castType = (t) => t; const castModule = (m) => m; const moduleByRouteType = new Map([ [castType('CreateMany'), castModule(routes_1.CreateManyModule)], [castType('CreateOne'), castModule(routes_1.CreateOneModule)], [castType('DeleteMany'), castModule(routes_1.DeleteManyModule)], [castType('DeleteOne'), castModule(routes_1.DeleteOneModule)], [castType('DuplicateMany'), castModule(routes_1.DuplicateManyModule)], [castType('DuplicateOne'), castModule(routes_1.DuplicateOneModule)], [castType('GetMany'), castModule(routes_1.GetManyModule)], [castType('GetOne'), castModule(routes_1.GetOneModule)], [castType('ReplaceOne'), castModule(routes_1.ReplaceOneModule)], [castType('UpdateMany'), castModule(routes_1.UpdateManyModule)], [castType('UpdateOne'), castModule(routes_1.UpdateOneModule)], [castType('Aggregate'), castModule(routes_1.AggregateModule)], ]); routes = this.setDefaultRoutes(this.state.get('routesConfig'), controllerRoutesConfig, routes); const apiModule = { module: DynamicApiModule_1, imports: [ ...routes.map((routeConfig) => { const { type, description: routeDescription, version: routeVersion, validationPipeOptions: routeValidationPipeOptions, webSocket: routeWebSocket, } = routeConfig; const module = moduleByRouteType.get(type); const description = routeDescription ?? (0, helpers_1.getDefaultRouteDescription)(type, entity.name); const version = routeVersion ?? controllerVersion; if (version && !(0, helpers_1.isValidVersion)(version)) { reject(new Error(`Invalid version ${version} for ${type} route.` + ' Version must be a string that matches numeric format, e.g. 1, 2, 3, ..., 99.')); return; } const validationPipeOptions = routeValidationPipeOptions ?? controllerValidationPipeOptions; return module.forFeature(databaseModule, entity, controllerOptions, { ...routeConfig, description }, version, validationPipeOptions ?? { transform: true }, routeWebSocket ?? featureWebSocket); }), ], providers: [ { provide: core_1.APP_INTERCEPTOR, inject: [cache_manager_1.CACHE_MANAGER, core_1.Reflector, http_adapter_host_1.HttpAdapterHost, interfaces_1.DYNAMIC_API_GLOBAL_STATE], useFactory: (cacheManager, reflector, httpAdapterHost, state) => { return new interceptors_1.DynamicApiCacheInterceptor(cacheManager, reflector, httpAdapterHost, state); }, }, { provide: core_1.APP_GUARD, inject: [core_1.Reflector, interfaces_1.DYNAMIC_API_GLOBAL_STATE], useFactory: (reflector, state) => { return new guards_1.DynamicApiJwtAuthGuard(reflector, state); }, }, ], }; resolve(apiModule); }); }); } static buildStateFromOptions(uri, useGlobalCache, cacheOptions, useAuth, routesConfig, webSocket) { const routesConfigState = this.state.get('routesConfig'); return { uri, initialized: true, isGlobalCacheEnabled: useGlobalCache, ...(cacheOptions?.excludePaths ? { cacheExcludedPaths: cacheOptions?.excludePaths } : {}), ...(useAuth?.userEntity ? { isAuthEnabled: true, credentials: { loginField: !useAuth.login?.loginField ? 'email' : String(useAuth.login.loginField), passwordField: !useAuth.login?.passwordField ? 'password' : String(useAuth.login.passwordField), }, jwtSecret: useAuth.jwt?.secret ?? 'dynamic-api-jwt-secret', jwtExpirationTime: useAuth.jwt?.expiresIn ?? '1d', gatewayOptions: (0, helpers_1.initializeConfigFromOptions)(webSocket), } : {}), ...(routesConfig?.excluded?.length || routesConfig?.defaults.length ? { routesConfig: { defaults: routesConfig.defaults?.length ? routesConfig.defaults : routesConfigState.defaults, excluded: routesConfig.excluded ?? [], }, } : {}), gatewayOptions: (0, helpers_1.initializeConfigFromOptions)(webSocket), }; } static setDefaultRoutes(stateRoutesConfig, controllerRoutesConfig = {}, routes = []) { const defaults = controllerRoutesConfig.defaults ?? stateRoutesConfig.defaults; const excluded = controllerRoutesConfig.excluded ?? stateRoutesConfig.excluded; const routesWithSubPath = routes.filter((route) => route.subPath); const routesWithoutSubPath = routes.filter((route) => !route.subPath && !defaults.includes(route.type)); return routesWithSubPath.concat(routesWithoutSubPath, defaults.filter((type) => !excluded.includes(type)) .map((type) => { const configuredRoute = routes.find((route) => route.type === type && !route.subPath); return configuredRoute ?? { type }; })); } }; exports.DynamicApiModule = DynamicApiModule; DynamicApiModule.state = new services_1.DynamicApiGlobalStateService(); exports.DynamicApiModule = DynamicApiModule = DynamicApiModule_1 = __decorate([ (0, common_1.Module)({}) ], DynamicApiModule); //# sourceMappingURL=dynamic-api.module.js.map