Flame is a data model and query library for Firestore.
Firestore is a fully managed, internet scale document database offered by Google. Flame was designed to improve clarity and accuracy of Firestore related data model and query code.
Among other features, Flame makes it easy to define models, write queries and transactions, and page data with cursor based paging. As a bonus, (compared to using firestore-admin directly) using Flame will greatly reduce the amount code in API endpoints and Lambda functions that interact with Firestore.
If you have any ± feedback, feature requests, or bug reports, please open an issue on Github.
Install flame-odm
using yarn
or npm
.
At this time, Flame targets node.js and will not work in the browser.
Note: Flame works alongside existing installations of firebase-admin in your project.
The connection to Firestore is defined as part of an Adapter
. If you are using Firebase Functions, Flame's default Adapter
will connect automatically. The following example shows how to define the connection manually using a service account.
Note: Flame doesn't immediately create a database connection. When queries are run, the Adapter lazily connects to Firestore as needed.
Let's create our first Model
using the Adapter
we just defined.
Now, we can use our User Model
to create a Record
.
Then, we can save the Record
we just created as a document to Firestore.
Finally, we can execute a Query
to retrieve the document saved in Firestore.
Create an Access
that can be used to screen Object
s using a role-basd mask.
Object
that mirrors defaults
on the target Model
, where the value of each field is an Array
of roles allowed to access the given field.Access
.
List the fields allowed by an Access
, given one or more roles
.
Creates a copy of obj including only role-allowed fields.
Create an Adapter
which can be used as a mixin
when creating a Model
or Record
.
When service_account
is 'firebase-function'
or 'google-cloud'
the service account will be retrieved automatically from the respective platform.
When service_account
is 'process-env'
Flame will look for the service account as a JSON string stored at process.env.FB_SERVICE_ACCOUNT
.
When service_account
is an Object
, Flame assumes the Object
is the service account.
When service_account
is a Function
, Flame will invoke service_account()
, which should return a Promise
that resolves to a service account Object
.
When unspecified, Flame will default to using 'firebase-function'
.
Note: If you are using Flame in a Firebase Function, you do not need to define or use an Adapter
. Flame will automatically use the default Adapter
and connect as needed.
Create multiple Adapter
s with different app_name
s to connect to multiple Firestore databases.
If service_account
is: 'google-cloud'
, 'firebase-function'
, or null
then app_name
is ignored.
Adapter
.
Avoid calling Adapter.connect()
directly, it is invoked automatically by Adapter
, Model
, and Record
methods as needed.
Connect to Firestore.
Executes a set of database operations as a transaction.
The argument fn
is a Function invoked with one argument: T (Transaction)
which may be passed to any read or write methods carried out within the context of Adatper.transact
.
fn
.
Create a Config
which is used to store and pass configuration options to other constructors.
Object
of { field: value, ...}
entries allowed by the constructor or method that will recieve Config
.Config
.
Create a Model
. A Model
defines the structure of the documents to be stored in Firestore.
This Model
's type.
By default, type
will be the collection in Firestore for documents saved by Record
s created from this Model
. However, the collection can be overriden with a custom Config
.
The structure of your Model defined by an Object
of {field: value, ...}
entries, where value
can be any of: Array
, Boolean
, Number
, Null
, Object
, String
, or Function
.
When value
is a Function
, it will be invoked with two arguments: type
and values
where type
is the Model
's type
and values
is a clone of defaults
.
Model
's constructor of (Type)
, the Model
's corresponding default (Type)
will be overridden.Model
.
Count the number of documents in a collection that satisfy query
.
Query
that determines what to count. If query
is not specified, all documents in the collection are counted.Promise
that resolves to the Integer
number of documents in the collection that satisfy query
, or Null
if Model.count()
fails.
Create a new Record
.
Object
of the values
for Record
. values
will be merged with the Model
's defaults
.Model.create()
of (Type)
, the created Record
's corresponding default (Type)
will be overridden.Record
.
Extend a Model
.
This Model
's type.
By default type
will be the collection used in Firestore when saving a Record
. However, the collection can be overriden with a custom Config
.
The structure of your Model
defined by an Object
of {field: value, ...}
entries, where value
can be any of: Array
, Boolean
, Number
, Null
, Object
, String
, or Function
. defaults
will be merged with the extended Model
's defaults
.
When value
is a Function
, it will be invoked with two arguments: type
and values
where type
is the Model
's type
and values
is a clone of defaults
.
Model
's constructor of (Type)
, the Model
's corresponding default (Type)
will be overridden.Model
.
Retrieve the first document in a collection that satisfies query
.
Query
that determines what documents are elliglbe. If query
is not specified, the first document in the collection is returnedObject
. Use when invoking Model.find()
within the context of Adapter.transact()
.Object
, or Null
if there is no match.
Retrieve all documents in a collection that satisfy query
.
Query
that determines what documents will be included. If query
is not specified, all documents in the collection will be included.Object
. Use when invoking Model.findAll()
within the context of Adapter.transact()
.Null
if there are no matches.
Create a partial Record
using an existing document ID.
Object
of the values
for Record
. values
will be merged with the Model
's defaults
.Model.fragment()
of (Type)
, the created Record
's corresponding default (Type)
will be overridden.Record
.
Retrieve a single document from a collection.
Object
. Use when invoking Model.get()
within the context of Adapter.transact()
.Record
Object
, or Null
if there is no document with the given id
.
Retreive multiple documents from a collection.
Object
. Use when invoking Model.getAll()
within the context of Adapter.transact()
.Array
of the document Objects
, or Null
if any of the provided ids
do not correspond to a document in Firestore.
Retrieve a page of documents from a collection.
Pager
to use.An Object
that defines the current cursor and it's position.
When unspecified or Null
, cursor
defaults to the first document in the collection that satisfies pager
.
Object
. Use when invoking Model.getAll()
within the context of Adapter.transact()
.Object
, or Null
if there are no documents that satisfy the supplied pager
and cursor
.
Traverse all documents in a collection that satisify the constraints of pager
. fn
is invoked once with each record as its first argument.
The Pager
to use. When Pager
is initalized with { size: 1 }
, each invocation of fn
will be in serial. Otherwise, fn
will be invoked on all records in a given page in parallel.
Use size
as a rate-limiter to ensure Model.traverse()
doesn't exceed read or write limits.
An Object
that defines the current cursor and it's position.
When unspecified or Null
, the cursor defaults to the first document in the collection that satisfies pager
.
Object
, or Null
if there are no documents that satisfy the supplied pager
.
Creates a Pager
that can be used to in combination with Model.page()
to retrieve cursor-based pages from a collection in Firestore.
An Array
of constraint tuples that defines what documents are included when retrieving a page using this Pager
in combination with Model.page()
. Each constraint tuple is represented using an Array
in the form [constraint, field, value(s)]
.
The allowed constraint tuples are:
Constraint Tuples | ||
---|---|---|
'and' | One or more 'and', 'or, 'eq', 'eq-any', 'gt', 'gte', 'includes', 'includes-any', 'lt', 'lte', 'not-eq', 'not-eq-any' constraint tuples. | |
'or' | One or more 'and', 'or, 'eq', 'eq-any', 'gt', 'gte', 'includes', 'includes-any', 'lt', 'lte', 'not-eq', 'not-eq-any' constraint tuples. | |
'eq' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'eq-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'gt' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'gte' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'includes' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'includes-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'lt' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'lte' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'not-eq' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'not-eq-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'order-by' | field (String) | value (String) |
Object
of the form { size: value (Integer) }
where value
is the number of documents per page.Pager
.
Create a Query
that can be used with Model.count()
, Model.find()
, and Model.findAll()
to count and retrieve documents from Firestore.
An Array
of constraint tuples that defines what documents are included when using this Query
in combination with Model.count()
, Model.find()
, or Model.findAll()
. Each constraint tuple is represented using an Array
in the form [constraint, field, value(s)]
or [constraint, value(s)]
.
The allowed constraint tuples are:
Constraint Tuples | ||
---|---|---|
'and' | One or more 'and', 'or, 'eq', 'eq-any', 'gt', 'gte', 'includes', 'includes-any', 'lt', 'lte', 'not-eq', 'not-eq-any' constraint tuples. | |
'or' | One or more 'and', 'or, 'eq', 'eq-any', 'gt', 'gte', 'includes', 'includes-any', 'lt', 'lte', 'not-eq', 'not-eq-any' constraint tuples. | |
'eq' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'eq-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'gt' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'gte' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'includes' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'includes-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'limit' | value (Integer) | |
'lt' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'lte' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'not-eq' | field (String) | value (Array|Boolean|Number|Null|Object|String) |
'not-eq-any' | field (String) | values (Array<Array|Boolean|Number|Null|Object|String>) |
'order-by' | field (String) | value (String) |
'start-at' | value (Array<Strings>) |
Query
.
Permanently removes the document represented by this Record
from Firestore.
Object
. Use when invoking Record.destroy()
within the context of Adapter.transact()
.true
if successful, otherwise false
.
Produces an Object
of the Record
's fields that are not valid.
Array
of fields to validate. When unspecified or Null
, all fields are validated.Object
in the form of { field: value (Boolean), ... }
where each field
is a field in the Record
, and each value
is true
if the field
fails this Record
's corresponding Validator
function.
Produces the Object
representation of this Record
's fields and values.
Record
's as an Object
.
Check if all fields
of the Record
are valid.
Null
all fields are checked.true
if all fields are valid, otherwise false
.
Save this Record
to Firestore as a document.
Object
. Use when invoking Record.save()
within the context of Adapter.transact()
.true
when successful, otherwise false
.
Update this Record
's corresponding document in Firestore.
Record
's document in Firestore.Object
. Use when invoking Record.update()
within the context of Adapter.transact()
.true
when successful, otherwise false
.
Create a Serializer
that can be used to transform Record
Object
format into a Firestore document Object
format, and vice-a-versa.
opts
is an Object
with three allowed fields: prefixes
, separator
, and fmt
.
prefixes
is an Array
of prefixes that can be used to create 2-level Record
s that will be automatically flattened by Flame as they are written to Firestore, and documents retrieved from Firestore will automatically be expanded back into 2-level Objects
.
separator
is used as field concatenator between the prefixes
and the 2nd-level field names for 2-level Record
s stored in Firestore.
fmt
normalizes the casing for field names when in Firestore, and as Objects
. Snake, kebabk, pascal, and camel cases are supported.
Serializer
.
Create a Validator
that can be used to check if a Record
's fields are valid.
An Object
of the form { field: validator }
that mirrors the structure of the target Model
, where the validator of each field is a Function
.
Each validator
is invoked with two arguments, value
and object
. value
is the Record
's corresponding field
value, and object
is the full Object
representation of the Record
.
Each validator
should evaluate true
if valid, false
otherwise.
Validator
.