All that was missing was an ORM. Annotation-based, no less. Java devs have made very painful experiences with those. For good reasons (that are easy to google)
What you gained was giving a type name to a collection of attributes and describing relationships between them.
What you lost was the ability to treat the data coming from the database as - well - data.
You just put it into a straight jacket (classes).
Your saving grace is a `toData()` function ;)
Such ORMs pretend that data are objects in OOP sense, with internal mutable state stored in their fields. This leads to endless bugs with dirty vs clean state, complicated and bug-prone logic in `.save` methods, hard to debug performance problems with transparent lazy-loading of related objects, and inevitable performance loss on hydration / dehydration of all fields. (I saw and fought this all in practice.)
Better approaches, such as the one available in SQL Alchemy, do not hide the relational nature of the data. They allow to `select` arbitrary tuples, and, most importantly, to build queries from composable, reusable parts.
ORM is not the best interface to an RDBMS. But a good, ergonomic interface to an RDBMS is a very important and useful thing.
IMO it fits realy well into the whole TypeScript cosmos and to be honest I'm quite happy with my straight jacket.
There is a huge downside though, this ORM doesn't implement any of the real-time features which makes Firestore so appealing in the first place. Snapshot changes is one of the best things about Firestore, allowing realtime database updates to appear on the client. By not using this feature this becomes indistinguishable from any other database backend...
There's also a major limitation without using Batched transactions. As Firestore limits you to 500 updates per request, which comes up pretty fast in a lot of systems.
Sorry to be so critical, genuinely like the efforts made, just thought I'd mention why those features are important.
Realtime updates have been implemented in the latest version. Unfortunately no work has done on batched transactions, but I plan to add the feature when I have some spare time.
This is the nomenclatural equivalent of code golf. If someone bragged that they overlapped two constants to save 3 bytes, I would not consider that an improvement. Whatever happened to the belief that communication was more important than brevity?
Some teams even test their user interfaces with users. Names are part of the user interface, yet I've never heard of anyone in software testing a name.
I love me a good ORM, though I know many people are not fans. However, having to annotate every member with what almost seems like a duplicate statement seems like a painful way to define an ORM. Before seeing this project I had been under the erroneous assumption that Typescript would somehow provide class introspection, e.g., allow one to 'collect' all defined member variables of a class, but it seems  that it does not. I think I've been spoiled by Python.
If I ever try Firebase it will be nice to have this.
Code looks nice! Except like sibling commenter I'm not sure what good typing/programming would look like if doing an ORM in TS.
It's my first time hearing about Firestore by the way. My understanding is Firebase has a real time store, but Firestore is a different tool, similar to MongoDB?
Link to Firestore: https://firebase.google.com/docs/firestore
A lot to ask for but where is that? Protobuf is a great great technology for data transmission, something google uses heavily especially for firestore but it would be great to bring more visibility into that versus hiding it away.
I think this is actually pretty cool. I will probably give it a go next time I work with Firestore.
I just looked at this and the fact that it doesn't support transactions is a major dealbreaker. So you do an update on two entities and one fails because of some random network error, now your database is left in an inconsistent state. Not good. Any ORM should, from the start, be written around transactions.
The other issue here is how the tests are written. I appreciate tests, but in this case, they are written agains the client sdk, not the admin sdk. I discovered a huge inconsistency between the two API's that I just filed an issue for... which this project doesn't hit, because it doesn't use transactions...