@nestjs/graphql 不适用于无服务器

@nestjs/graphql not working with serverless

我对 @nestjs/graphqlserverless.

有疑问

当我使用 $ nest start 命令正常启动应用程序时,它运行良好,没有任何错误。 但是使用 $ sls offline 命令,它不是 运行 并且当我转到 /graphql (游乐场)端点时出现此错误:

offline: ANY /graphql (λ: graphql)
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [NestFactory] Starting Nest application...
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] ConfigHostModule dependencies initialized +35ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] JwtModule dependencies initialized +1ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] GraphQLModule dependencies initialized +0ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] GraphQLSchemaBuilderModule dependencies initialized +0ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] GraphQLModule dependencies initialized +1ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] DatabaseModule dependencies initialized +166ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] AuthModule dependencies initialized +2ms
[Nest] 49532  - 04/02/2022, 22:56:30     LOG [InstanceLoader] UsersModule dependencies initialized +1ms
offline: Failure: Cannot determine a GraphQL output type for the "roles". Make sure your class is decorated with an appropriate decorator.

我认为问题出在公开 User(另一个对象类型+实体)的特定对象类型上。

// auth.models.ts
import { User } from '@features/graphql/users/entities';
import { Field, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class SignInUserModel {
  @Field(() => User, { nullable: true })
  user?: User;

  @Field(() => String, { nullable: true })
  accessToken?: string;

  @Field(() => String, { nullable: true })
  refreshToken?: string;
}

因为如果我从 SignInUserModel 中删除 User 字段,问题就会消失...有人知道我需要做什么吗? 我的用户模型中 roles 缺少特定的装饰器或其他东西? 我完全迷路了哈哈

关于我的代码:

// lambda.handler
import { defaultConfig } from '@config';
import { GraphQLModule } from '@features/graphql/graphql.module';
import { Logger, ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import serverlessExpress from '@vendia/serverless-express';
import { Callback, Context, Handler } from 'aws-lambda';

let server: Handler;

async function bootstrap() {
  const config = defaultConfig();

  const app = await NestFactory.create(GraphQLModule);

  // Logger
  if (config.isLoggerEnabled) app.useLogger(app.get(Logger));

  // Validation
  app.useGlobalPipes(new ValidationPipe());

  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress({ app: expressApp });
}

export const handler: Handler = async (
  event: any,
  context: Context,
  callback: Callback,
) => {
  server = server ? server : await bootstrap();
  return server(event, context, callback);
};

// graphql.module.ts
import { ConfigModule, graphqlConfig } from '@config';
import { AppService } from '@features/app.service';
import { UsersModule } from '@features/graphql/users/users.module';
import { AuthModule } from '@features/_auth/auth.module';
import { Module } from '@nestjs/common';
import { GraphQLModule as NESTJSGraphQLModule } from '@nestjs/graphql';

@Module({
  imports: [
    ConfigModule,
    AuthModule,
    NESTJSGraphQLModule.forRoot({
      installSubscriptionHandlers: true,
      autoSchemaFile: graphqlConfig().generatedSchemaFileLocation,
      sortSchema: true,
      debug: graphqlConfig().isDebugEnabled,
      introspection: true,
      context: ({ req }) => ({ headers: req.headers }),
      playground: graphqlConfig().isPlaygroundEnabled
        ? {
            settings: { 'schema.polling.enable': false },
          }
        : false,
    }),
    UsersModule,
  ],
  providers: [AppService],
})
export class GraphQLModule {
  constructor(private readonly appService: AppService) {
    if (!this.appService.checkEnv()) process.exit();
  }
}
// user.entity.ts
import { UserRole } from '@features/graphql/users/users.enums';
import { Field, ObjectType } from '@nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@ObjectType()
@Entity({ name: 'users' })
export class User {
  @PrimaryGeneratedColumn('uuid')
  @Field(() => String)
  id: string;

  @Column('text')
  @Field(() => String)
  firstName: string;

  @Column('text')
  @Field(() => String)
  lastName: string;

  @Column('text')
  @Field(() => String)
  email: string;

  @Column({ type: 'enum', enum: UserRole, array: true, default: ['USER'] })
  @Field(() => [UserRole])
  roles: UserRole[];

  ...
}
// user.enums.ts
export enum UserRole {
  ADMIN = 'ADMIN',
  MODERATOR = 'MODERATOR',
  USER = 'USER',
}
// serverless.ts
import type { AWS } from '@serverless/typescript';
import { config as dotEnvConfig } from 'dotenv';
import * as envVar from 'env-var';
import packageConfig from './package.json';

dotEnvConfig();

const serverlessConfiguration: AWS = {
  service: packageConfig.name,
  useDotenv: true,
  frameworkVersion: '*',
  plugins: {
    modules: [
      'serverless-plugin-optimize',
      'serverless-offline',
      'serverless-plugin-warmup',
    ],
  },
  custom: {
    warmup: {
      default: {
        enabled: true,
      },
    },
    'serverless-offline': {
      noPrependStageInUrl: true,
    },
  },
  provider: {
    name: 'aws',
    lambdaHashingVersion: '20201221',
    runtime: 'nodejs12.x',
    apiGateway: {
      shouldStartNameWithService: true,
    },
    environment: {
      /* ... my envs ... */
    },
  },
  functions: {
    graphql: {
      handler: 'dist/src/features/graphql/_lambda.handler',
      events: [
        {
          http: {
            method: 'ANY',
            path: '/graphql',
          },
        },
      ],
    },
  },
};

module.exports = serverlessConfiguration;

我正在使用软件包:

  "dependencies": {
    "@nestjs/common": "^8.0.0",
    "@nestjs/config": "^1.1.6",
    "@nestjs/core": "^8.0.0",
    "@nestjs/graphql": "^9.1.2",
    "@nestjs/jwt": "^8.0.0",
    "@nestjs/passport": "^8.1.0",
    "@nestjs/platform-express": "^8.0.0",
    "@nestjs/typeorm": "^8.0.3",
    "@vendia/serverless-express": "^4.5.3",
    "apollo-server-express": "^3.6.2",
    "aws-lambda": "^1.0.7",
    "bcryptjs": "^2.4.3",
    "class-validator": "^0.13.2",
    "env-var": "^7.1.1",
    "graphql": "^15",
    "nestjs-pino": "^2.5.0",
    "passport": "^0.5.2",
    "passport-local": "^1.0.0",
    "pg": "^8.7.1",
    "pino-http": "^6.6.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0",
    "typeorm": "^0.2.41"
  },
  "devDependencies": {
    "@faker-js/faker": "^6.0.0-alpha.5",
    "@nestjs/cli": "^8.0.0",
    "@nestjs/schematics": "^8.0.0",
    "@nestjs/testing": "^8.0.0",
    "@serverless/typescript": "^3.0.0",
    "@types/aws-lambda": "^8.10.92",
    "@types/bcryptjs": "^2.4.2",
    "@types/express": "^4.17.13",
    "@types/jest": "27.0.2",
    "@types/node": "^16.0.0",
    "@types/passport-local": "^1.0.34",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "eslint": "^8.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "jest": "^27.2.5",
    "npm-run-all": "^4.1.5",
    "prettier": "^2.3.2",
    "serverless-offline": "^8.4.0",
    "serverless-plugin-optimize": "^4.2.1-rc.1",
    "serverless-plugin-warmup": "^6.2.0",
    "source-map-support": "^0.5.20",
    "supertest": "^6.2.2",
    "ts-jest": "^27.1.3",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsc-alias": "^1.5.0",
    "tsconfig-paths": "^3.12.0",
    "typescript": "^4.3.5"
  }

感谢您的帮助,希望您能找到解决方案:)

根据此页面 https://docs.nestjs.com/graphql/unions-and-enums

枚举需要用函数声明 registerEnumType

registerEnumType(UserRole, {
  name: 'UserRole',
});