ravendb / ravendb-nodejs-client

RavenDB node.js client
MIT License
63 stars 32 forks source link

Documents are saved into @empty collection #414

Closed zaksnet closed 5 months ago

zaksnet commented 5 months ago

I am trying to build an adapter for Lucia but the DatabaseSession object is saved in the @empty collection.

public async setSession(databaseSession: DatabaseSession): Promise<void> {
      const session = documentStore.openSession();
      await session.store(databaseSession);
      await session.saveChanges();
}

I also saw this issue but i am already passing the object directly without explicitly defining an id. It is worth noting that the DatabaseSession interface is part of an external library and i have no control over it.

export interface DatabaseSession {
    userId: string;
    expiresAt: Date;
    id: string;
    attributes: RegisteredDatabaseSessionAttributes;
}

At first i though this might be due to the id being generated by Lucia instead of being null, but when i tried this:

public async setSession(databaseSession: DatabaseSession): Promise<void> {
    (databaseSession as any).id = null;
    const session = documentStore.openSession();
    await session.store<DatabaseSession>(databaseSession);
    await session.saveChanges();
}

I still received the same result (I also checked in the debugger to see if the id is null, and it was.).

EDIT: This Worked. The session is saved in RavenDbDatabaseSession collection :

public async setSession(databaseSession: DatabaseSession): Promise<void> {
      var newSession = new RavenDbDatabaseSession(null, databaseSession.userId, databaseSession.expiresAt, databaseSession.attributes);
      const session = documentStore.openSession();
      await session.store(newSession);
      await session.saveChanges();
}

class RavenDbDatabaseSession {
    constructor(
          id: string | null,
          userId: string,
          expiresAt: Date,
          attributes: RegisteredDatabaseSessionAttributes
) {
      Object.assign(this, {
          id,
          userId,
          expiresAt,
          attributes
      });
    }
}

EDIT 2: That seemed to work:

public async setSession(databaseSession: DatabaseSession): Promise<void> {
      const session = documentStore.openSession();
      (databaseSession as any)['@metadata'] = { "@collection": 'Sessions' };
      await session.store<DatabaseSession>(databaseSession);
      await session.saveChanges();
}
ayende commented 5 months ago

In JS, this is how we detect your entity collection: https://github.com/ravendb/ravendb-nodejs-client/blob/v5.4/src/Documents/Conventions/DocumentConventions.ts#L658

Basically, if you don't have a constructor field (which JS provides for classes), you need to use the findCollectionNameForObjectLiteral on the conventions to figure out what the type is.

ml054 commented 5 months ago

Also this might be helpful: https://github.com/ravendb/ravendb-nodejs-client?tab=readme-ov-file#using-object-literals-for-entities

zaksnet commented 5 months ago

Thanks!