@simpleclub/firestore-decorators v0.0.10
Firestore decorators for Typescript
Firestore decorators is an provides a convenient method to generating Firestore converters automagically. It can be used with Typescript.
This library currently only supports the admin Firebase SDK.
It is inspired by the Firebase Firestorm library, but less opinionated how you should use the model. It only parses models from Firestore documents to models and nothing more.
Contents
Requirements
Firestore decorators relies on using Typescript's
experimental decorators
for defining your models. Please ensure you have the following in your tsconfig.json
(ES5 is minimum target):
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}Installation
For npm:
$ npm install firebase-decoratorsFor yarn:
$ yarn add firebase-decoratorsUsage
Getting Started
Learn how to set up and us Firestore decorators to auto-generate Firestore converters.
1. Initialize decorators
Call decorators.initialize(firestore, options?) as soon as you initialize
your firestore app. See initialization options
for more information about initializing Firestore decorators.
import * as decorators from 'firestore-decorators';
...
const firestore = firebase.initializeApp(...).firestore();
decorators.initialize(firestore, /* options */);
...2. Defining collection models
Here we have a class representing a posts collection. Entity classes are
typically non-pluralized as they represent a single document from that
collection. To define a collection you must:
- Extend from the
Entityclass. - Annotate your class with
@collection(opts: ICollectionConfig). - Declare a series of fields, annotated with
@field(opts: IFieldConfig).
import { Entity, collection, field } from 'firestore-decorators';
@collection({
path: 'posts',
})
export default class Post extends Entity {
@field({ name: 'title' })
title!: string;
@field({ name: 'content' })
content!: string;
}3. Defining subcollections
Each of your models, whether they represent a root collection or subcollection must extend from the
Entityclass provided.
Now we want documents in the posts collection to have a subcollection
of comments. First, we need to create a class for the comments. We also annotate the class with @collection, ]
but we use placeholders for the post ID.
import { Entity, collection, field } from 'firestore-decorators';
@collection({
path: 'posts/{post}/comments',
})
export default class Comment extends Entity {
@field({ name: 'content' })
content!: string;
@field({ name: 'by' })
by!: string;
}4. Defining document references
Finally, we want documents in the posts collection to reference an author in
an authors collection (another root collection). First, we define the Author entity:
import { Entity, collection, field } from 'firestore-decorators';
@collection({
path: 'authors',
})
export default class Author extends Entity {
@field({ name: 'name' })
name!: string;
}Then we can add an Author reference to the Post entity using the @documentRef(opts: IDocumentRefConfig) decorator:
import {firestore} from 'firebase-admin';
import { Entity, collection, documentRef } from 'firestore-decorators';
import Author from './Author';
@collection({
path: 'posts',
})
export default class Post extends Entity {
@documentRef({
name: 'author',
entity: Author
})
author!: firestore.DocumentReference<Author>;
...
}Custom Data Types
Arrays
Firestore documents can contain arrays of strings, numbers, objects,
etc. Defining arrays in Firestore decorators is as simple as assigning properties
as array types in your Entity files. For example:
class Example extends Entity {
@field({ name: 'example_property_1' })
property1!: string[];
@field({ name: 'example_property_2' })
property2!: firestore.DocumentReference<AnotherEntity>[];
}Nested Data
Firestore documents can contains nested objects (or maps). For a nested
object, you need to create a new class to represent that object, and add
a property with that class in your Entity, wrapped with the @map decorator.
class Example extends Entity {
@map({ name: 'nested_object' })
nestedObject!: Nested;
}
class Nested {
@field({ name: 'nested_property' })
nestedProperty!: string;
}And then to use this entity:
const nested = new Nested();
nested.nestedProperty = 'test';
const example = new Example();
example.nestedObject = nested;Important: If your is nested data is an array you must provide the 'entity' option in the configuration.
class Nested {
@map({ name: 'nested_array', entity: Nested })
nestedObject: Nested[];
}Geopoints
Geopoints store locational data and can be used as fields.
class Example extends Entity {
@geoPoint({
name: 'geopoint_property',
})
geopoint!: firestore.GeoPoint;
} And then to assign a GeoPoint:
const example = new Example();
example.geopoint = new firestore.Geopoint(latitude, longitude);Timestamps
You can represent date & time data in your Entity files.
class Example extends Entity {
@timestamp({
name: 'timestamp_property',
})
timestamp!: firestore.Timestamp;
}Initialization Options
Firestore decorators.intialize({ ...opts : IFireormConfig }) can be called
with the following options:
| Option | Description | Type |
|---|---|---|
fieldConversion | Providing this option will convert Entity propertity names into firestore collection names so you don't need to provide the name option in @field() decorators. To view available values please check out the docs. | enum FieldConversionType |
Development
Setup
- Clone the repo.
- Install dependencies.
cd firestore-decorators
yarn installTesting
The testing script looks for *.spec.ts files in the src
and test directory.
yarn testContributing
Found a bug?
Please report any bugs you have found submitting an issue to our Github repository, after ensuring the issue doesn't already exist. Alternatively, you can make a pull request with a fix.
Pull Requests
If you would like to help add or a feature or fix a bug, you can do so by making a pull request. The project uses Conventional Commits, so please make sure you follow the spec when making PRs. You must also include relevant tests.
License
Contributing
If you wish to contribute a change in this repo, please review our contribution guide, and send a pull request.