I'm working with TypeGoose right now. When I do
const testData= {
"title": "Test Game 1",
"scenes": [
{
"sceneName": "Northern Milestone",
"dmNotes": [
{
"content": "A crossroads where an path branches off towards a town with hostels. Much of the game's map can be seen with limited detail from the great plateau this crossroads sits atop."
}
],
"characters": [
{
"characterName": "Ian",
"isPlayerCharacter": true,
},
{
"characterName": "Wanderful"
}
]
},
{
"sceneName": "North Woods",
"characters": [],
"dmNotes": [
{
"content": "A thick woods, perceptive characters may smell faint smoke."
}
]
}
],
"items": []
}
mongoose.set("debug", true);
await GameModel.create(testData);
I get the database call:
Mongoose: games.insertOne({ title: 'Test Game 1', templateChildren: [], scenes: [ { _id: ObjectId("64efc2a0eb4110d73787c7ff") }, { _id: ObjectId("64efc2a0eb4110d73787c800") } ], items: [], _id: ObjectId("64efc2a0eb4110d73787c7fe"), __v: 0}, {})
Why are the scenes being turned into ObjectId?
Here's my schemas:
export class Character {
@prop({required: true, default: false})
isPlayerCharacter!: boolean;
@prop({required: true, default: 'Unnamed Character'})
characterName!: string;
@prop({required: true, default: false})
template!: boolean;
@prop({type: () => [DMNote], default: []})
dmNotes!: DMNote[];
@prop({required: true, default: new Stats()})
stats!: Stats;
@prop({required: true, default: new SkillStats()})
skills!: SkillStats;
@prop({type: () => [Item], default: []})
items!: Item[];
@prop({required: true, default: 0})
sceneId!: number;
@prop({required: true, default: 0})
skillStatsId!: number;
@prop({ref: () => User, required: false})
player?: Ref<User>;
}
export class SceneClass {
@prop({required: true, default: 'Unnamed Scene'})
sceneName!: string;
@prop({required: true, default: false})
template!: boolean;
@prop({type: () => [Character], default: []})
characters!: Character[];
@prop({type: () => [DMNote], default: []})
dmNotes!: DMNote[];
@prop({type: () => [Item], default: []})
items!: Item[];
}
export class Game {
@prop()
title?: string;
@prop()
isTemplate!: boolean;
@prop({ref: () => Game})
templateChildren?: Ref<Game>[];
@prop({ref: () => Game})
templateParent?: Ref<Game>;
@prop({type: () => [SceneClass], required: true, default: []})
scenes!: SceneClass[];
@prop({type: () => [Item]})
items: Item[] = [];
@prop({ref: () => User})
owner?: Ref<User>;
public getCharacters(this: DocumentType<Game>) {
return this.scenes.map((scene) => scene.characters || []).flat();
}
public findCharacterByName(this: DocumentType<Game>, characterName: string) {
return this.getCharacters().find((character) => character.characterName === characterName);
}
public async getUsersCharacterInThisGame(this: DocumentType<Game>, user: DocumentType<User>) {
return this.getCharacters().find((character) => character.player?._id.toHexString() === user._id.toHexString());
}
public async getSceneWithUser(this: DocumentType<Game>, user: DocumentType<User>) {
const playedCharacter = await this.getUsersCharacterInThisGame(user);
if (!playedCharacter) return undefined;
return this.scenes.find((scene) => scene.characters.find((character) => character.characterName === playedCharacter.characterName))
}
}
export class User {
@prop({required: true, default: '', unique: true})
userName!: String;
@prop({type: () => [MessageClass], required: true, default: []})
sentMessages?: MessageClass[];
@prop({type: () => [MessageClass], required: true, default: []})
receivedMessages!: MessageClass[];
}
That's not the whole datamodel, but it's what looked immediately relevant. Let me know if you need anything else defined before we discuss.
When you use
type: () => [SceneClass]with Typegoose, it's going to cast the provided value.And since your class has not constructor, it will not pickup any properties. You will be left with empty object with only
_idin them.You should add a constructor:
and create new Objects in your
testData:(not sure you need the second part in your case, I can't try it right now)