lukeautry / tsoa

Build OpenAPI-compliant REST APIs using TypeScript and Node
MIT License
3.48k stars 498 forks source link

Populate causes error log: Debug Failure. False expression: Node must have a real position for this operation #1599

Closed yalcinozer closed 6 months ago

yalcinozer commented 6 months ago

I have a students field and it is an object of arrays. One of the field is ObjectId and referenced to another collection. The endpoint populates and returns the data even if command line logs error. And this behaviour is not exclusive to this model, happens in others if they have some structure. I am open to take any support If I am making mistakes. Thanks.

Sorting

Expected Behavior

It shouldn't log any errors.


// MODEL
import mongoose, { Schema } from 'mongoose';

const LocalSchema = new mongoose.Schema({
  student: { type: Schema.Types.ObjectId, ref: "Student" },
  attendance: {
    type: [Boolean],
    default: [false, false, false, false, false]
  }
}, { _id: false })

const classroomSchema = new mongoose.Schema(
  {
    teacher: { type: Schema.Types.ObjectId, ref: "Teacher" },
    students: [LocalSchema],
    start: Date,
    end: Date,
    city: { type: String, enum: ["izmir", "istanbul"] },
    level: {
      type: String,
      enum: ["beginner", "elementary", "upper-elementary", "lower-intermediate", "lower-intermediate", "intermediate", "advanced"]
    },
    quota: Number,
  }, { timestamps: true });

// After adding this hook, ClassroomModel.find() runs without errors 
// classroomSchema.pre('find', function (next) {
//   this.populate([
//     { path: 'students', populate: "student" },
//     { path: "teacher" }
//   ]);
//   next();
// });
const ClassroomModel = mongoose.model<Classroom & mongoose.Document>('Classroom', classroomSchema);

// CONTROLLER
  @Security("jwt", ["admin", "student", "teacher"])
  @Get("")
  public async getClassrooms(@Request() request) {
    return ClassroomModel.find().populate([
      { path: "students", populate: "student" },
      { path: "teacher" }
    ]) // adding .lean() solves the issue
  }

Current Behavior

There was a problem resolving type of 'Omit<any, any>'.
[1] Generate routes error.
[1]  Error: Debug Failure. False expression: Node must have a real position for this operation
[1]     at NodeObject.assertHasRealPosition (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/node_modules/typescript/lib/typescript.js:168209:22)
[1]     at NodeObject.getText (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/node_modules/typescript/lib/typescript.js:168243:18)
[1]     at /Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:695:103
[1]     at Array.reduce (<anonymous>)
[1]     at TypeResolver.contextualizedName (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:693:45)
[1]     at TypeResolver.getReferenceType (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:578:27)
[1]     at TypeResolver.resolve (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:390:36)
[1]     at TypeResolver.getTypeAliasReference (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:628:143)
[1]     at TypeResolver.getReferenceType (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:597:38)
[1]     at TypeResolver.resolve (/Users/realite/programming/node/royal-turkish-server/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:390:36)

Possible Solution

I realised error logs disappears if I do one of two things below:

Context (Environment)

Version of the library: 5.1.1 Version of NodeJS: v18.17.0

jackey8616 commented 6 months ago

@yalcinozer TL;DR using lean is a good solution, and should be use like this at least. otherwise you can wrap the data into a interface to explicitly defines the return type.

If you did not to do so. tsoa will try to infer the type by resolving object gives after return.

In your case, after query the schema, the return type would be mongoose.Document, which contains the type Omit<any, any> that tsoa cannot resolve causing this error.

With lean() function, mongoose will transform the Document object to plain object, which tsoa can resolve it.

About Omit<any, any>, in actually can consider as an issue, but currently I think its not causing people bothering , YET. Directly return the database object is not a prefer, wrapping data into concrete interface is the responsibility of developers using tsoa.

jackey8616 commented 6 months ago

@yalcinozer If there is no more concerns, Can you close this issue? thx.

yalcinozer commented 6 months ago

Of course. I am not too familiar with the process, was expecting you might do it, thanks. It resolved for now.