{"id":22662726,"url":"https://github.com/ngxs-labs/firestore-plugin","last_synced_at":"2026-01-18T07:45:37.505Z","repository":{"id":37874646,"uuid":"226566256","full_name":"ngxs-labs/firestore-plugin","owner":"ngxs-labs","description":"Firestore plugin for NGXS","archived":false,"fork":false,"pushed_at":"2025-11-10T13:49:50.000Z","size":5115,"stargazers_count":20,"open_issues_count":4,"forks_count":14,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-11-27T15:20:53.468Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://ngxs-firebase-plugin.netlify.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ngxs-labs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-12-07T19:36:07.000Z","updated_at":"2025-11-10T13:49:55.000Z","dependencies_parsed_at":"2024-04-15T15:12:20.888Z","dependency_job_id":"b73887ab-8044-4656-833a-e5013a6bee65","html_url":"https://github.com/ngxs-labs/firestore-plugin","commit_stats":{"total_commits":368,"total_committers":7,"mean_commits":52.57142857142857,"dds":0.04619565217391308,"last_synced_commit":"0fcf11021c5d8942e98b2a09d008a27488ed19cc"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ngxs-labs/firestore-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngxs-labs%2Ffirestore-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngxs-labs%2Ffirestore-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngxs-labs%2Ffirestore-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngxs-labs%2Ffirestore-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngxs-labs","download_url":"https://codeload.github.com/ngxs-labs/firestore-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngxs-labs%2Ffirestore-plugin/sbom","scorecard":{"id":683714,"data":{"date":"2025-08-11","repo":{"name":"github.com/ngxs-labs/firestore-plugin","commit":"11c3620dffb215279816b5c54d3f4de503a4042c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/master.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/master.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/ngxs-labs/firestore-plugin/master.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/master.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/ngxs-labs/firestore-plugin/master.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/master.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/ngxs-labs/firestore-plugin/master.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/master.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/ngxs-labs/firestore-plugin/master.yml/master?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 16 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"37 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-c75v-2vq8-878f","Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-c7qv-q95q-8v27","Warn: Project is vulnerable to: GHSA-4www-5p9h-95mh","Warn: Project is vulnerable to: GHSA-9gqv-wp59-fq42","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-9qxr-qj54-h672","Warn: Project is vulnerable to: GHSA-m4v8-wqvr-p9f7","Warn: Project is vulnerable to: GHSA-c76h-2ccp-4975","Warn: Project is vulnerable to: GHSA-cxrh-j4jr-qwg3","Warn: Project is vulnerable to: GHSA-3g92-w8c5-73pq","Warn: Project is vulnerable to: GHSA-64vr-g452-qvp3","Warn: Project is vulnerable to: GHSA-9cwx-2883-4wfx","Warn: Project is vulnerable to: GHSA-vg6x-rcgg-rjx6","Warn: Project is vulnerable to: GHSA-x574-m823-4x7w","Warn: Project is vulnerable to: GHSA-4r4m-qw57-chr8","Warn: Project is vulnerable to: GHSA-xcj6-pq6g-qj4x","Warn: Project is vulnerable to: GHSA-356w-63v5-8wf4","Warn: Project is vulnerable to: GHSA-859w-5945-r5v3","Warn: Project is vulnerable to: GHSA-4vvj-4cpr-p986","Warn: Project is vulnerable to: GHSA-4v9v-hfq4-rm2v","Warn: Project is vulnerable to: GHSA-9jgg-88mc-972h","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T00:00:04.936Z","repository_id":37874646,"created_at":"2025-08-22T00:00:04.936Z","updated_at":"2025-08-22T00:00:04.936Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28533172,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-09T12:02:03.202Z","updated_at":"2026-01-18T07:45:37.479Z","avatar_url":"https://github.com/ngxs-labs.png","language":"TypeScript","funding_links":[],"categories":["State Management"],"sub_categories":["NGXS"],"readme":"![master](https://github.com/ngxs-labs/firestore-plugin/workflows/master/badge.svg?branch=master)\n[![npm version](https://badge.fury.io/js/%40ngxs-labs%2Ffirestore-plugin.svg)](https://badge.fury.io/js/%40ngxs-labs%2Ffirestore-plugin)\n[![Coverage Status](https://coveralls.io/repos/github/ngxs-labs/firestore-plugin/badge.svg?branch=master)](https://coveralls.io/github/ngxs-labs/firestore-plugin?branch=master)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/ngxs-labs/emitter/master/docs/assets/logo.png\"\u003e\n\u003c/p\u003e\n\n---\n\n# NGXS Firestore\n\n## Compatibility\n\nWe've introduced a breaking change in order to support firebase v9. You can find detailed compatibility between\n@angular/fire, angular and firebase [here](https://github.com/angular/angularfire/blob/master/README.md)\n\n| Angular | Firebase | AngularFire                                                                   | @ngxs-labs/firestore-plugin |\n| ------- | -------- | ----------------------------------------------------------------------------- | --------------------------- |\n| \u003e=12    | 9        | [\u003e=7.0](https://github.com/angular/angularfire#angular-and-firebase-versions) | 1.2.x                       |\n| 11      | 8        | 6                                                                             | 0.x                         |\n\nIf you are using Firebase modular version check [here](docs/FIREBASE_MODULAR.md).\n\n## Demo\n\n- [Demo](https://ngxs-firebase-plugin.netlify.com/)\n\n## Resources\n\n- [ngHouston - Firebase + NGXS, the perfect couple](https://www.youtube.com/watch?v=_V_8K_dbb0g\u0026t=1697s)\n- [indepth - Firebase + NGXS, the perfect couple](https://indepth.dev/posts/1322/firebase-ngxs-the-perfect-couple)\n- [Adventures in Angular - Matchmaking NGXS and Firebase with Joaquin Cid ](https://open.spotify.com/episode/6r1j1QxEhcb4MeQg4RL7Yc?si=qBv_n7EbQ9-yodAvqukePQ\u0026dl_branch=1)\n\n## Description\n\nNGXS Firestore plugin helps you integrate Firestore and NGXS. It uses `@angular/fire` under the hood and provides a\nwrapper service with CRUD operations methods and easy integration with NGXS actions. In addition provides tracking of\nactive connections.\n\n![debug](https://raw.githubusercontent.com/ngxs-labs/firebase-plugin/master/docs/assets/readme_debug_data.png)\n\n## Quick start\n\nInstall the plugin:\n\n- npm\n\n```console\nnpm install --save @ngxs-labs/firestore-plugin\n```\n\n- yarn\n\n```console\nyarn add @ngxs-labs/firestore-plugin\n```\n\nIn your `app.module.ts` include the plugin, you will also need to include `@angular/fire` and `NgxsModule`, as they are\npeer dependencies for the plugin. Make sure also you have installed `firebase` library as well.\n\n### Firebase (Modular)\n\n```ts\nimport { NgxsModule } from '@ngxs/store';\nimport { NgxsFirestoreModule } from '@ngxs-labs/firestore-plugin';\nimport { provideFirebaseApp, getApp, initializeApp } from '@angular/fire/app';\nimport { getFirestore, provideFirestore } from '@angular/fire/firestore';\n\n@NgModule({\n  imports: [\n    provideFirebaseApp(() =\u003e initializeApp({ ... })),\n    provideFirestore(() =\u003e getFirestore()),\n    NgxsModule.forRoot(),\n    NgxsFirestoreModule.forRoot()\n  ],\n  ...\n})\nexport class AppModule { }\n```\n\n### Firebase (Compat)\n\n```ts\n//...\nimport { NgxsModule } from '@ngxs/store';\nimport { NgxsFirestoreModule } from '@ngxs-labs/firestore-plugin/compat';\nimport { AngularFireModule } from '@angular/fire/compat';\nimport { AngularFirestoreModule } from '@angular/fire/compat/firestore';\n\n@NgModule({\n  declarations: [AppComponent, ListComponent],\n  imports: [\n    //...\n    AngularFireModule.initializeApp(environment.firebase),\n    AngularFirestoreModule,\n    NgxsModule.forRoot(),\n    NgxsFirestoreModule.forRoot()\n  ]\n  //...\n})\nexport class AppModule {}\n```\n\nNext create a service (i.e `races.firestore.ts`) to execute Firestore operations. This service extends `NgxsFirestore`,\na generic service that takes type `\u003cT\u003e` of the Firestore document. We also need to provide the `path` of the Firestore\ncollection.\n\n```ts\n//...\nimport { NgxsFirestore } from '@ngxs-labs/firestore-plugin';\n// or if you are using firebase compat\nimport { NgxsFirestore } from '@ngxs-labs/firestore-plugin/compat';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class RacesFirestore extends NgxsFirestore\u003cRace\u003e {\n  protected path = 'races';\n}\n```\n\nFinally we create the `@State`. The state will contain actions to execute the Firestore CRUD operations via the service\ncreated previously. When getting data from Firestore, we have two options:\n\n- Get data once\n- Connect to a document or collection stream and receive changes as they occur on the Firestore server.\n\n### Connect and get data once\n\nFor the first scenario, `NgxsFirestore` provides the methods `docOnce$()` and `collectionOnce$()`, which will get the\nfirst emission and unsubscribe immediately after. NGXS handles subscribing to the `Observable` and the action is done\nonce the first data is emmited.\n\n```ts\nexport class GetAllOnce {\n  public static readonly type = '[Races] GetAllOnce';\n}\n\n@State\u003cRacesStateModel\u003e({\n  name: 'races',\n  defaults: {\n    races: []\n  }\n})\nexport class RacesState {\n  constructor(private racesFS: RacesFirestore) {}\n\n  @Action(GetAllOnce)\n  getAllOnce({ getState, patchState }: StateContext\u003cRacesStateModel\u003e) {\n    return this.racesFS.collectionOnce$().pipe(\n      tap((races) =\u003e {\n        patchState({ races: races });\n      })\n    );\n  }\n}\n```\n\n![debug](https://raw.githubusercontent.com/ngxs-labs/firebase-plugin/master/docs/assets/readme_get_all_once.png)\n\n### Connect to stream and receive data changes until disconnected\n\nFor the second scenario, the plugin provides the `NgxsFirestoreConnect` service, which let's you connect an `@Action`\nwith a Firestore query and emit every new change as a separate `Emitted` action.\n\nThe service `connect` method takes as arguments the `Action` that will trigger subscribing to the Firestore query. In\naddition an `opts` object with `to` field, to pass the function that returns the Firestore query.\n\nOnce connection is setup, you can then create handlers for the specific events of the stream.\n\nYou can add handlers for:\n\n- Connected event with `@Action(StreamConnected(RacesActions.GetAll))`.\n\n  This event will be fired once on first emission.\n\n- Emmited event with `@Action(StreamEmitted(RacesActions.GetAll))`\n\n  This event will be fired each observable emission. This action will return `Emitted\u003cAction, T\u003e` where `Action` is the\n  action bound, and `T` is the type of the returned results from the Firestore query.\n\n- Disconnected event with `@Action(StreamDisconnected(RacesActions.GetAll))`\n\n  This event will be fired on observable disconnect.\n\n```ts\n//...\nimport { NgxsFirestoreConnect } from '@ngxs-labs/firestore-plugin';\n\nexport class GetAll {\n  public static readonly type = '[Races] GetAll';\n}\n\nexport class Get {\n  public static readonly type = '[Races] Get';\n  constructor(public payload: string) {}\n}\n\nexport class RacesState implements NgxsOnInit {\n  //...\n  constructor(private racesFS: RacesFirestore, private ngxsFirestoreConnect: NgxsFirestoreConnect) {}\n\n  ngxsOnInit() {\n    // query collection\n    this.ngxsFirestoreConnect.connect(RacesActions.GetAll, {\n      to: () =\u003e this.racesFS.collection$()\n    });\n\n    // query doc\n    this.ngxsFirestoreConnect.connect(RacesActions.Get, {\n      to: (action) =\u003e this.racesFS.doc$(action.payload),\n      trackBy: (action) =\u003e action.payload\n    });\n  }\n\n  // GetAll\n  @Action(StreamConnected(RacesActions.GetAll))\n  getAllConnected(ctx: StateContext\u003cRacesStateModel\u003e, { action }: Connected\u003cRacesActions.GetAll\u003e) {\n    // do something when connected\n  }\n\n  @Action(StreamEmitted(RacesActions.GetAll))\n  getAllEmitted(ctx: StateContext\u003cRacesStateModel\u003e, { action, payload }: Emitted\u003cRacesActions.Get, Race[]\u003e) {\n    ctx.setState(patch({ races: payload }));\n  }\n\n  @Action(StreamDisconnected(RacesActions.GetAll))\n  getAllDisconnected(ctx: StateContext\u003cRacesStateModel\u003e, { action }: Disconnected\u003cRacesActions.GetAll\u003e) {\n    // do something when disconnected\n  }\n\n  //Get\n  @Action(StreamEmitted(RacesActions.Get))\n  get(ctx: StateContext\u003cRacesStateModel\u003e, { action, payload }: Emitted\u003cRacesActions.Get, Race\u003e) {\n    ctx.setState(\n      patch({\n        races: iif(\n          (races) =\u003e !!races.find((race) =\u003e race.id === payload.id),\n          updateItem((race) =\u003e race.id === payload.id, patch(payload)),\n          insertItem(payload)\n        )\n      })\n    );\n  }\n}\n```\n\nOnce you connect to the Firestore stream you'll keep receiving every server update on a new `Emitted` action, making it\neasier to debug.\n\n![debug](https://raw.githubusercontent.com/ngxs-labs/firebase-plugin/master/docs/assets/readme_actions_emit.gif)\n\n#### Adding write operations\n\nWhen adding write operation to your state, you can use the helper methods from `NgxsFirestore`. Since your data is\nconnnected from Firestore, every write operation you run in the state will trigger an emission and update the state.\n\n```ts\nexport class Create {\n  public static readonly type = '[Races] Create';\n  constructor(public payload: Race) {}\n}\n\nexport class RacesState implements NgxsOnInit {\n  //...\n  // Create\n  @Action(RacesActions.Create)\n  create(ctx: StateContext\u003cRacesStateModel\u003e, { action }: Connected\u003cRacesActions.Create\u003e) {\n    // do something when connected\n    return this.racesFS.create$(action.payload);\n  }\n}\n```\n\n#### Getting data from Firestore and Disconnecting\n\nAfter all your Firestore queries are bind to its respective Actions, you can start getting data by dispatching the\n`Action` like this:\n\n```ts\n//...\nthis.store.dispatch(new RacesActions.GetAll());\n// or\nthis.store.dispatch(new RacesActions.Get(id));\n```\n\nIf you need to disconnect you can dispatch\n\n```ts\n//...\nthis.store.dispatch(new Disconnect(new RacesActions.GetAll()));\n// or\nthis.store.dispatch(new Disconnect(new RacesActions.Get(id)));\n```\n\n### NgxsFirestore options\n\nNgxsFirestore allows to setup an \"id\" field, and automatically set the Firestore's doc id in the response object. To do\nthis, you just need to setup `idField` in your `NgxsFirestore` class.\n\n```ts\nexport class RacesFirestore extends NgxsFirestore\u003cRace\u003e {\n  idField = 'raceId';\n}\n```\n\nAnother option you can setup is a conversion on items that come from or go to Firestore. You can do this, setting a\n`firebase.firestore.FirestoreDataConverter` and configure `toFirestore` and `fromFirestore`. `toFirestore` will be\napplied before saving the object to Firestore and `fromFirestore` will be applied when items are streamed from Firestore\nto your app.\n\n```ts\nexport class RacesFirestore extends NgxsFirestore\u003cRace\u003e {\n  protected path = 'races';\n  idField = 'raceId';\n\n  converter: firebase.firestore.FirestoreDataConverter\u003cRace\u003e = {\n    toFirestore: (value) =\u003e {\n      const db = { ...value };\n      delete db.testProp;\n      return db;\n    },\n    fromFirestore: (snapshot, options) =\u003e {\n      const data = snapshot.data(options);\n\n      return \u003cRace\u003e{ ...data, testProp: data.id + data.title };\n    }\n  };\n}\n```\n\nYou can also configure if you want to retrieve the\n[metadata from firestore document](https://firebase.google.com/docs/firestore/manage-data/enable-offline).\n\nEnabling fetching metadata, you will get `fromCache` and `hasPendingWrites` fields that can be useful to inform users if\ndata is being read from the server or writes have already been commited to the database.\n\nYou can disable `metadata` setting it to `false`.\n\n```ts\nexport class RacesFirestore extends NgxsFirestore\u003cRace\u003e {\n  metadataField = '_metadata';\n}\n```\n\n### Retrieving data from subcollections\n\nWhen you need to pull data from a subcollection you can create a specific Firestore service for the subcollection. Let's\nsay the races collection, contains a classification subcollection, then you could setup the Firestore subcollection\nservice like this.\n\n```ts\n@Injectable({\n  providedIn: 'root'\n})\nexport class ClassificationsFirestore extends NgxsFirestore\u003cRace\u003e {\n  protected get path() {\n    return `races/${this.raceId}/classifications`;\n  }\n\n  private _raceId = '';\n  public setRaceId(raceId) {\n    this._raceId = raceId;\n  }\n\n  protected get raceId() {\n    return this._raceId;\n  }\n}\n```\n\n### Paging\n\nFirestore allows us to page queries using a combination of `limit` and `startAt` options when we create our query. This\nplugin includes a simple approach to allow fetching from the database using `limit`.\n\n```ts\n//...\nconstructor(\n  //...\n  private ngxsFirestoreConnect: NgxsFirestoreConnect,\n  private ngxsFirestorePage: NgxsFirestorePageService\n) {}\n\nngxsOnInit(ctx: StateContext\u003cRacesStateModel\u003e) {\n  this.ngxsFirestoreConnect.connect(GetPages, {\n    to: () =\u003e {\n      const obs$ = this.ngxsFirestorePage.create((pageFn) =\u003e this.racesFS.collection$((ref) =\u003e pageFn(ref)), 5, [\n        { fieldPath: 'title' }\n      ]);\n\n      return obs$;\n    }\n  });\n}\n\n```\n\nIn your `@State` you include the `NgxsFirestorePageService` that we'll use to `connect` the paged query with NGXS. The\npage service will `create` a managed `Observable` based on the query you pass into. You completed the configuration with\nthe page size and the fields to order the query by.\n\nThe page service will fetch first page when you dispatch the connected `@Action`, in the example `GetPages`, and will\nincrease the fetched results on each subsequent `GetNextPage`. The result will be 5 items pulled initially, 10 items\nafter `GetNextPage` and so on and so forth. This way you always get synced results with the database and increase the\nsize when you need to see more items. Along with `GetNextPage` the plugin includes `GetLastPage` that will decrease the\nsize pulled when dispatched.\n\nThis approach does not support paging queries providing where to start getting results from, but it is a simple way to\nlimit queries and still be connected with the NGXS store.\n\n### @angular/fire - firebase.js compatibility\n\nIn version 1.2.x the plugin will include two `NgxsFirestore` to allow compatibility with firebase compat and modular.\n\nThe service name will remain the same but the compat version will be exported under\n`@ngxs-labs/firestore-plugin/compat`.\n\nThe compat submodule will also export `NgxsFirestoreAdapter`, `NgxsFirestorePageService` and\n`NgxsFirestorePageIdService`.\n\nIf you intend to keep using compat version for a while, make sure you are using the correct import\n`@ngxs-labs/firestore-plugin/compat`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngxs-labs%2Ffirestore-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngxs-labs%2Ffirestore-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngxs-labs%2Ffirestore-plugin/lists"}