elersong / fireorm24

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

Support Multiple SubCollections of the Same Type #32

Closed elersong closed 1 month ago

elersong commented 2 months ago

Description

Defining multiple subcollections of the same type within a Fireorm model causes an error. While there are workarounds, such as extending the class, this should ideally be supported without errors. The issue seems to stem from the way MetadataStorage.setCollection() evaluates children before parents and updates segments.

Steps to Reproduce

  1. Create a model with multiple subcollections of the same type.
  2. Attempt to use the model in Fireorm.
  3. Observe the error caused by having multiple subcollections of the same type.

Expected Behavior

Fireorm should support multiple subcollections of the same type within a model without causing errors.

Actual Behavior

An error is thrown when defining multiple subcollections of the same type within a model.

Acceptance Criteria

Additional Context

Proposed API Changes

  1. Update MetadataStorage.setCollection:

    • Modify the MetadataStorage.setCollection() method to correctly handle multiple subcollections of the same type.
    class MetadataStorage {
     setCollection(collection: any) {
       // Logic to handle multiple subcollections of the same type
       // Ensure parent and child collections are evaluated and updated correctly
     }
    }
  2. Support Multiple SubCollections:

    • Ensure the model can support multiple subcollections of the same type without errors.
    @Collection()
    class Band {
     id: string;
     name: string;
     @SubCollection(Album, 'albums')
     albums: ISubCollection<Album>;
     @SubCollection(Album, 'singles')
     singles: ISubCollection<Album>;
    }
  3. Unit Tests:

    • Add unit tests to validate the correct handling of multiple subcollections of the same type.
    test('should support multiple subcollections of the same type', () => {
     const bandRepository = getRepository(Band);
     const band = new Band();
     band.id = 'band1';
     band.name = 'Test Band';
    
     const album = new Album();
     album.id = 'album1';
     album.name = 'Test Album';
    
     const single = new Album();
     single.id = 'single1';
     single.name = 'Test Single';
    
     band.albums.create(album);
     band.singles.create(single);
    
     expect(band.albums.findById('album1').name).toBe('Test Album');
     expect(band.singles.findById('single1').name).toBe('Test Single');
    });

Example Implementation

class Album {
  id: string;
  name: string;
}

@Collection()
class Band {
  id: string;
  name: string;
  @SubCollection(Album, 'albums')
  albums: ISubCollection<Album>;
  @SubCollection(Album, 'singles')
  singles: ISubCollection<Album>;
}

const bandRepository = getRepository(Band);

const band = new Band();
band.id = 'band1';
band.name = 'Test Band';

const album = new Album();
album.id = 'album1';
album.name = 'Test Album';

const single = new Album();
single.id = 'single1';
single.name = 'Test Single';

bandRepository.create(band);
band.albums.create(album);
band.singles.create(single);

const fetchedAlbum = band.albums.findById('album1');
const fetchedSingle = band.singles.findById('single1');

console.log(fetchedAlbum.name); // Output: 'Test Album'
console.log(fetchedSingle.name); // Output: 'Test Single'

Original Issue