Package Exports
- firelordjs
- firelordjs/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (firelordjs) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme

FirelordJS çç«åJS
FirelordJS is the only library capable of providing insane type safety while exposing almost all the API of the official Firestore SDK. The goal is to end Firestore typing madness.
FirelordJS:
- Has the lowest learning curve (API is nearly identical to the original API).
- Has the lowest technical debt (easy to revert to the official API).
- Offer truly generic type safe solutions.
- Offer effortless solutions for Firestore quirks.
- Is the only library capable of typing against Firestore limitations.
- Has the smallest package size.
- Has no code generation, no schema language, just pure Typescript.
Support @firebase/rules-unit-testing and emulator
I am confident it has the best type safe and nothing come close. I put money on my words and I will buy you x cups of coffee if you:
- found something better: 75 cups
- created something better: 1000 cups (you don't need to a make full fledge library, something that is minimally better is enough, open an issue if you want to take this challenge)
FirelordJS is thoroughly tested, it tests source code, built files and published package.
No mock test, all tests test against real database and emulator to ensure the highest certainty.
More than 250 tests.
Undocumented releases are README updates.
Upcoming V3
Update: Currently Firelord is powerful enough. Therefore, we think it is ok to stay at v2 for now, unless we receive sufficient assistance.
V3 focus on codebase redesign and rewrite with TS 5.0, hopefully with further improved code quality, potential contributors will find it easier to work with.
Code Quality Improvements:
- More extensible and simpler type logics.(to fix noticeable lag performance issue)
- Implement latest TS features.
- Better files and folders structure.
- Remove trivial APIs.
- Less wordy and more concise Documentation.
- All input types be read-only.
- More tests.
Other tasks:
- Enable new undocumented Firestore capability:in and array-contains-any combination query is now possible
- Fix in code documentation not working(alternative solution is available, but this might be TS bug)
V3 New Features
Auto narrow to literal type, remove the need to manually assert as const. Most of this issue was resolved in v2.3.1 (while v2.3.2 resolved accepting const asserted values issues). To solve the rest of the issues, we need TS 5.0 const type parameter.
Narrow read type base on query constraint. For example
where('a', '==', true)
will narrow the read type of fielda
totrue
, it should be able to narrow down complex case likewhere('a.b.c', '==', { d:[{e:1}] })
. Expected to support==
comparator for all types and possibly!=
comparator for literal type(type filtering for!=
comparator poses great complexity hence I may not work on it).Mandatory field update. Example, for field like
updatedAt
, it is mandatory to includes it every time you update the document. There are two ways to implement these feature: via Meta Type and via abstraction. With Meta Type(using special field value), it is less flexible because we no longer able to exclude it from all update operations. With abstraction, it is more flexible but require more works from user. I prefer via abstraction due to it does not shut down other use cases despite having lower user experience.Support tuple data type.
Replace
set merge
withupset
(update if exist, else set). It will receives 1 doc ref argument and 2 data arguments(partial data and complete data). It will attempt to update the document with partial data or create a document with complete data if the document does not exist.
What Will Not Be Implemented
Support for wide numeric key and wide string key (Record<number, unknown> and Record<string, unknown>). It still needs more consideration because this data type is pointless to query(we need to know what the key is first, it would be better to just save the document ID somewhere) and we need to constantly aware of the document size limit. If you don't care about query and you sure that the size limit will not exceed 1 MB, then this is for you. But allowing this also open up for mistake and bad practice for those who are not aware. Most likely I will not implement this but will give it deeper thoughts in the future.
Support for object unions type. Objects unions type seem to be a good type to have in NoSQL database because of how ever-changing NoSQL schema is. However, this is not the case because it brings uncertainty that cannot be handled reasonably. For example, with
{a:number}|{b:string}
, you can set{a:1}
then update{b:"x"}
, in this case the type is no longer unions type but an intersection type:{a:number} & {b:string}
. So I will not implement this feature and will remove it from FireSageJS too. A better way to solve this is to usePossiblyReadAsUndefined
label on newly add field instead(you can also label abandoned fields asPossiblyReadAsUndefined
, but an easier way is to totally ignore them).Support for optional (
?
modifier). Optional is a highly requested feature because of how common it is, however because of how Firestore works: it is impossible to query a missing field. Example: it is impossible to query user that has no phone number if phone number field does not exist. Because of this, it is important to make sure every field exists. You may not need the field now, but you may need it later plus adding default value is simple, especially with such powerful typing library like Firelord. So in order to not accidentally cripple your query in the future, I will not implement this feature. Yes, set merge basically lead to the same problem, hence I encourage you to useupset
instead (will be available in the future).
Possible Architecture Changes in V3
Firelord follows a type-first approach, which means that every entity starts with a type. While this approach has its benefits, it can be seen as objectively inferior to a code-first approach since we can always infer types from code(with code-first approach), but not the other way around(with type-first approach). A good example of this is tools that build on top of zod
, like trpc, which provides both validation and type inference, but this is not possible for Firelord.
Some may question why embedded validation is necessary for databases API, as they are not endpoints(where data validation usually takes place). However, Firestore is a database that directly interacts with clients. Therefore, it is necessary to have validation for triggers, as security rules may not always suffice and do not have type safe.
Type-first approach offers better developer experience, but it cannot do anything at runtime. On the other hand, the code-first approach may require some initial trade-offs in developer experience, but it can be more adaptable in the long term.
Trivial
- The name Firelord is a reference to the Firelord of Avatar.
Contributing
Read here
Related Projects
- Firelord - Typescript wrapper for Firestore Admin
- FireSword - Filter Firestore and RTDB Unknown Keys.
- FireCall - Helper Function to write easier and safer Firebase onCall function.
- FireSageJS - Typescript wrapper for Realtime Database