elersong / fireorm24

ORM for Firebase Firestore 🔥 updated for 2024
MIT License
1 stars 0 forks source link

Include Firestore Timestamps in Entities #39

Open elersong opened 1 month ago

elersong commented 1 month ago

Description

When using the Firestore admin SDK, we can retrieve document timestamps (createTime, updateTime, readTime). These timestamps are useful for backend applications that utilize Firestore. This proposal suggests including these timestamps in Fireorm entities, allowing users to automatically access them without manual creation.

Steps to Reproduce

  1. Create an entity and save it to Firestore using Fireorm.
  2. Retrieve the entity and attempt to access its timestamps (createTime, updateTime, readTime).

Expected Behavior

Entities should automatically include createTime, updateTime, and readTime properties, populated with the corresponding Firestore document timestamps.

Actual Behavior

Currently, entities do not include these timestamps automatically and require manual creation and management.

Acceptance Criteria

Additional Context

Proposed API Changes

  1. Add Timestamp Properties to Entities:

    • Modify the entity base class to include createTime, updateTime, and readTime properties.
    class BaseEntity {
     id: string;
     createTime?: Date;
     updateTime?: Date;
     readTime?: Date;
    }
  2. Update Repository Methods:

    • Update repository methods to populate these properties from Firestore document metadata.
    class BaseFirestoreRepository<T extends BaseEntity> {
     private extractTFromDocSnap(docSnap: DocumentSnapshot): T {
       const entity = docSnap.data() as T;
       entity.createTime = docSnap.createTime?.toDate();
       entity.updateTime = docSnap.updateTime?.toDate();
       entity.readTime = docSnap.readTime?.toDate();
       return entity;
     }
    
     async findById(id: string): Promise<T | null> {
       const docSnap = await this.firestoreColRef.doc(id).get();
       return docSnap.exists ? this.extractTFromDocSnap(docSnap) : null;
     }
    }
  3. Provide TypeScript Support:

    • Add a Timestamped wrapper to add typing for the new properties.
    export type Timestamped<T> = T & {
     createTime: Date;
     updateTime: Date;
     readTime: Date;
    };
  4. Unit Tests:

    • Add unit tests to validate the inclusion and correctness of the timestamps.
    test('should include Firestore timestamps in entities', async () => {
     const todoRepository = getRepository(Todo);
     const todo = new Todo();
     todo.text = "Check fireorm's Github Repository";
     todo.done = false;
    
     const createdTodo = await todoRepository.create(todo);
     const retrievedTodo = await todoRepository.findById(createdTodo.id);
    
     expect(retrievedTodo).not.toBeNull();
     expect(retrievedTodo.createTime).toBeInstanceOf(Date);
     expect(retrievedTodo.updateTime).toBeInstanceOf(Date);
     expect(retrievedTodo.readTime).toBeInstanceOf(Date);
    });

Example Implementation

import { Collection, getRepository } from 'fireorm';

@Collection()
class Todo extends BaseEntity {
  text: string;
  done: boolean;
}

const todoRepository = getRepository(Todo);

const todo = new Todo();
todo.text = "Check fireorm's Github Repository";
todo.done = false;

const todoDocument = await todoRepository.create(todo); // Create todo

const mySuperTodoDocument = await todoRepository.findById(todoDocument.id); // Read todo. Also retrieves createTime, updateTime and readTime from the Firestore DocumentRef

console.log(mySuperTodoDocument.createTime); // Output: 2022-12-17 00:00:00
console.log(mySuperTodoDocument.updateTime); // Output: 2022-12-17 00:00:00
console.log(mySuperTodoDocument.readTime); // Output: 2022-12-17 00:00:01

Original Issue

elersong commented 1 month ago

Potentially connected to #35