Admin JS with NestJS, how to configure mongoose?

189 Views Asked by At

I have configured adminJS in nest js and it runs successfully on localhost:5000/admin

    @Module({
  imports: [
    import('@adminjs/nestjs').then(({ AdminModule }) =>
      AdminModule.createAdminAsync({
        useFactory: () => ({
          adminJsOptions: {
            rootPath: '/admin',
            resources: [],
          },
          auth: {
            authenticate,
            cookieName: 'adminjs',
            cookiePassword: 'secret',
          },
          sessionOptions: {
            resave: true,
            saveUninitialized: true,
            secret: 'secret',
          },
        }),
      }),
    ),
   ,
    MongooseModule.forRoot('mongodb://localhost:27017/arm-club-control'),
    UserModule,
  
  ],
})
export class AppModule {}

But I want to add mongoose adapter and in the import part I am having problems with import so in github I found this setting to add mongoose adapter main.ts

import * as process from 'process';
import { HttpAdapterHost, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { json, urlencoded } from 'express';

(async function () {
  const PORT: number = Number(process.env.PORT) || 5000;
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  const AdminJS = await import('adminjs');
  const AdminJSExpress = await import('@adminjs/express');
  const AdminJSMongoose = await import('@adminjs/mongoose');

  const expressApp = app.get(HttpAdapterHost).httpAdapter;
  const admin = new AdminJS.default({});
  expressApp.use(
    admin.options.rootPath,
    AdminJSExpress.default.buildRouter(admin),
    AdminJS.default.registerAdapter({
      Resource: AdminJSMongoose.Resource,
      Database: AdminJSMongoose.Database,
    }),
  );

  app.setGlobalPrefix('api');
  app.enableCors();
  app.use(json({ limit: '50mb' }));
  app.use(urlencoded({ extended: true, limit: '50mb' }));
  const config = new DocumentBuilder()
    .setTitle('ARM CLUB CONTROL')
    .setDescription('This app is build on NEST JS')
    .setVersion('0.0.1')
    .addTag('3aqaryan')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('/api/docs', app, document);
  await app.listen(PORT, '0.0.0.0', () => {
    console.log(`Server is started on ${PORT} port`);
  });
})();

But after adding this on, I get

 AdminJS.default.registerAdapter({
      Resource: AdminJSMongoose.Resource,
      Database: AdminJSMongoose.Database,
    }),

  throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
            ^
TypeError: Router.use() requires a middleware function but got a undefined
    at Function.use (/home/zakaryan6691/Documents/Projects/armclubcontrol/server/node_modules/express/lib/router/index.js:469:13)
    at Function.<anonymous> (/home/zakaryan6691/Documents/Projects/armclubcontrol/server/node_modules/express/lib/application.js:227:21)
    at Array.forEach (<anonymous>)
    at Function.use (/home/zakaryan6691/Documents/Projects/armclubcontrol/server/node_modules/express/lib/application.js:224:7)
    at ExpressAdapter.use (/home/zakaryan6691/Documents/Projects/armclubcontrol/server/node_modules/@nestjs/core/adapters/http-adapter.js:14:30)
    at /home/zakaryan6691/Documents/Projects/armclubcontrol/server/src/main.ts:18:14

How to configure adminJS for User schema?

import * as mongoose from 'mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument, Types } from 'mongoose';
export type UserDocument = HydratedDocument<User>;

@Schema({ timestamps: true })
export class User {
  @Prop()
  name: string;

  @Prop()
  lastname: string;

  @Prop()
  username: string;

  @Prop()
  email: string;

  @Prop()
  password: string;

  @Prop()
  age: number;

  @Prop()
  role: string;

  @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Club' }] })
  clubs: Array<Types.ObjectId>;

  @Prop()
  activated: boolean;

  @Prop()
  otp: number | null;

  @Prop()
  expiresOtpIn: number | null;

  @Prop()
  refreshToken: string;
}

export const UserSchema = SchemaFactory.createForClass(User);

1

There are 1 best solutions below

2
On

From their docs it looks like you shouldn't be calling AdminJS.default.registerAdapter inside of the expressApp.use, as it's not a middleware. Just make sure it's called before the application starts, or follow their docs explicitly, and you should be fine