MongoDB, Mongoose и Apollo GraphQL определяют тип _id в документе - PullRequest
1 голос
/ 09 марта 2019

Я использую TypeScript с NestJS в этом проекте:

https://github.com/EricKit/nest-user-auth

Я пытаюсь добавить свойство _id в схему GraphQL:

type User {
  username: String!
  email: String!
  permissions: [String!]!
  createdAt: Date!
  updatedAt: Date!
  enabled: Boolean!
  _id: String!
}

Теперь NestJS создает файл типа для пользователя из этой схемы

export abstract class User {
    username: string;
    email: string;
    permissions: string[];
    createdAt: Date;
    updatedAt: Date;
    enabled: boolean;
    _id: string;
}

Проблема теперь в том, что я хочу создать интерфейс для UserDocument, который добавляет специфические поля mongoDB и определяет документ

export interface UserDocument extends User, Document {
  // Declaring everything that is not in the GraphQL Schema for a User
  _id: string; // TODO: This should actually be Types.ObjectId
  password: string;
  lowercaseUsername: string;
  lowercaseEmail: string;
  passwordReset?: {
    token: string;
    expiration: Date;
  };

  checkPassword(password: string): Promise<boolean>;
}

Я не могу определить _id как mongoose.Type.ObjectID, потому что он выдает ошибку:

Interface 'UserDocument' incorrectly extends interface 'User'.
  Types of property '_id' are incompatible.
    Type 'ObjectId' is not assignable to type 'string'.

Это имеет смысл, я хотел бы найти способ сохранить его как ObjectId в моей схеме UserDocument, сохранить его в виде строки в схеме и при этом иметь возможность расширять тип схемы GraphQL. Это возможно?

1 Ответ

2 голосов
/ 09 марта 2019

Способ GraphQL - это пользовательский скалярный тип для сериализации / десериализации ObjectId

Схема GraphQL

scalar Date
scalar MongoObjectId
...
type User {
  username: String!
  email: String!
  permissions: [String!]!
  createdAt: Date!
  updatedAt: Date!
  enabled: Boolean!
  _id: MongoObjectId!
}

Скалярный класс MongoObjectId, основанный на Скаляр даты NestJs и Скаляр TypeGraphQL ObjectId

import { Scalar } from '@nestjs/graphql';
import { Kind, ASTNode } from 'graphql';
import { ObjectId } from "mongodb";

@Scalar('MongoObjectId')
export class ObjectIdScalar {
  description = 'Mongo object id scalar type';

  parseValue(value: string) {
    return new ObjectId(value); // value from the client
  }

  serialize(value: ObjectId) {
    return value.toHexString(); // value sent to the client
  }

  parseLiteral(ast: ASTNode) {
    if (ast.kind === Kind.STRING) {
      return new ObjectId(ast.value); // value from the client query
    }
    return null;
  }
}

После этого нам нужно зарегистрировать ObjectIdScalar в качестве провайдера (точно так же как с скаляр даты ) и изменить _id с string на Type.ObjectID.

...