Showing preview only (987K chars total). Download the full file or copy to clipboard to get everything.
Repository: angular/angularfire
Branch: main
Commit: ac3dd7c38a2c
Files: 459
Total size: 887.3 KB
Directory structure:
gitextract_l7_cun8a/
├── .editorconfig
├── .firebaserc
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── codeql-analysis.yml
│ └── test.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── SECURITY.md
├── angular.json
├── docs/
│ ├── analytics.md
│ ├── app-check.md
│ ├── auth.md
│ ├── compat/
│ │ ├── analytics/
│ │ │ └── getting-started.md
│ │ ├── auth/
│ │ │ ├── getting-started.md
│ │ │ └── router-guards.md
│ │ ├── emulators/
│ │ │ └── emulators.md
│ │ ├── firestore/
│ │ │ ├── collections.md
│ │ │ ├── documents.md
│ │ │ ├── offline-data.md
│ │ │ └── querying-collections.md
│ │ ├── functions/
│ │ │ └── functions.md
│ │ ├── messaging/
│ │ │ └── messaging.md
│ │ ├── performance/
│ │ │ └── getting-started.md
│ │ ├── remote-config/
│ │ │ └── getting-started.md
│ │ ├── rtdb/
│ │ │ ├── lists.md
│ │ │ ├── objects.md
│ │ │ └── querying-lists.md
│ │ └── storage/
│ │ └── storage.md
│ ├── compat.md
│ ├── database.md
│ ├── deploy/
│ │ └── getting-started.md
│ ├── firebase.json
│ ├── firestore.md
│ ├── functions.md
│ ├── install-and-setup.md
│ ├── install-angular-cli-windows10.md
│ ├── install-firebase-tools.md
│ ├── messaging.md
│ ├── performance.md
│ ├── remote-config.md
│ ├── storage.md
│ ├── universal/
│ │ ├── cloud-functions.md
│ │ ├── getting-started.md
│ │ └── prerendering.md
│ ├── version-4-upgrade.md
│ ├── version-5-upgrade.md
│ ├── version-6-upgrade.md
│ ├── version-7-upgrade.md
│ ├── vertexai.md
│ └── zones.md
├── eslint.config.js
├── firebase.json
├── karma.conf.js
├── mise.toml
├── package.json
├── sample/
│ ├── .editorconfig
│ ├── .firebaserc
│ ├── .gitignore
│ ├── README.md
│ ├── angular.json
│ ├── database.rules.json
│ ├── firebase.json
│ ├── firestore.indexes.json
│ ├── firestore.rules
│ ├── functions/
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── package.json
│ ├── seed/
│ │ ├── auth_export/
│ │ │ ├── accounts.json
│ │ │ └── config.json
│ │ ├── database_export/
│ │ │ └── angularfire2-test.json
│ │ ├── firebase-export-metadata.json
│ │ ├── firestore_export/
│ │ │ ├── all_namespaces/
│ │ │ │ └── all_kinds/
│ │ │ │ ├── all_namespaces_all_kinds.export_metadata
│ │ │ │ └── output-0
│ │ │ └── firestore_export.overall_export_metadata
│ │ └── storage_export/
│ │ ├── buckets.json
│ │ └── metadata/
│ │ └── angularfire2-test.appspot.com/
│ │ └── google-g.png.json
│ ├── src/
│ │ ├── app/
│ │ │ ├── app.component.spec.ts
│ │ │ ├── app.component.ts
│ │ │ ├── app.config.client.ts
│ │ │ ├── app.config.server.ts
│ │ │ ├── app.config.ts
│ │ │ ├── app.routes.server.ts
│ │ │ ├── app.routes.ts
│ │ │ ├── auth/
│ │ │ │ └── auth.component.ts
│ │ │ ├── database/
│ │ │ │ └── database.component.ts
│ │ │ ├── firestore/
│ │ │ │ └── firestore.component.ts
│ │ │ ├── functions/
│ │ │ │ └── functions.component.ts
│ │ │ ├── messaging/
│ │ │ │ └── messaging.component.ts
│ │ │ ├── remote-config/
│ │ │ │ └── remote-config.component.ts
│ │ │ ├── storage/
│ │ │ │ └── storage.component.ts
│ │ │ └── upboats/
│ │ │ └── upboats.component.ts
│ │ ├── environments/
│ │ │ └── environment.ts
│ │ ├── index.html
│ │ ├── main.server.ts
│ │ ├── main.ts
│ │ ├── server.ts
│ │ └── styles.css
│ ├── storage.rules
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── site/
│ ├── .eleventy.js
│ ├── .firebaserc
│ ├── .gitignore
│ ├── firebase.json
│ ├── package.json
│ ├── postcss.config.js
│ ├── scripts/
│ │ └── build.js
│ └── src/
│ ├── _data/
│ │ └── nextprev.json
│ ├── _includes/
│ │ ├── default.njk
│ │ ├── guide.njk
│ │ ├── next-prev.njk
│ │ └── side-nav.njk
│ ├── analytics/
│ │ ├── analytics.11tydata.json
│ │ ├── getting-started.md
│ │ └── index.md
│ ├── auth/
│ │ ├── auth.11tydata.json
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── route-guards.md
│ ├── firestore/
│ │ ├── collections.md
│ │ ├── documents.md
│ │ ├── firestore.11tydata.json
│ │ └── index.md
│ ├── functions/
│ │ ├── functions.11tydata.json
│ │ ├── getting-started.md
│ │ └── index.md
│ ├── get-started/
│ │ ├── deploying.md
│ │ ├── get-started.11tydata.json
│ │ ├── index.md
│ │ ├── local-development.md
│ │ └── quick-start.md
│ ├── index.md
│ ├── ionic/
│ │ ├── authentication.md
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── ionic.11tydata.json
│ ├── js/
│ │ ├── click-card.js
│ │ ├── menu-button.js
│ │ └── tab-switcher.js
│ ├── messaging/
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── messaging.11tydata.json
│ ├── performance/
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── performance.11tydata.json
│ ├── remote-config/
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── remote-config.11tydata.json
│ ├── rtdb/
│ │ ├── index.md
│ │ ├── lists.md
│ │ ├── objects.md
│ │ ├── querying.md
│ │ └── rtdb.11tydata.json
│ ├── shortcodes/
│ │ ├── buttons/
│ │ │ └── index.js
│ │ ├── disclaimerprod/
│ │ │ └── index.js
│ │ ├── filters/
│ │ │ └── index.js
│ │ ├── headings/
│ │ │ └── index.js
│ │ ├── includecode/
│ │ │ ├── fetch.js
│ │ │ ├── from-local.js
│ │ │ ├── index.js
│ │ │ ├── snippets.js
│ │ │ └── transform.js
│ │ ├── index.js
│ │ └── version/
│ │ └── index.js
│ ├── storage/
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ └── storage.11tydata.json
│ ├── styles/
│ │ ├── prism.css
│ │ ├── tailwind.config.js
│ │ └── tailwind.css
│ └── universal/
│ ├── cloud-functions.md
│ ├── getting-started.md
│ ├── index.md
│ ├── prerendering.md
│ └── universal.11tydata.json
├── src/
│ ├── ai/
│ │ ├── ai.module.ts
│ │ ├── ai.spec.ts
│ │ ├── ai.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── analytics/
│ │ ├── analytics.module.ts
│ │ ├── analytics.spec.ts
│ │ ├── analytics.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ ├── screen-tracking.service.ts
│ │ └── user-tracking.service.ts
│ ├── app/
│ │ ├── app.module.ts
│ │ ├── app.spec.ts
│ │ ├── app.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── app-check/
│ │ ├── app-check.module.ts
│ │ ├── app-check.spec.ts
│ │ ├── app-check.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── auth/
│ │ ├── auth.module.ts
│ │ ├── auth.spec.ts
│ │ ├── auth.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ └── rxfire.ts
│ ├── auth-guard/
│ │ ├── auth-guard.module.ts
│ │ ├── auth-guard.spec.ts
│ │ ├── auth-guard.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── compat/
│ │ ├── analytics/
│ │ │ ├── analytics.module.ts
│ │ │ ├── analytics.spec.ts
│ │ │ ├── analytics.ts
│ │ │ ├── base.ts
│ │ │ ├── index.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ ├── public_api.ts
│ │ │ ├── screen-tracking.service.ts
│ │ │ └── user-tracking.service.ts
│ │ ├── angularfire2.spec.ts
│ │ ├── auth/
│ │ │ ├── auth.module.ts
│ │ │ ├── auth.spec.ts
│ │ │ ├── auth.ts
│ │ │ ├── base.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ └── public_api.ts
│ │ ├── auth-guard/
│ │ │ ├── auth-guard.module.ts
│ │ │ ├── auth-guard.spec.ts
│ │ │ ├── auth-guard.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ └── public_api.ts
│ │ ├── cache.ts
│ │ ├── database/
│ │ │ ├── database.module.ts
│ │ │ ├── database.spec.ts
│ │ │ ├── database.ts
│ │ │ ├── interfaces.ts
│ │ │ ├── list/
│ │ │ │ ├── audit-trail.spec.ts
│ │ │ │ ├── audit-trail.ts
│ │ │ │ ├── changes.spec.ts
│ │ │ │ ├── changes.ts
│ │ │ │ ├── create-reference.ts
│ │ │ │ ├── data-operation.ts
│ │ │ │ ├── remove.ts
│ │ │ │ ├── snapshot-changes.spec.ts
│ │ │ │ ├── snapshot-changes.ts
│ │ │ │ ├── state-changes.spec.ts
│ │ │ │ ├── state-changes.ts
│ │ │ │ └── utils.ts
│ │ │ ├── ng-package.json
│ │ │ ├── object/
│ │ │ │ ├── create-reference.ts
│ │ │ │ └── snapshot-changes.ts
│ │ │ ├── observable/
│ │ │ │ ├── fromRef.spec.ts
│ │ │ │ └── fromRef.ts
│ │ │ ├── package.json
│ │ │ ├── public_api.ts
│ │ │ ├── utils.spec.ts
│ │ │ └── utils.ts
│ │ ├── firebase.app.module.ts
│ │ ├── firebase.app.ts
│ │ ├── firestore/
│ │ │ ├── collection/
│ │ │ │ ├── changes.ts
│ │ │ │ ├── collection.spec.ts
│ │ │ │ └── collection.ts
│ │ │ ├── collection-group/
│ │ │ │ ├── collection-group.spec.ts
│ │ │ │ └── collection-group.ts
│ │ │ ├── document/
│ │ │ │ ├── document.spec.ts
│ │ │ │ └── document.ts
│ │ │ ├── firestore.module.ts
│ │ │ ├── firestore.spec.ts
│ │ │ ├── firestore.ts
│ │ │ ├── interfaces.ts
│ │ │ ├── ng-package.json
│ │ │ ├── observable/
│ │ │ │ └── fromRef.ts
│ │ │ ├── package.json
│ │ │ ├── public_api.ts
│ │ │ └── utils.spec.ts
│ │ ├── functions/
│ │ │ ├── base.ts
│ │ │ ├── functions.module.ts
│ │ │ ├── functions.spec.ts
│ │ │ ├── functions.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ └── public_api.ts
│ │ ├── messaging/
│ │ │ ├── base.ts
│ │ │ ├── messaging.module.ts
│ │ │ ├── messaging.spec.ts
│ │ │ ├── messaging.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ └── public_api.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── performance/
│ │ │ ├── base.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ ├── performance.module.ts
│ │ │ ├── performance.service.ts
│ │ │ ├── performance.spec.ts
│ │ │ ├── performance.ts
│ │ │ └── public_api.ts
│ │ ├── proxy.ts
│ │ ├── public_api.ts
│ │ ├── remote-config/
│ │ │ ├── base.ts
│ │ │ ├── index.ts
│ │ │ ├── interfaces.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ ├── public_api.ts
│ │ │ ├── remote-config.module.ts
│ │ │ ├── remote-config.spec.ts
│ │ │ └── remote-config.ts
│ │ └── storage/
│ │ ├── interfaces.ts
│ │ ├── ng-package.json
│ │ ├── observable/
│ │ │ └── fromTask.ts
│ │ ├── package.json
│ │ ├── pipes/
│ │ │ └── storageUrl.pipe.ts
│ │ ├── public_api.ts
│ │ ├── ref.ts
│ │ ├── storage.module.ts
│ │ ├── storage.spec.ts
│ │ ├── storage.ts
│ │ └── task.ts
│ ├── core.ts
│ ├── data-connect/
│ │ ├── data-connect.module.ts
│ │ ├── data-connect.spec.ts
│ │ ├── data-connect.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── overrides.ts
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── database/
│ │ ├── database.module.ts
│ │ ├── database.spec.ts
│ │ ├── database.ts
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ └── rxfire.ts
│ ├── firestore/
│ │ ├── firebase.ts
│ │ ├── firestore.module.ts
│ │ ├── firestore.spec.ts
│ │ ├── firestore.ts
│ │ ├── lite/
│ │ │ ├── firebase.ts
│ │ │ ├── lite.module.ts
│ │ │ ├── lite.spec.ts
│ │ │ ├── lite.ts
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ ├── public_api.ts
│ │ │ └── rxfire.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ └── rxfire.ts
│ ├── functions/
│ │ ├── firebase.ts
│ │ ├── functions.module.ts
│ │ ├── functions.spec.ts
│ │ ├── functions.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ └── rxfire.ts
│ ├── messaging/
│ │ ├── firebase.ts
│ │ ├── messaging.module.ts
│ │ ├── messaging.spec.ts
│ │ ├── messaging.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ └── public_api.ts
│ ├── ng-package.json
│ ├── package.json
│ ├── performance/
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── performance.module.ts
│ │ ├── performance.spec.ts
│ │ ├── performance.ts
│ │ ├── public_api.ts
│ │ └── rxfire.ts
│ ├── public_api.ts
│ ├── remote-config/
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ ├── remote-config.module.ts
│ │ ├── remote-config.spec.ts
│ │ ├── remote-config.ts
│ │ └── rxfire.ts
│ ├── schematics/
│ │ ├── add/
│ │ │ ├── index.ts
│ │ │ └── schema.json
│ │ ├── builders.json
│ │ ├── collection.json
│ │ ├── common.ts
│ │ ├── deploy/
│ │ │ ├── actions.jasmine.ts
│ │ │ ├── actions.ts
│ │ │ ├── builder.ts
│ │ │ ├── functions-templates.ts
│ │ │ └── schema.json
│ │ ├── firebaseTools.ts
│ │ ├── interfaces.ts
│ │ ├── migration.json
│ │ ├── setup/
│ │ │ ├── index.ts
│ │ │ ├── prompts.ts
│ │ │ └── schema.json
│ │ ├── tsconfig.json
│ │ ├── update/
│ │ │ ├── index.ts
│ │ │ └── v7/
│ │ │ └── index.ts
│ │ ├── utils.ts
│ │ └── versions.json
│ ├── storage/
│ │ ├── firebase.ts
│ │ ├── ng-package.json
│ │ ├── package.json
│ │ ├── public_api.ts
│ │ ├── rxfire.ts
│ │ ├── storage.module.ts
│ │ ├── storage.spec.ts
│ │ └── storage.ts
│ ├── test-config.ts
│ ├── test.ts
│ ├── utils.ts
│ └── zones.ts
├── test/
│ ├── database.rules.json
│ ├── firestore.indexes.json
│ ├── firestore.rules
│ ├── functions/
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── storage.rules
├── tools/
│ ├── build.sh
│ ├── build.ts
│ └── jasmine.ts
├── tsconfig.base.json
├── tsconfig.build.json
├── tsconfig.jasmine.json
├── tsconfig.json
├── tsconfig.spec.json
└── typedoc.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
================================================
FILE: .firebaserc
================================================
{
"projects": {
"default": "angularfire2-test"
}
}
================================================
FILE: .gitattributes
================================================
src/**/firebase.ts linguist-generated=true
src/**/rxfire.ts linguist-generated=true
src/compat/**/base.ts linguist-generated=true
samples/**/* linguist-generated=true
yarn.lock linguist-generated=true
================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '20 23 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
================================================
FILE: .github/workflows/test.yml
================================================
name: Test and publish
on:
push:
branches:
- main
paths-ignore:
- "**/*.md"
pull_request:
branches:
- "**"
release:
types:
- published
schedule:
- cron: 0 0 * * 1-5
jobs:
build:
runs-on: ubuntu-latest
name: Build
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
- name: Setup node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: '20'
check-latest: false
- name: angular build cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ./.angular
key: angular-cache
- name: node_modules cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
id: node_modules_cache
with:
path: ./node_modules
key: ${{ runner.os }}-20-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-20-
- name: Install deps
if: steps.node_modules_cache.outputs.cache-hit != 'true'
run: |
npm ci
- name: Build
run: ./tools/build.sh
- name: 'Upload Artifact'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with:
name: angularfire-${{ github.run_id }}
path: dist
retention-days: 1
test:
runs-on: ${{ matrix.os }}
needs: build
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
node: ["20", "22", "24"]
fail-fast: false
name: Test Node ${{ matrix.node }} (${{ matrix.os }})
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
- name: Setup node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: ${{ matrix.node }}
check-latest: true
- name: node_modules cache
id: node_modules_cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-${{ matrix.node }}-
- name: Install deps
if: steps.node_modules_cache.outputs.cache-hit != 'true'
run: npm ci
- name: Download Artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with:
name: angularfire-${{ github.run_id }}
path: dist
- name: Test Node
run: |
npm run build:jasmine
npm run test:node
browser:
runs-on: ${{ matrix.os }}
needs: build
name: Test ${{ matrix.browser }}
strategy:
matrix:
os: [ ubuntu-latest ]
browser: [ chrome-headless, firefox-headless ]
# TODO(davideast): Figure out why Safari tests timeout only on CI
# include:
# - os: macos-latest
# browser: safari
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
- name: Setup node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: 20
check-latest: false
- name: Setup java
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165
with:
distribution: 'temurin'
java-version: '11'
- name: node_modules cache
id: node_modules_cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-${{ matrix.node }}-
- name: Install deps
if: steps.node_modules_cache.outputs.cache-hit != 'true'
run: npm ci
- name: Firebase emulator cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ~/.cache/firebase/emulators
key: firebase_emulators
- name: Download Artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with:
name: angularfire-${{ github.run_id }}
path: dist
- name: Test browser
run: npm run test:${{ matrix.browser }}
contribute:
runs-on: ${{ matrix.os }}
name: Contribute Node ${{ matrix.node }} (${{ matrix.os }})
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
node: ["20"]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
- name: Setup node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: ${{ matrix.node }}
check-latest: true
- name: node_modules cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
id: node_modules_cache
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-${{ matrix.node }}-
- name: Install deps
if: steps.node_modules_cache.outputs.cache-hit != 'true'
run: npm ci
#- name: Lint
# run: npm run lint
- name: Build
run: npm run build
- name: Test Node
run: |
npm run build:jasmine
npm run test:node
- name: Firebase emulator cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ~/.cache/firebase/emulators
key: firebase_emulators
- name: Setup java
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165
with:
distribution: 'temurin'
java-version: '11'
- name: Test headless
run: npm run test:chrome-headless
# Tests are flaky on Windows
continue-on-error: ${{ matrix.os == 'windows-latest' }}
# Break the branch protection test into a seperate step, so we can manage the matrix more easily
test_and_contribute:
runs-on: ubuntu-latest
name: Branch protection
needs: ['test', 'contribute', 'browser']
steps:
- run: true
publish:
runs-on: ubuntu-latest
name: Publish (NPM)
needs: ['build', 'test', 'browser']
if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'release' }}
steps:
- name: Setup node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
check-latest: false
- name: 'Download Artifacts'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with:
name: angularfire-${{ github.run_id }}
path: dist
- name: Publish
run: |
cd ./dist/packages-dist
chmod +x publish.sh
./publish.sh
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
================================================
FILE: .gitignore
================================================
node_modules/
dist/
dist-test/
docs/api/
typings/
npm-debug.log
.idea/
.vscode/settings.json
angular-fire-*.tgz
angularfire2-*.tgz
*.ngfactory.ts
*.ngsummary.json
.DS_Store
yarn-error.log
*.bak
yarn.lock
test/ng-build/**/yarn.lock
tools/build.js
coverage
*.log
api-*.json
angularfire.tgz
unpack.sh
publish.sh
.firebase
.angular
.vscode
================================================
FILE: .npmignore
================================================
*.spec.*
test-config.*
publish.sh
__ivy_ngcc__/
*.min.js
*.min.js.map
*.__ivy_ngcc_bak
================================================
FILE: .nvmrc
================================================
lts/*
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to AngularFire
We would love for you to contribute to AngularFire and help make it even better than it is
today! As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Initial Setup](#setup)
- [Submission Guidelines](#submit)
- [Submitting an Issue](#submit-issue)
- [Submitting a Pull Request](#submit-pr)
- [Before you submit](#submit-before)
- [How to submit](#submit-how)
- [Deploying docs](#submit-docs)
- Appendix
- [Coding Rules][rules] (external link)
- [Commit Message Guidelines][commit] (external link)
- [Signing the CLA](#cla)
## <a name="coc"></a> Code of Conduct
Help us keep the Angular and Firebase communities open and inclusive. Please read and follow the Angular [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
If you have questions about how to *use* AngularFire, please direct them to the [Angular Google Group][angular-group]
discussion list or [StackOverflow][stackoverflow] (include the `firebase` and `angular` tags!).
Please note that the Angular team's capacity to answer usage questions is limited.
Members of the Firebase team can be reached on [Slack][slack] and via the [Firebase Google Group][firebase-group].
## <a name="issue"></a> Found an Issue?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
[submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Want a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our [GitHub
Repository][github]. If you would like to *implement* a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
Please consider what kind of change it is:
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
and help you to craft the change so that it is successfully accepted into the project.
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="setup"></a> Initial Setup
1) Create a fork of AngularFire (See [Forking a Project][github-fork])
2) Clone your fork, CD into the directory, and install dependencies
```shell
$ git clone <your fork SSH/HTTPS from GitHub>
$ cd angularfire
$ npm i
$ npm run build
$ npm run test:all
```
3) Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Help us to maximize the effort we can spend improving the product by not reporting duplicate issues.
Search the archives before you submit.
Providing the following information will increase the chances of your issue being dealt with quickly:
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
* **Angular Version** - what version of Angular, Firebase, and AngularFire are you using?
* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
* **Browsers and Operating System** - is this a problem with all browsers?
* **Reproduce the Error** - provide a live example (using StackBlitz (https://stackblitz.com/edit/angular-fire-start))
or a unambiguous set of steps
* **Related Issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
You can file new issues by providing the above information [here](https://github.com/angular/angularfire2/issues/new).
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
#### <a name="submit-before"></a> Before you submit:
* Ensure proposed changes or problem have already been clearly defined and
discussed in the issue tracker. We don't want you to burn time on code
that isn't a good fit for the project.
* Search [GitHub](https://github.com/angular/angularfire2/pulls) for an open or closed PR
that relates to your submission. You don't want to duplicate effort.
* Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without this.
* Review our [Coding Rules][rules] (external link)
* Review our [Commit Message Guidelines][commit] (external link)
#### <a name="submit-how"></a> How to submit:
* Create your patch, **including appropriate test cases**.
* Follow the [Angular Coding Rules][rules].
* Run the full test suite (`yarn test`) and ensure that all tests pass.
* Commit your changes using a descriptive commit message that follows the
[Angular commit message conventions][commit]. Adherence to these conventions
is necessary because release notes are automatically generated from these messages.
```shell
git commit -a
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
* Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
* In GitHub, send a pull request to `angular:master`.
* If we suggest changes then:
* Make the required updates.
* Re-run the test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
```shell
git rebase master -i
git push -f
```
That's it! Thank you for your contribution!
## <a name="cla"></a> Signing the CLA
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
* For individuals we have a [simple click-through form][individual-cla].
* For corporations we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
[slack]: https://firebase-community.appspot.com/
[coc]: https://github.com/angular/code-of-conduct/blob/main/CODE_OF_CONDUCT.md
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[corporate-cla]: https://code.google.com/legal/corporate-cla-v1.0.html
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[js-style-guide]: https://google.github.io/styleguide/javascriptguide.xml
[jsfiddle]: http://jsfiddle.net
[plunker]: http://plnkr.co/edit
[runnable]: http://runnable.com
[github]: https://github.com/angular/angularfire2
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularfire
[rules]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#rules
[commit]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines
[angular-group]: https://groups.google.com/forum/#!forum/angular
[firebase-group]: https://groups.google.com/forum/#!forum/firebase-talk
[github-fork]: https://help.github.com/articles/fork-a-repo/
================================================
FILE: ISSUE_TEMPLATE.md
================================================
<!--
IMPORTANT! YOU MUST FOLLOW THESE INSTRUCTIONS OR YOUR ISSUE WILL BE CLOSED.
Thank you for contributing to the Angular and Firebase communities!
Have a usage question?
=======================
We get lots of those and we love helping you, but GitHub is not the best place for them and they will be closed. Here are some resources to get help:
- Go through the Developer's Guide: https://github.com/angular/angularfire2#developer-guide
If the official documentation doesn't help, try asking through our officially supported channels:
- Firebase Google Group: https://groups.google.com/forum/#!forum/firebase-talk
- Stack Overflow: https://stackoverflow.com/questions/tagged/angular (include the firebase and angularfire tags, too!)
*Please avoid double posting across multiple channels!*
Think you found a bug?
=======================
Yeah, we're definitely not perfect! Please use the bug report template below and include a minimal repro when opening the issue.
Have a feature request?
========================
Great, we love hearing how we can improve our products! Remove the template below and
provide an explanation of your feature request. Provide code samples if applicable. Try to
think about what it will allow you to do that you can't do today? How will it make current
workarounds straightforward? What potential bugs and edge cases does it help to avoid?
-->
### Version info
<!-- What versions of the following libraries are you using? Note that your issue may already
be fixed in the latest versions. -->
**Angular:**
**Firebase:**
**AngularFire:**
**Other (e.g. Ionic/Cordova, Node, browser, operating system):**
### How to reproduce these conditions
**Failing test unit, Stackblitz demonstrating the problem**
<!--
Provide a failing test unit, or create a minimal, complete, and
verifiable example (http://stackoverflow.com/help/mcve) using
StackBlitz (https://stackblitz.com/edit/angular-fire-start).
-->
**Steps to set up and reproduce**
<!-- detailed instructions to run your minimal repro or to recreate the environment -->
**Sample data and security rules**
<!-- include/attach/link to some json sample data (or provide credentials to a sanitized, test Firebase project) -->
### Debug output
** Errors in the JavaScript console **
** Output from `firebase.database().enableLogging(true);` **
** Screenshots **
### Expected behavior
<!-- What is the expected behavior? -->
### Actual behavior
<!-- What is the actual behavior? -->
================================================
FILE: LICENSE
================================================
The MIT License
Copyright (c) 2014-2016 Google, Inc. http://angular.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for contributing to the Firebase community! Please fill out the pull request form below
and make note of the following:
Run the linter and test suite
==============================
Make sure your changes pass our linter and the tests all pass on your local machine. We've hooked
up this repo with continuous integration to double check those things for you.
Add tests (if applicable)
==============================
Most non-trivial changes should include some extra test coverage. If you aren't sure how to add
tests, feel free to submit regardless and ask us for some advice.
Sign our CLA
==============================
Please sign our Contributor License Agreement (https://cla.developers.google.com/about/google-individual)
before sending PRs. We cannot accept code without this.
-->
### Checklist
- Issue number for this PR: #nnn (required)
- Docs included?: (yes/no; required for all API/functional changes)
- Test units included?: (yes/no; required)
- In a clean directory, `yarn install`, `yarn test` run successfully? (yes/no; required)
### Description
<!-- Are you fixing a bug? Updating our documentation? Implementing a new feature? Make sure we
have the context around your change. Link to other relevant issues or pull requests. -->
### Code sample
<!-- Proposing an API change? Provide code samples showing how the API will be used. -->
================================================
FILE: README.md
================================================
# AngularFire
AngularFire smooths over the rough edges an Angular developer might encounter when implementing the framework-agnostic
[Firebase JS SDK](https://github.com/firebase/firebase-js-sdk) & aims to provide a more natural developer experience
by conforming to Angular conventions.
<strong><pre>ng add @angular/fire</pre></strong>
- **Dependency injection** - Provide and Inject Firebase services in your components.
- **Zone.js wrappers** - Stable zones allow proper functionality of service workers, forms, SSR, and pre-rendering.
- **Observable based** - Utilize RxJS rather than callbacks for real-time streams.
- **NgRx friendly API** - Integrate with NgRx using AngularFire's action based APIs.
- **Lazy-loading** - AngularFire dynamically imports much of Firebase, reducing the time to load your app.
- **Deploy schematics** - Get your Angular application deployed on Firebase Hosting with a single command.
- **Google Analytics** - Zero-effort Angular Router awareness in Google Analytics.
- **Router Guards** - Guard your Angular routes with built-in Firebase Authentication checks.
## Example use
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { getFirestore, provideFirestore } from '@angular/fire/firestore';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideFirestore(() => getFirestore()),
...
],
...
})
```
```ts
import { AsyncPipe } from '@angular/common';
import { inject } from '@angular/core';
import { Firestore, collectionData, collection } from '@angular/fire/firestore';
interface Item {
name: string,
...
};
@Component({
selector: 'app-root',
template: `
<ul>
@for (item of (item$ | async); track item) {
<li>
{{ item.name }}
</li>
}
</ul>
`,
imports: [AsyncPipe]
})
export class AppComponent {
firestore = inject(Firestore);
itemCollection = collection(this.firestore, 'items');
item$ = collectionData<Item>(itemCollection);
}
```
## Resources
[Quickstart](docs/install-and-setup.md) - Get your first application up and running by following our quickstart guide.
[Contributing](CONTRIBUTING.md)
[Stackblitz Template](https://stackblitz.com/edit/angular-fire-start) - Remember to set your Firebase configuration in `app/app.module.ts`.
[Upgrading from v6.0? Check out our guide.](docs/version-7-upgrade.md)
### Sample app
The [`sample`](sample) folder contains a kitchen sink application that demonstrates use of the "modular" API, in a zoneless server-rendered application, with all the bells and whistles.
### Having troubles?
Get help on our [Q&A board](https://github.com/angular/angularfire/discussions?discussions_q=category%3AQ%26A), the official [Firebase Mailing List](https://groups.google.com/forum/#!forum/firebase-talk), the [Firebase Community Slack](https://firebase.community/) (`#angularfire2`), the [Angular Community Discord](http://discord.gg/angular) (`#firebase`), [Gitter](https://gitter.im/angular/angularfire2), the [Firebase subreddit](https://www.reddit.com/r/firebase), or [Stack Overflow](https://stackoverflow.com/questions/tagged/angularfire2).
> **NOTE:** While relatively stable, AngularFire is a [developer preview](https://angular.io/guide/releases#developer-preview) and is subject to change before general availability. Questions on the mailing list and issues filed here are answered on a <strong>best-effort basis</strong> by maintainers and other community members. If you are able to reproduce a problem with Firebase <em>outside of AngularFire's implementation</em>, please [file an issue on the Firebase JS SDK](https://github.com/firebase/firebase-js-sdk/issues) or reach out to the personalized [Firebase support channel](https://firebase.google.com/support/).
## Developer Guide
This developer guide assumes you're using the new tree-shakable AngularFire API, [if you're looking for the compatibility API you can find the documentation here](docs/compat.md).
[See the v7 upgrade guide for more information on this change.](docs/version-7-upgrade.md).
### Firebase product integrations
<table>
<tr>
<td>
#### [Analytics](docs/analytics.md#analytics)
```ts
import { } from '@angular/fire/analytics';
```
</td>
<td>
#### [Authentication](docs/auth.md#authentication)
```ts
import { } from '@angular/fire/auth';
```
</td>
</tr>
<tr>
<td>
#### [Cloud Firestore](docs/firestore.md#cloud-firestore)
```ts
import { } from '@angular/fire/firestore';
```
</td>
<td>
#### [Cloud Functions](docs/functions.md#cloud-functions)
```ts
import { } from '@angular/fire/functions';
```
</td>
</tr>
<tr>
<td>
#### [Cloud Messaging](docs/messaging.md#cloud-messaging)
```ts
import { } from '@angular/fire/messaging';
```
</td>
<td>
#### [Cloud Storage](docs/storage.md#cloud-storage)
```ts
import { } from '@angular/fire/storage';
```
</td>
</tr>
<tr>
<td>
#### [Performance Monitoring](docs/performance.md#performance-monitoring)
```ts
import { } from '@angular/fire/performance';
```
</td>
<td>
#### [Realtime Database](docs/database.md#realtime-database)
```ts
import { } from '@angular/fire/database';
```
</td>
</tr>
<tr>
<td>
#### [Remote Config](docs/remote-config.md#remote-config)
```ts
import { } from '@angular/fire/remote-config';
```
</td>
<td>
#### [App Check](docs/app-check.md#app-check)
```ts
import { } from '@angular/fire/app-check';
```
</td>
</tr>
<tr>
<td>
#### [Vertex AI](docs/vertexai.md#vertex-ai)
```ts
import { } from '@angular/fire/vertexai';
```
</td>
</tr>
</table>
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 6.0+ | :white_check_mark: |
| < 6.0 | :x: |
## Reporting a Vulnerability
Please contact [Firebase support](https://firebase.google.com/support) and send ticket details to [angularfire-maintainers@google.com](mailto:angularfire-maintainers@google.com?subject=[SECURITY]) with `[SECURITY]` in the subject.
================================================
FILE: angular.json
================================================
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": ".",
"projects": {
"angularfire": {
"projectType": "library",
"root": "src",
"sourceRoot": "src",
"prefix": "angularfire",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "tsconfig.json",
"project": "src/ng-package.json"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js"
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
}
}
}
},
"cli": {
"packageManager": "npm",
"analytics": "86795b8f-9036-4a53-929c-a7303453d677"
}
}
================================================
FILE: docs/analytics.md
================================================
<img align="right" width="30%" src="images/analytics-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Analytics
</small>
# Analytics
Google Analytics is an app measurement solution, available at no charge, that provides insight on app usage and user engagement.
[Learn more](https://firebase.google.com/docs/analytics)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Analytics instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideAnalytics, getAnalytics } from '@angular/fire/analytics';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideAnalytics(() => getAnalytics()),
...
],
...,
}
```
Next inject `Analytics` into your component:
```typescript
import { Component, inject } from '@angular/core';
import { Analytics } from '@angular/fire/analytics';
@Component({ ... })
export class UserProfileComponent {
private analytics = inject(Analytics);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/analytics'` to `import { ... } from '@angular/fire/analytics'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/analytics/get-started?platform=web) | [API Reference](https://firebase.google.com/docs/reference/js/analytics)
================================================
FILE: docs/app-check.md
================================================
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ App Check
</small>
<img align="right" width="30%" src="images/reCAPTCHA-logo@1x.png">
# App Check
App Check helps protect your API resources from abuse by preventing unauthorized clients from accessing your backend resources. It works with both Firebase services, Google Cloud services, and your own APIs to keep your resources safe.
[Learn More](https://firebase.google.com/docs/app-check)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a App Check instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideAppCheck, initializeAppCheck, ReCaptchaV3Provider } from '@angular/fire/app-check';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideAppCheck(() => initializeAppCheck(getApp(), {
provider: new ReCaptchaV3Provider(/* configuration */),
})),
...
],
...
})
```
Next inject `AppCheck` it into your component:
```ts
import { Component, inject} from '@angular/core';
import { AppCheck } from '@angular/fire/app-check';
@Component({ ... })
export class AppCheckComponent {
private appCheck = inject(AppCheck);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/app-check'` to `import { ... } from '@angular/fire/app-check'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/app-check/web/recaptcha-enterprise-provider) | [API Reference](https://firebase.google.com/docs/reference/js/app-check)
================================================
FILE: docs/auth.md
================================================
<img align="right" width="30%" src="images/auth-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Authentication
</small>
# Authentication
Most apps need to know the identity of a user. Knowing a user's identity allows an app to securely save user data in the cloud and provide the same personalized experience across all of the user's devices.
Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook and Twitter, and more.
Firebase Authentication integrates tightly with other Firebase services, and it leverages industry standards like OAuth 2.0 and OpenID Connect, so it can be easily integrated with your custom backend.
[Learn more about Firebase Authentication](https://firebase.google.com/docs/auth)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Auth instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideAuth(() => getAuth()),
...
],
...
})
```
Next inject `Auth` into your component:
```ts
import { Component, inject} from '@angular/core';
import { Auth } from '@angular/fire/auth';
@Component({ ... })
export class LoginComponent {
private auth = inject(Auth);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/auth'` to `import { ... } from '@angular/fire/auth'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/auth/web/start) | [API Reference](https://firebase.google.com/docs/reference/js/auth)
## Server-side Rendering
To support Auth context in server-side rendering, you can provide `FirebaseServerApp`:
```ts
import { ApplicationConfig, PLATFORM_ID, inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { provideFirebaseApp, initializeApp, initializeServeApp, initializeServerApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => {
if (isPlatformBrowser(inject(PLATFORM_ID))) {
return initializeApp(firebaseConfig);
}
// Optional, since it's null in dev-mode and SSG
const request = inject(REQUEST, { optional: true });
const authIdToken = request?.headers.authorization?.split("Bearer ")[1];
return initializeServerApp(firebaseConfig, {
authIdToken,
releaseOnDeref: request || undefined
});
}),
provideAuth(() => getAuth(inject(FirebaseApp)),
...
],
...
})
```
Follow Firebase's [ Session Management with Service Workers documentation](https://firebase.google.com/docs/auth/web/service-worker-sessions) to learn how to pass the `idToken` to the server. __Note: this will not currently work in dev-mode as Angular SSR does not provide a method to get the Request headers.__
## Convenience observables
AngularFire provides observables to allow convenient use of the Firebase Authentication with RXJS.
### user
The `user` observable streams events triggered by sign-in, sign-out, and token refresh events.
Example code:
```ts
import { Auth, User, user } from '@angular/fire/auth';
...
export class UserComponent implements OnDestroy {
private auth: Auth = inject(Auth);
user$ = user(auth);
userSubscription: Subscription;
...
constructor() {
this.userSubscription = this.user$.subscribe((aUser: User | null) => {
//handle user state changes here. Note, that user will be null if there is no currently logged in user.
console.log(aUser);
})
}
ngOnDestroy() {
// when manually subscribing to an observable remember to unsubscribe in ngOnDestroy
this.userSubscription.unsubscribe();
}
}
```
### authState
The `authState` observable streams events triggered by sign-in and sign-out events.
Example code:
```ts
import { Auth, authState } from '@angular/fire/auth';
...
export class UserComponent implements OnDestroy {
private auth: Auth = inject(Auth);
authState$ = authState(auth);
authStateSubscription: Subscription;
...
constructor() {
this.authStateSubscription = this.authState$.subscribe((aUser: User | null) => {
//handle auth state changes here. Note, that user will be null if there is no currently logged in user.
console.log(aUser);
})
}
ngOnDestroy() {
// when manually subscribing to an observable remember to unsubscribe in ngOnDestroy
this.authStateSubscription.unsubscribe();
}
}
```
### idToken
The `idToken` observable streams events triggered by sign-in, sign-out and token refresh events.
Example code:
```ts
import { Auth, idToken } from '@angular/fire/auth';
...
export class UserComponent implements OnDestroy {
private auth: Auth = inject(Auth);
idToken$ = idToken(auth);
idTokenSubscription: Subscription;
...
constructor() {
this.idTokenSubscription = this.idToken$.subscribe((token: string | null) => {
//handle idToken changes here. Note, that user will be null if there is no currently logged in user.
console.log(string);
})
}
ngOnDestroy() {
// when manually subscribing to an observable remember to unsubscribe in ngOnDestroy
this.idTokenSubscription.unsubscribe();
}
}
```
## Connecting the emulator suite
```ts
import { connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth';
@NgModule({
imports: [
provideAuth(() => {
const auth = getAuth();
connectAuthEmulator(auth, 'http://localhost:9099', { disableWarnings: true });
return auth;
}),
]
})
```
================================================
FILE: docs/compat/analytics/getting-started.md
================================================
# Getting started with Google Analytics
`AngularFireAnalytics` dynamically imports the `firebase/analytics` library and provides a promisified version of the [Firebase Analytics SDK (`firebase.analytics.Analytics`)](https://firebase.google.com/docs/reference/js/firebase.analytics.Analytics.html).
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
### API:
```ts
class AngularFireAnalytics {
updateConfig(options: {[key:string]: any}): Promise<void>;
// from firebase.analytics() proxy:
logEvent(eventName: string, eventParams?: {[key: string]: any}, options?: analytics.AnalyticsCallOptions): Promise<void>;
setCurrentScreen(screenName: string, options?: analytics.AnalyticsCallOptions): Promise<void>;
setUserId(id: string, options?: analytics.AnalyticsCallOptions): Promise<void>;
setUserProperties(properties: analytics.CustomParams, options?: analytics.AnalyticsCallOptions): Promise<void>;
setAnalyticsCollectionEnabled(enabled: boolean): Promise<void>;
app: Promise<app.App>;
}
COLLECTION_ENABLED = InjectionToken<boolean>;
APP_VERSION = InjectionToken<string>;
APP_NAME = InjectionToken<string>;
DEBUG_MODE = InjectionToken<boolean>;
CONFIG = InjectionToken<Config>;
```
### Usage:
```ts
import { AngularFireAnalyticsModule } from '@angular/fire/compat/analytics';
@NgModule({
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAnalyticsModule
]
})
export class AppModule { }
```
`AngularFireAnalyticsModule` will dynamically import and configure `firebase/analytics`. A `page_view` event will automatically be logged (see `CONFIG` below if you wish to disable this behavior.)
In your component you can then dependency inject `AngularFireAnalytics` and make calls against the SDK:
```ts
import { AngularFireAnalytics } from '@angular/fire/compat/analytics';
constructor(analytics: AngularFireAnalytics) {
analytics.logEvent('custom_event', { ... });
}
```
## Tracking Screen Views
You can log [`screen_view` events](https://firebase.google.com/docs/reference/js/firebase.analytics.Analytics.html#parameters_10) yourself of course, but AngularFire provides the `ScreenTrackingService` which automatically integrates with the Angular Router to provide Firebase with screen view tracking. You simply can integrate like so:
```ts
import { AngularFireAnalyticsModule, ScreenTrackingService } from '@angular/fire/compat/analytics';
@NgModule({
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAnalyticsModule
],
providers: [
ScreenTrackingService
]
})
export class AppModule { }
```
`AngularFireAnalyticsModule` will initialize `ScreenTrackingService` if it is provided.
## Tracking User Identifiers
To enrich your Analytics data you can track the currently signed in user by setting [`setuserid`](https://firebase.google.com/docs/reference/js/firebase.analytics.Analytics.html#setuserid) and [`setUserProperties`](https://firebase.google.com/docs/reference/js/firebase.analytics.Analytics.html#set-user-properties). AngularFire provides a `UserTrackingService` which will dynamically import `firebase/auth`, monitor for changes in the logged in user, and call `setuserid` for you automatically.
```ts
import { AngularFireAnalyticsModule, UserTrackingService } from '@angular/fire/compat/analytics';
@NgModule({
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAnalyticsModule
],
providers: [
UserTrackingService
]
})
export class AppModule { }
```
`AngularFireAnalyticsModule` will initialize `UserTrackingService` if it is provided.
## Configuration with Dependency Injection
### Configure Google Analtyics with `CONFIG`
Using the `CONFIG` DI Token (*default: {}*) will allow you to configure Google Analytics. E.g, you could skip sending the initial `page_view` event, anonymize IP addresses, and disallow ads personalization signals for all events like so:
```ts
import { AngularFireAnalyticsModule, CONFIG } from '@angular/fire/compat/analytics';
@NgModule({
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAnalyticsModule
],
providers: [
{ provide: CONFIG, useValue: {
send_page_view: false,
allow_ad_personalization_signals: false,
anonymize_ip: true
} }
]
})
export class AppModule { }
```
See the gtag.js documentation to learn of the different configuration options at your disposal.
### Use DebugView `DEBUG_MODE`
To use [DebugView in Analytics](https://console.firebase.google.com/project/_/analytics/debugview) set `DEBUG_MODE` to `true` (*default: false*).
### Track deployments with `APP_NAME` and `APP_VERSION`
If you provide `APP_NAME` and `APP_VERSION` (*default: undefined*) you will be able to [track version adoption](https://console.firebase.google.com/project/_/analytics/latestrelease) of your PWA.
### Disable analytics collection via `COLLECTION_ENABLED`
If you set `COLLECTION_ENABLED` (*default: true*) to `false` then analytics collection will be disabled for this app on this device. To opt back in to analytics collection you could then call `setAnalyticsCollectionEnabled(true)`.
Putting these APIs to use with cookies would allow you to create a flexible analytics collection scheme that would respect your user's desire for privacy.
================================================
FILE: docs/compat/auth/getting-started.md
================================================
# 5. Getting started with Firebase Authentication
`AngularFireAuth.user` provides you an `Observable<User|null>` to monitor your application's authentication State.
`AngularFireAuth` promise proxies an initialized
`firebase.auth.Auth` instance, allowing you to log users in, out, etc. [See
the Firebase docs for more information on what methods are available.](https://firebase.google.com/docs/reference/js/auth.auth)
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
**Example app:**
```ts
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import firebase from 'firebase/compat/app';
@Component({
selector: 'app-root',
template: `
<div *ngIf="auth.user | async as user; else showLogin">
<h1>Hello {{ user.displayName }}!</h1>
<button (click)="logout()">Logout</button>
</div>
<ng-template #showLogin>
<p>Please login.</p>
<button (click)="login()">Login with Google</button>
</ng-template>
`,
})
export class AppComponent {
constructor(public auth: AngularFireAuth) {
}
login() {
this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
}
logout() {
this.auth.signOut();
}
}
```
## Configuration with Dependency Injection
The AngularFireAuth Module provides several DI tokens to further configure your
authentication process.
### Configure
Using the `SETTINGS` DI Token (*default: null*), we can set the current Auth
instance's settings. This is used to edit/read configuration related options
like app verification mode for phone authentication, which is useful for
[testing](https://cloud.google.com/identity-platform/docs/test-phone-numbers).
```ts
import { SETTINGS as AUTH_SETTINGS } from '@angular/fire/compat/auth';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: AUTH_SETTINGS, useValue: { appVerificationDisabledForTesting: true } },
]
})
export class AppModule { }
```
Read more at [Firebase Auth Settings](https://firebase.google.com/docs/reference/js/auth.authsettings).
### Use Current Browser Language
Using the `USE_DEVICE_LANGUAGE` DI Token (*default: null*), which is a boolean
that allow you to set the current language to the default device/browser
preference. This allows to localize emails but be aware that this only applies
if you use the standard template provided by Firebase.
```ts
import { USE_DEVICE_LANGUAGE } from '@angular/fire/compat/auth';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: USE_DEVICE_LANGUAGE, useValue: true },
]
})
export class AppModule { }
```
If you want to set a different language, you can use `LANGUAGE_CODE` DI Token
(*default: null*).
More info at the [firebase auth docs](https://firebase.google.com/docs/reference/js/auth.auth#authlanguagecode).
```ts
import { LANGUAGE_CODE } from '@angular/fire/compat/auth';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: LANGUAGE_CODE, useValue: 'fr' },
]
})
export class AppModule { }
```
### Persistence
Firebase Auth default behavior is to persist a user's session even after the
user closes the browser. To change the current type of persistence on the
current Auth instance for the currently saved Auth session and apply this type
of persistence for future sign-in requests, including sign-in with redirect
requests, you can use the `PERSISTENCE` DI Token (*default: null*).
The possible types are `'local'`, `'session'` or `'none'`. Read more at
[authentication state persistence](https://firebase.google.com/docs/auth/web/auth-state-persistence).
```ts
import { PERSISTENCE } from '@angular/fire/compat/auth';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: PERSISTENCE, useValue: 'session' },
]
})
export class AppModule { }
```
### Tenant
If you need to use multi-tenancy, you can set the current Auth instance's tenant
ID using `TENANT_ID` DI Token (*default: null*).
More tutorials regarding this topic are _coming soon_.
```ts
import { TENANT_ID } from '@angular/fire/compat/auth';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: TENANT_ID, useValue: 'tenant-id-app-one' },
]
})
export class AppModule { }
```
- [Multi-Tenancy Authentication](https://cloud.google.com/identity-platform/docs/multi-tenancy-authentication)
- [Firebase Auth Tenant](https://firebase.google.com/docs/reference/js/auth.auth#tenantid)
## UI Libraries
- Material Design : [ngx-auth-firebaseui](https://github.com/AnthonyNahas/ngx-auth-firebaseui)
- Bootstrap : [@firebaseui/ng-bootstrap](https://github.com/firebaseui/ng-bootstrap)
## Cordova
Learn how to [setup Firebase Authentication with Cordova](https://firebase.google.com/docs/auth/web/cordova) in the Firebase Guides.
================================================
FILE: docs/compat/auth/router-guards.md
================================================
# Route users with AngularFire guards
`AngularFireAuthGuard` provides a prebuilt [`canActivate` Router Guard](https://angular.io/api/router/CanActivate) using `AngularFireAuth`. By default unauthenticated users are not permitted to navigate to protected routes:
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
```ts
import { AngularFireAuthGuard } from '@angular/fire/compat/auth-guard';
export const routes: Routes = [
{ path: '', component: AppComponent },
{ path: 'items', component: ItemListComponent, canActivate: [AngularFireAuthGuard] },
]
```
## Customizing the behavior of `AngularFireAuthGuard`
To customize the behavior of `AngularFireAuthGuard`, you can pass an RXJS pipe through the route data's `authGuardPipe` key.
The `auth-guard` module provides the following pre-built pipes:
| Exported pipe | Functionality |
|-|-|
| `loggedIn` | The default pipe, rejects if the user is not authenticated. |
| `isNotAnonymous` | Rejects if the user is anonymous |
| `emailVerified` | Rejects if the user's email is not verified |
| `hasCustomClaim(claim)` | Rejects if the user does not have the specified claim |
| `redirectUnauthorizedTo(redirect)` | Redirect unauthenticated users to a different route |
| `redirectLoggedInTo(redirect)` | Redirect authenticated users to a different route |
Example use:
```ts
import { AngularFireAuthGuard, hasCustomClaim, redirectUnauthorizedTo, redirectLoggedInTo } from '@angular/fire/compat/auth-guard';
const adminOnly = () => hasCustomClaim('admin');
const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['login']);
const redirectLoggedInToItems = () => redirectLoggedInTo(['items']);
const belongsToAccount = (next) => hasCustomClaim(`account-${next.params.id}`);
export const routes: Routes = [
{ path: '', component: AppComponent },
{ path: 'login', component: LoginComponent, canActivate: [AngularFireAuthGuard], data: { authGuardPipe: redirectLoggedInToItems }},
{ path: 'items', component: ItemListComponent, canActivate: [AngularFireAuthGuard], data: { authGuardPipe: redirectUnauthorizedToLogin }},
{ path: 'admin', component: AdminComponent, canActivate: [AngularFireAuthGuard], data: { authGuardPipe: adminOnly }},
{ path: 'accounts/:id', component: AdminComponent, canActivate: [AngularFireAuthGuard], data: { authGuardPipe: belongsToAccount }}
];
```
Use the provided `canActivate` helper and spread syntax to make your routes more readable:
```ts
import { canActivate } from '@angular/fire/compat/auth-guard';
export const routes: Routes = [
{ path: '', component: AppComponent },
{ path: 'login', component: LoginComponent, ...canActivate(redirectLoggedInToItems) },
{ path: 'items', component: ItemListComponent, ...canActivate(redirectUnauthorizedToLogin) },
{ path: 'admin', component: AdminComponent, ...canActivate(adminOnly) },
{ path: 'accounts/:id', component: AdminComponent, ...canActivate(belongsToAccount) }
];
```
### Compose your own pipes
`AngularFireAuthGuard` pipes are RXJS operators which transform an optional User to a boolean or Array (for redirects). You can easily build your own to customize behavior further:
```ts
import { map } from 'rxjs/operators';
// This pipe redirects a user to their "profile edit" page or the "login page" if they're unauthenticated
// { path: 'profile', ...canActivate(redirectToProfileEditOrLogin) }
const redirectToProfileEditOrLogin = () => map(user => user ? ['profiles', user.uid, 'edit'] : ['login']);
```
The `auth-guard` modules provides a `customClaims` operator to reduce boiler plate when checking a user's claims:
```ts
import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';
import { customClaims } from '@angular/fire/compat/auth-guard';
// This pipe will only allow users with the editor role to access the route
// { path: 'articles/:id/edit', component: ArticleEditComponent, ...canActivate(editorOnly) }
const editorOnly = () => pipe(customClaims, map(claims => claims.role === 'editor'));
```
### Using router state
`AngularFireAuthGuard` will also accept `AuthPipeGenerator`s which generate `AuthPipe`s given the router state:
```ts
import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';
import { customClaims } from '@angular/fire/compat/auth-guard';
// Only allow navigation to the route if :userId matches the authenticated user's uid
// { path: 'user/:userId/edit', component: ProfileEditComponent, ...canActivate(onlyAllowSelf) }
const onlyAllowSelf = (next) => map(user => !!user && next.params.userId === user.uid);
// Only allow navigation to the route if the user has a custom claim matching :accountId
// { path: 'accounts/:accountId/billing', component: BillingDetailsComponent, ...canActivate(accountAdmin) }
const accountAdmin = (next) => pipe(customClaims, map(claims => claims[`account-${next.params.accountId}-role`] === 'admin'));
```
================================================
FILE: docs/compat/emulators/emulators.md
================================================
# Connect your app and start prototyping
In this guide, we'll look at how to use `@angular/fire` to connect an Angular application with Firebase Emulator Suite to start prototyping your apps.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
There are four supported emulators, all of them available at the Firebase suite workflow:
- [Authentication Emulator](https://firebase.google.com/docs/emulator-suite/connect_auth)
- [Realtime Database Emulator](https://firebase.google.com/docs/emulator-suite/connect_rtdb)
- [Cloud Firestore Emulator](https://firebase.google.com/docs/emulator-suite/connect_firestore)
- [Cloud Functions Emulator](https://firebase.google.com/docs/emulator-suite/connect_functions)
**The Auth Emulator only works with Firebase v8 and above, which is supported by `@angular/fire` 6.1.0 or higher**.
Before configuring these emulators at the Angular App, be sure to install the ones you need by following the [Install, configure and integrate Local Emulator Suite](https://firebase.google.com/docs/emulator-suite/install_and_configure) documentation.
_**TL;DR**_
Initialize firebase to your project (if you haven't) by running:
```shell
firebase init
```
Then launch the emulator setup wizard by running:
```shell
firebase init emulators
```
Follow the instructions to download whatever emulator you want to use then checkout that the `firebase.json` file got updated with the default ports per emulator, something like this:
```jsonc
{
// Existing firebase configuration ...
// Optional emulator configuration. Default
// values are used if absent.
"emulators": {
"firestore": {
"port": "8080"
},
"ui": {
"enabled": true, // Default is `true`
"port": 4000 // If unspecified, see CLI log for selected port
},
"auth": {
"port": "9099"
},
"functions": {
"port": "5001"
},
"database": {
"port": "9000"
},
"pubsub": {
"port": "8085"
}
}
}
```
Then launch the emulators by running
```shell
firebase emulators:start
```
Then you can visit
```shell
┌─────────────────────────────────────────────────────────────┐
│ ✔ All emulators ready! It is now safe to connect your app. │
│ i View Emulator UI at http://127.0.0.1:4000/ │
└─────────────────────────────────────────────────────────────┘
```
## Import the DI Tokens at your AppModule
Configuring your app to connect to local emulators is easily done by using dependency injection tokens provided by the library. However, there are slighty changes between 6.0.0 and 6.1.0 in the way it was done.
### 6.1.0 Method
Each module (database, firestore, auth, function) provides `USE_EMULATOR` token to configure the emulator `host` and `port` by passing a tuple of `[string, number]` values, which are set by default to `localhost` and the asigned port from your `firebase.json` file.
Update your `environment.ts` file:
```ts
export const environment = {
production: false,
useEmulators: true,
...
}
```
Import these tokens at your `app.module.ts` as follow:
```ts
import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/compat/auth';
import { USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/compat/database';
import { USE_EMULATOR as USE_FIRESTORE_EMULATOR } from '@angular/fire/compat/firestore';
import { USE_EMULATOR as USE_FUNCTIONS_EMULATOR } from '@angular/fire/compat/functions';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: USE_AUTH_EMULATOR, useValue: environment.useEmulators ? ['http://localhost', 9099] : undefined },
{ provide: USE_DATABASE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9000] : undefined },
{ provide: USE_FIRESTORE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 8080] : undefined },
{ provide: USE_FUNCTIONS_EMULATOR, useValue: environment.useEmulators ? ['localhost', 5001] : undefined },
]
})
export class AppModule { }
```
The environment `useEmulators` flag is used to control whenever the app should connect to the emulators, which is usually done in non-production environments.
Also you can opt-in the new way of setting the Cloud Functions [origin](https://firebase.google.com/docs/functions/locations) in Firebase v8 by using the `NEW_ORIGIN_BEHAVIOR` token in conjuction with the already present `ORIGIN` token.
```ts
import { isDevMode, NgModule } from '@angular/core';
import { ORIGIN as FUNCTIONS_ORIGIN, NEW_ORIGIN_BEHAVIOR } from '@angular/fire/compat/functions';
@NgModule({
// ... Existing configuration
providers: [
// ... Existing Providers
{ provide: NEW_ORIGIN_BEHAVIOR, useValue: true },
{ provide: FUNCTIONS_ORIGIN, useFactory: () => isDevMode() ? undefined : location.origin },
]
})
export class AppModule { }
```
### 6.0.0 Method
With the exception of the Auth Emulator, the old way of setting the `host` and `port` for each emulator was done using a different set of tokens by passing the entire url path as string.
```ts
import { URL as DATABASE_URL } from '@angular/fire/compat/database';
import { ORIGIN as FUNCTIONS_ORIGIN } from '@angular/fire/compat/functions';
import { SETTINGS as FIRESTORE_SETTINGS } from '@angular/fire/compat/firestore';
@NgModule({
// ... Existing configuration
providers: [
{
provide: DATABASE_URL,
useValue: environment.useEmulators ? `http://localhost:9000?ns=${environment.firebase.projectId}` : undefined
},
{ provide: FIRESTORE_SETTINGS, useValue: environment.useEmulators ? { host: 'localhost:8080', ssl: false } : {} },
{ provide: FUNCTIONS_ORIGIN, useFactory: environment.useEmulators ? 'http://localhost:5001' : undefined },
]
})
export class AppModule { }
```
For older versions, please upgrade your app to latest version to get the advantages of these new features :rocket:
================================================
FILE: docs/compat/firestore/collections.md
================================================
# 3. Collections in AngularFirestore
> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, there are no tables or rows. Instead, you store data in *documents*, which are organized into *collections*.
Each *document* contains a set of key-value pairs. Cloud Firestore is optimized for storing large collections of small documents.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
## Using `AngularFirestoreCollection`
The `AngularFirestoreCollection` service is a wrapper around the native Firestore SDK's [`CollectionReference`](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.CollectionReference) and [`Query`](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Query) types. It is a generic service that provides you with a strongly typed set of methods for manipulating and streaming data. This service is designed for use as an `@Injectable()`.
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
export interface Item { name: string; }
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
{{ item.name }}
</li>
</ul>
`
})
export class AppComponent {
private itemsCollection: AngularFirestoreCollection<Item>;
items: Observable<Item[]>;
constructor(private afs: AngularFirestore) {
this.itemsCollection = afs.collection<Item>('items');
this.items = this.itemsCollection.valueChanges();
}
addItem(item: Item) {
this.itemsCollection.add(item);
}
}
```
The `AngularFirestoreCollection` is a service you use to create streams of the collection and perform data operations on the underyling collection.
### The `DocumentChangeAction` type
With the exception of the `valueChanges()`, each streaming method returns an Observable of `DocumentChangeAction[]`.
A `DocumentChangeAction` gives you the `type` and `payload` properties. The `type` tells when what `DocumentChangeType` operation occured (`added`, `modified`, `removed`). The `payload` property is a `DocumentChange` which provides you important metadata about the change and a `doc` property which is the `DocumentSnapshot`.
```ts
interface DocumentChangeAction {
//'added' | 'modified' | 'removed';
type: DocumentChangeType;
payload: DocumentChange;
}
interface DocumentChange {
type: DocumentChangeType;
doc: DocumentSnapshot;
oldIndex: number;
newIndex: number;
}
interface DocumentSnapshot {
exists: boolean;
ref: DocumentReference;
id: string;
metadata: SnapshotMetadata;
data(): DocumentData;
get(fieldPath: string): any;
}
```
## Streaming collection data
There are multiple ways of streaming collection data from Firestore.
### `valueChanges({ idField?: string })`
**What is it?** - The current state of your collection. Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the document data is included. Optionally, you can pass an options object with an `idField` key containing a string. If provided, the returned JSON objects will include their document ID mapped to a property with the name provided by `idField`.
**Why would you use it?** - When you just need a list of data. No document metadata is attached to the resulting array which makes it simple to render to a view.
**When would you not use it?** - When you need a more complex data structure than an array.
**Best practices** - Use this method to display data on a page. It's simple but effective. Use `.snapshotChanges()` once your needs become more complex.
#### Example of persisting a Document Id
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
export interface Item { id: string; name: string; }
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
{{ item.name }}
</li>
</ul>
`
})
export class AppComponent {
private itemsCollection: AngularFirestoreCollection<Item>;
items: Observable<Item[]>;
constructor(private readonly afs: AngularFirestore) {
this.itemsCollection = afs.collection<Item>('items');
this.items = this.itemsCollection.valueChanges({ idField: 'customID' });
}
addItem(name: string) {
// Persist a document id
const id = this.afs.createId();
const item: Item = { id, name };
this.itemsCollection.doc(id).set(item);
}
}
```
### `snapshotChanges()`
**What is it?** - The current state of your collection. Returns an Observable of data as a synchronized array of `DocumentChangeAction[]`.
**Why would you use it?** - When you need a list of data but also want to keep around metadata. Metadata provides you the underyling `DocumentReference`, document id, and array index of the single document. Having the document's id around makes it easier to use data manipulation methods. This method gives you more horsepower with other Angular integrations such as ngrx, forms, and animations due to the `type` property. The `type` property on each `DocumentChangeAction` is useful for ngrx reducers, form states, and animation states.
**When would you not use it?** - When you need a more complex data structure than an array or if you need to process changes as they occur. This array is synchronized with the remote and local changes in Firestore.
**Best practices** - Use an observable operator to transform your data from `.snapshotChanges()`. Don't return the `DocumentChangeAction[]` to the template. See the example below.
#### Example
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface Shirt { name: string; price: number; }
export interface ShirtId extends Shirt { id: string; }
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let shirt of shirts | async">
{{ shirt.name }} is {{ shirt.price }}
</li>
</ul>
`
})
export class AppComponent {
private shirtCollection: AngularFirestoreCollection<Shirt>;
shirts: Observable<ShirtId[]>;
constructor(private readonly afs: AngularFirestore) {
this.shirtCollection = afs.collection<Shirt>('shirts');
// .snapshotChanges() returns a DocumentChangeAction[], which contains
// a lot of information about "what happened" with each change. If you want to
// get the data and the id use the map operator.
this.shirts = this.shirtCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Shirt;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
}
}
```
### `stateChanges()`
**What is it?** - Returns an Observable of the most recent changes as a `DocumentChangeAction[]`.
**Why would you use it?** - The above methods return a synchronized array sorted in query order. `stateChanges()` emits changes as they occur rather than syncing the query order. This works well for ngrx integrations as you can build your own data structure in your reducer methods.
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of AngularFirestore.
#### Example
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface AccountDeposit { description: string; amount: number; }
export interface AccountDepositId extends AccountDeposit { id: string; }
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let deposit of deposits | async">
{{ deposit.description }} for {{ deposit.amount }}
</li>
</ul>
`
})
export class AppComponent {
private depositCollection: AngularFirestoreCollection<AccountDeposit>;
deposits: Observable<AccountDepositId[]>;
constructor(private readonly afs: AngularFirestore) {
this.depositCollection = afs.collection<AccountDeposit>('deposits');
this.deposits = this.depositCollection.stateChanges(['added']).pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as AccountDeposit;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
}
}
```
### `auditTrail()`
**What is it?** - Returns an Observable of `DocumentChangeAction[]` as they occur. Similar to `stateChanges()`, but instead it keeps around the trail of events as an array.
**Why would you use it?** - This method is like `stateChanges()` except it is not ephemeral. It collects each change in an array as they occur. This is useful for ngrx integrations where you need to replay the entire state of an application. This also works as a great debugging tool for all applications. You can simply write `afs.collection('items').auditTrail().subscribe(console.log)` and check the events in the console as they occur.
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of AngularFirestore.
#### Example
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface AccountLogItem { description: string; amount: number; }
export interface AccountLogItemId extends AccountLogItem { id: string; }
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let log of accountLogs | async">
{{ log.description }} for {{ log.amount }}
</li>
</ul>
`
})
export class AppComponent {
private accountLogCollection: AngularFirestoreCollection<AccountLogItem>;
accountLogs: Observable<AccountLogItemId[]>;
constructor(private readonly afs: AngularFirestore) {
this.accountLogCollection = afs.collection<AccountLogItem>('accountLog');
this.accountLogs = this.accountLogCollection.auditTrail().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as AccountLogItem;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
}
}
```
### Limiting events
There are three `DocumentChangeType`s in Firestore: `added`, `removed`, and `modified`. Each streaming method listens to all three by default. However, you may only be interested in one of these events. You can specify which events you'd like to use through the first parameter of each method:
#### Basic example
```ts
constructor(private afs: AngularFirestore): {
this.itemsCollection = afs.collection<Item>('items');
this.items = this.itemsCollection.snapshotChanges(['added', 'removed']);
}
```
#### Component example
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
{{ item.name }}
</li>
</ul>
`
})
export class AppComponent {
private itemsCollection: AngularFirestoreCollection<Item>;
items: Observable<Item[]>;
constructor(private afs: AngularFirestore) {
this.itemsCollection = afs.collection<Item>('items');
this.items = this.itemsCollection.valueChanges(['added', 'removed']);
}
}
```
## State based vs. action based
Each one of these methods falls into two categories: state based and action based. State based methods return the state of your collection "as-is". Whereas action based methods return "what happened" in your collection.
For example, a user updates the third item in a list. In a state based method like `.valueChanges()` will update the third item in the collection and return an array of JSON data. This is how your state looks.
## Adding documents to a collection
To add a new document to a collection with a generated id use the `add()` method. This method uses the type provided by the generic class to validate it's type structure.
#### Basic example
```ts
constructor(private afs: AngularFirestore): {
const shirtsCollection = afs.collection<Item>('tshirts');
shirtsCollection.add({ name: 'item', price: 10 });
}
```
## Manipulating individual documents
To retrieve, update, or delete an individual document you can use the `doc()` method. This method returns an `AngularFirestoreDocument`, which provides methods for streaming, updating, and deleting. [See Using Documents with AngularFirestore for more information on how to use documents](documents.md).
### [Next Step: Querying Collections in AngularFirestore](querying-collections.md)
================================================
FILE: docs/compat/firestore/documents.md
================================================
# 2. Documents in AngularFirestore
> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, there are no tables or rows. Instead, you store data in *documents*, which are organized into *collections*.
Each *document* contains a set of key-value pairs. Cloud Firestore is optimized for storing large collections of small documents.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
## Using `AngularFirestoreDocument`
The `AngularFirestoreDocument` service is a wrapper around the native Firestore SDK's [`DocumentReference` type](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference). It is a generic service that provides you with a strongly typed set of methods for manipulating and streaming data. This service is designed for use as an `@Injectable()`.
```ts
import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';
export interface Item { name: string; }
@Component({
selector: 'app-root',
template: `
<div>
{{ (item | async)?.name }}
</div>
`
})
export class AppComponent {
private itemDoc: AngularFirestoreDocument<Item>;
item: Observable<Item>;
constructor(private afs: AngularFirestore) {
this.itemDoc = afs.doc<Item>('items/1');
this.item = this.itemDoc.valueChanges();
}
update(item: Item) {
this.itemDoc.update(item);
}
}
```
### The `DocumentChangeAction` type
With the exception of the `valueChanges()`, each streaming method returns an Observable of `DocumentChangeAction[]`.
A `DocumentChangeAction` gives you the `type` and `payload` properties. The `type` tells when what `DocumentChangeType` operation occured (`added`, `modified`, `removed`). The `payload` property is a `DocumentChange` which provides you important metadata about the change and a `doc` property which is the `DocumentSnapshot`.
```ts
interface DocumentChangeAction {
//'added' | 'modified' | 'removed';
type: DocumentChangeType;
payload: DocumentSnapshot;
}
interface DocumentChange {
type: DocumentChangeType;
doc: DocumentSnapshot;
oldIndex: number;
newIndex: number;
}
interface DocumentSnapshot {
exists: boolean;
ref: DocumentReference;
id: string;
metadata: SnapshotMetadata;
data(): DocumentData;
get(fieldPath: string): any;
}
```
## Streaming document data
There are multiple ways of streaming collection data from Firestore.
### `valueChanges({ idField?: string })`
**What is it?** - Returns an Observable of document data. All Snapshot metadata is stripped. This method provides only the data. Optionally, you can pass an options object with an `idField` key containing a string. If provided, the returned object will include its document ID mapped to a property with the name provided by `idField`.
**Why would you use it?** - When you just need the object data. No document metadata is attached which makes it simple to render to a view.
**When would you not use it?** - When you need document metadata.
### `snapshotChanges()`
**What is it?** - Returns an Observable of data as a `DocumentChangeAction`.
**Why would you use it?** - When you need the document data but also want to keep around metadata. This metadata provides you the underyling `DocumentReference` and document id. Having the document's id around makes it easier to use data manipulation methods. This method gives you more horsepower with other Angular integrations such as ngrx, forms, and animations due to the `type` property. The `type` property on each `DocumentChangeAction` is useful for ngrx reducers, form states, and animation states.
**When would you not use it?** - When you simply need to render data to a view and don't want to do any extra processing.
## Manipulating documents
AngularFirestore provides methods for setting, updating, and deleting document data.
- `set(data: T)` - Destructively updates a document's data.
- `update(data: T)` - Non-destructively updates a document's data.
- `delete()` - Deletes an entire document. Does not delete any nested collections.
## Querying?
Querying has no effect on documents. Documents are a single object and querying effects a range of multiple documents. If you are looking for querying then you want to use a collection.
## Retrieving nested collections
Nesting collections is a great way to structure your data. This allows you to group related data structures together. If you are creating a "Task List" site, you can group "tasks" under a user: `user/<uid>/tasks`.
To retrieve a nested collection use the `collection(path: string)` method.
```ts
constructor(private afs: AngularFirestore) {
this.userDoc = afs.doc<Item>('user/david');
this.tasks = this.userDoc.collection<Task>('tasks').valueChanges();
}
```
### [Next Step: Collections in AngularFirestore](collections.md)
================================================
FILE: docs/compat/firestore/offline-data.md
================================================
# Offline Data in Firestore
> Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline. You can write, read, listen to, and query the cached data. When the device comes back online, Cloud Firestore synchronizes any local changes made by your app to the data stored remotely in Cloud Firestore.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
**Offline persistence is an experimental feature that is supported only by the Chrome, Safari, and Firefox web browsers.** If a user opens multiple browser tabs that point to the same Cloud Firestore database, and offline persistence is enabled, Cloud Firestore will work correctly only in the first tab.
## Enable Offline Data in AngularFirestore
To enable offline persistence in your AngularFire application, call `enablePersistence()` when you are importing `AngularFirestoreModule` into your `@NgModule`:
```ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFirestoreModule.enablePersistence(),
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
While offline your listeners will receive listen events when the locally cached data changes. You can use to Documents and Collections normally.
To check whether you're receiving data from the server or the cache, use the `fromCache` property on the `SnapshotMetadata` in your snapshot event. If `fromCache` is true, the data came from the cache and might be stale or incomplete. If `fromCache` is false, the data is complete and current with the latest updates on the server.
[To learn more about Offline Persistence in Firestore, check out the Firebase documentation](https://firebase.google.com/docs/firestore/enable-offline).
================================================
FILE: docs/compat/firestore/querying-collections.md
================================================
# 4. Querying Collections in AngularFirestore
> Firestore has [powerful querying syntax](https://firebase.google.com/docs/firestore/query-data/queries) and the `AngularFirestoreCollection` provides a thin wrapper around it. This keeps you from having to learn two query syntax systems.
If you know the [Firestore query API](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Query) then you know how to query in AngularFirestore.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
## Creating a query with primitive/scalar values
Queries are created by building on the [`firebase.firestore.CollectionReference`](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.CollectionReference).
```ts
afs.collection('items', ref => ref.where('size', '==', 'large'))
```
### Query options
| method | purpose |
| ---------|--------------------|
| `where` | Create a new query. *Can be chained to form complex queries.* |
| `orderBy` | Sort by the specified field, in descending or ascending order. |
| `limit` | Sets the maximum number of items to return. |
| `startAt` | Results start at the provided document (inclusive). |
| `startAfter` | Results start after the provided document (exclusive). |
| `endAt` | Results end at the provided document (inclusive). |
| `endBefore` | Results end before the provided document (exclusive). |
[To learn more about querying and sorting in Firestore, check out the Firebase documentation](https://firebase.google.com/docs/firestore/query-data/queries).
## Invalid query combinations
Range filters can only be specified on a single field:
```ts
// WARNING: Do not copy and paste. This will not work!
ref.where('state', '>=', 'CA')
.where('population', '>', 100000)
```
Range filter and orderBy cannot be on different fields:
```ts
// WARNING: Do not copy and paste. This will not work!
ref.where('population', '>', 100000).orderBy('country')
```
Range filters / orderBy cannot be used in conjuction with user-defined data, they require composite indexes be defined on the specific fields.
```ts
// WARNING: Do not copy and paste. This will not work!
ref.where('tags.awesome', '==', true).orderBy('population')
```
## Dynamic querying
To enable dynamic queries one should lean on RxJS Operators like `switchMap`.
An RxJS Subject is imported below. A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners. See, [What is a Subject](http://reactivex.io/rxjs/manual/overview.html#subject) for more information.
When we call [`switchMap` on the Subject](https://www.learnrxjs.io/operators/transformation/switchmap.html), we can map each value to a new Observable; in this case a database query.
```ts
const size$ = new Subject<string>();
const queryObservable = size$.pipe(
switchMap(size =>
afs.collection('items', ref => ref.where('size', '==', size)).valueChanges()
)
);
// subscribe to changes
queryObservable.subscribe(queriedItems => {
console.log(queriedItems);
});
// trigger the query
size$.next('large');
// re-trigger the query!!!
size$.next('small');
```
### Example app
[See this example in action on StackBlitz](https://stackblitz.com/edit/angularfire-db-api-fbad9p).
```ts
import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/compat/firestore';
import { Observable, BehaviorSubject, combineLatest } from 'rxjs';
import { switchMap } from 'rxjs/operators';
export interface Item {
text: string;
color: string;
size: string;
}
@Component({
selector: 'app-root',
template: `
<div *ngIf="items$ | async; let items; else loading">
<ul>
<li *ngFor="let item of items">
{{ item.text }}
</li>
</ul>
<div *ngIf="items.length === 0">No results, try clearing filters</div>
</div>
<ng-template #loading>Loading…</ng-template>
<div>
<h4>Filter by size</h4>
<button (click)="filterBySize('small')">Small</button>
<button (click)="filterBySize('medium')">Medium</button>
<button (click)="filterBySize('large')">Large</button>
<button (click)="filterBySize(null)" *ngIf="this.sizeFilter$.getValue()">
<em>clear filter</em>
</button>
</div>
<div>
<h4>Filter by color</h4>
<button (click)="filterByColor('red')">Red</button>
<button (click)="filterByColor('green')">Blue</button>
<button (click)="filterByColor('blue')">Green</button>
<button (click)="filterByColor(null)" *ngIf="this.colorFilter$.getValue()">
<em>clear filter</em>
</button>
</div>
`,
})
export class AppComponent {
items$: Observable<Item[]>;
sizeFilter$: BehaviorSubject<string|null>;
colorFilter$: BehaviorSubject<string|null>;
constructor(afs: AngularFirestore) {
this.sizeFilter$ = new BehaviorSubject(null);
this.colorFilter$ = new BehaviorSubject(null);
this.items$ = combineLatest(
this.sizeFilter$,
this.colorFilter$
).pipe(
switchMap(([size, color]) =>
afs.collection('items', ref => {
let query : firebase.firestore.CollectionReference | firebase.firestore.Query = ref;
if (size) { query = query.where('size', '==', size) };
if (color) { query = query.where('color', '==', color) };
return query;
}).valueChanges()
)
);
}
filterBySize(size: string|null) {
this.sizeFilter$.next(size);
}
filterByColor(color: string|null) {
this.colorFilter$.next(color);
}
}
```
**To run the above example as is, you need to have sample data in your Firebase database with the following structure:**
```json
{
"items": {
"a" : {
"size" : "small",
"text" : "small thing",
"color" : "red"
},
"b" : {
"size" : "medium",
"text" : "medium sample",
"color" : "red"
},
"c" : {
"size" : "large",
"text" : "large widget",
"color" : "green"
}
}
}
```
## Collection Group Queries
To query across collections and sub-collections with the same name anywhere in Firestore, you can use collection group queries.
Collection Group Queries allow you to have a more nested data-structure without sacrificing performance. For example, we could easily query all comments a user posted; even if the comments were stored as a sub-collection under `Articles/**` or even nested deeply (`Articles/**/Comments/**/Comments/**/...`):
```ts
constructor(private afs: AngularFirestore) { }
ngOnInit() {
...
// Get all the user's comments, no matter how deeply nested
this.comments$ = afs.collectionGroup('Comments', ref => ref.where('user', '==', userId))
.valueChanges({ idField: 'docId' });
}
```
`collectionGroup` returns an `AngularFirestoreCollectionGroup` which is similar to `AngularFirestoreCollection`. The main difference is that `AngularFirestoreCollectionGroup` has no data operation methods such as `add` because it doesn't have a concrete reference.
### [Next Step: Getting started with Firebase Authentication](../auth/getting-started.md)
================================================
FILE: docs/compat/functions/functions.md
================================================
# AngularFireFunctions
> The Cloud Functions for Firebase client SDKs let you call functions directly from a Firebase app. To call a function from your app in this way, write and deploy an HTTPS Callable function in Cloud Functions, and then add client logic to call the function from your app.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
### Import the `NgModule`
Cloud Functions for AngularFire is contained in the `@angular/fire/functions` module namespace. Import the `AngularFireFunctionsModule` in your `NgModule`. This sets up the `AngularFireFunction` service for dependency injection.
```ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireFunctionsModule } from '@angular/fire/compat/functions';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireFunctionsModule
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
### Injecting the AngularFireFunctions service
Once the `AngularFireFunctionsModule` is registered you can inject the `AngularFireFunctions` service.
```ts
import { Component } from '@angular/core';
import { AngularFireFunctions } from '@angular/fire/compat/functions';
@Component({
selector: 'app-component',
template: ``
})
export class AppComponent {
constructor(private fns: AngularFireFunctions) { }
}
```
### Creating a callable function
AngularFireFunctions is super easy. You create a function on the server side and then "call" it by its name with the client library.
| method | |
| ---------|--------------------|
| `httpCallable(name: string): (data: T) ` | Creates a callable function based on a function name. Returns a function that can create the observable of the http call. |
```ts
import { Component } from '@angular/core';
import { AngularFireFunctions } from '@angular/fire/compat/functions';
@Component({
selector: 'app-root',
template: `{ data$ | async }`
})
export class AppComponent {
constructor(private fns: AngularFireFunctions) {
const callable = fns.httpsCallable('my-fn-name');
this.data$ = callable({ name: 'some-data' });
}
}
```
Notice that calling `httpsCallable()` does not initiate the request. It creates a function, which when called creates an Observable, subscribe or convert it to a Promise to initiate the request.
## Configuration via Dependency Injection
### Functions Region
Allow configuration of the Function's region by adding `REGION` to the `providers` section of your `NgModule`. The default is `us-central1`.
```ts
import { NgModule } from '@angular/core';
import { AngularFireFunctionsModule, REGION } from '@angular/fire/compat/functions';
@NgModule({
imports: [
...
AngularFireFunctionsModule,
...
],
...
providers: [
{ provide: REGION, useValue: 'asia-northeast1' }
]
})
export class AppModule {}
```
### Cloud Functions emulator
Point callable Functions to the Cloud Function emulator by adding `USE_EMULATOR` to the `providers` section of your `NgModule`.
```ts
import { NgModule } from '@angular/core';
import { AngularFireFunctionsModule, USE_EMULATOR } from '@angular/fire/compat/functions';
@NgModule({
imports: [
...
AngularFireFunctionsModule,
...
],
...
providers: [
{ provide: USE_EMULATOR, useValue: ['localhost', 5001] }
]
})
export class AppModule {}
```
[Learn more about integration with the Firebase Emulator suite on our dedicated guide here](../emulators/emulators.md).
### Firebase Hosting integration
If you serve your app using [Firebase Hosting](https://firebase.google.com/docs/hosting/), you can configure Functions to be served from the same domain as your app. This will avoid an extra round-trip per function call due to [CORS preflight request](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request). This only applies to sites hosted via firebase on `us-central1`.
To set this up, you first need to update your `hosting` section in `firebase.json` and add one `rewrite` rule per function:
```json
"hosting": {
"rewrites": [
{
"source": "/someFunction",
"function": "someFunction"
},
{
"source": "/anotherFunction",
"function": "anotherFunction"
},
...
]
}
```
Deploy your hosting project to the new settings go into effect, finally configure functions origin to point at your app domain:
```ts
import { NgModule } from '@angular/core';
import { AngularFireFunctionsModule, ORIGIN, NEW_ORIGIN_BEHAVIOR } from '@angular/fire/compat/functions';
@NgModule({
imports: [
...
AngularFireFunctionsModule,
...
],
...
providers: [
{ provide: NEW_ORIGIN_BEHAVIOR, useValue: true },
{ provide: ORIGIN, useValue: 'https://project-name.web.app' }
]
})
export class AppModule {}
```
================================================
FILE: docs/compat/messaging/messaging.md
================================================
# AngularFireMessaging
> The FCM JavaScript API lets you receive notification messages in web apps running in browsers that support the Push API.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
### AngularFireMessaging is not out-of-the-box compatible with the Angular Service Worker
If you are using the Angular Service Worker, you are not currently able to use AngularFireMessaging out-of-the-box.
If you'd like this feature please add your 👍 to [this issue](https://github.com/angular/angular/issues/34352).
Your alternatives are to use
- [WorkboxJS](https://developers.google.com/web/tools/workbox/)
- Follow the discussion in [this issue](https://github.com/angular/angular/issues/34352) and [here](https://github.com/angular/angularfire/discussions/1923), manually registering the Angular Service Worker
- The Firebase Messaging Service Worker, which is detailed below
### Import the `NgModule`
Push Notifications for AngularFire are contained in the `@angular/fire/messaging` module namespace. Import the `AngularFireMessagingModule` in your `NgModule`. This sets up the `AngularFireMessaging` service for dependency injection.
```ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireMessagingModule } from '@angular/fire/compat/messaging';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireMessagingModule
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
### Setting up the Firebase Messaging Service Worker
There are two parts to Firebase Messaging, a Service Worker and the DOM API. AngularFireMessaging allows you to request permission, get tokens, delete tokens, and subscribe to messages on the DOM side. To register to receive notifications you need to set up the Service Worker. [The official Firebase documentation for setting up the details exactly how to do that](https://firebase.google.com/docs/cloud-messaging/js/client).
You can either use the `firebase-messaging-sw.js` file provided in the docs or you can set your own Service Worker to import that script. Make sure to set up your `angular.json` file to copy over the Service Worker file:
```json
"assets": [
"assets",
"favicon.ico",
"firebase-messaging-sw.js",
"manifest.json"
],
```
[Warning] Remember update the `firebase-messaging-sw.js` everytime you update the `firebase` in package.json. The missmatch version could lead to unable to receive notification in `foreground`, you can create your `firebase-messaging-sw.js` like this:
```js
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/[the number of version matching with firebase in package.json]/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/[for example: 7.16.1]/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
apiKey: '<your-key>',
authDomain: '<your-project-authdomain>',
databaseURL: '<your-database-URL>',
projectId: '<your-project-id>',
storageBucket: '<your-storage-bucket>',
messagingSenderId: '<your-messaging-sender-id>'
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
```
### Requesting permission
Once you have the Firebase Messaging Service Worker set up and installed, you need to request permission to send a user notifications. While the browser will popup a UI for you, it is highly recommend to ask the user for permission with a custom UI and only ask when it makes sense. If you blindly ask for permission, you have an extremely high chance of getting denied or blocked.
```ts
import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
@Component({
selector: 'app-root',
template: `
<button (click)="requestPermission()">
Hello this is a chat app. You should let us send you notifications for this reason.
</button>
`
})
export class AppComponent {
constructor(private afMessaging: AngularFireMessaging) { }
requestPermission() {
this.afMessaging.requestPermission
.subscribe(
() => { console.log('Permission granted!'); },
(error) => { console.error(error); },
);
}
}
```
Once you have the permission of the user, you need their token. You can do this with the `getToken` observable or the `tokenChanges` observable. The `tokenChanges` observable listens for token refreshes whereas the `getToken` observable is a one-time call.
```ts
import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
import { mergeMapTo } from 'rxjs/operators';
@Component({
selector: 'app-root',
template: `
<button (click)="requestPermission()">
Hello this is a chat app. You should let us send you notifications for this reason.
</button>
`
})
export class AppComponent {
constructor(private afMessaging: AngularFireMessaging) { }
requestPermission() {
this.afMessaging.requestPermission
.pipe(mergeMapTo(this.afMessaging.tokenChanges))
.subscribe(
(token) => { console.log('Permission granted! Save to the server!', token); },
(error) => { console.error(error); },
);
}
}
```
Once you have a user's token, you need to save it to the server in order to send them notifications in response to events. Let's say you want to send a push each time a user sends a chat message. Once a user grants permission, you can send the token to the Realtime Database or Cloud Firestore and associate it with a unique id, like a Firebase Auth UID. You can then create a Cloud Function trigger that looks up the user's token when a chat message is created.
### Shortcutting token requests
An easier way of requesting permission and getting tokens is with the `requestToken` observable. It combines the two steps above into one observable.
```ts
import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
@Component({
selector: 'app-root',
template: `
<button (click)="requestPermission()">
Hello this is a chat app. You should let us send you notifications for this reason.
</button>
`
})
export class AppComponent {
constructor(private afMessaging: AngularFireMessaging) { }
requestPermission() {
this.afMessaging.requestToken
.subscribe(
(token) => { console.log('Permission granted! Save to the server!', token); },
(error) => { console.error(error); },
);
}
}
```
The `requestToken` observable uses the `tokenChanges` observable to listen to refreshes.
### Deleting tokens
Need to delete a user's token? Not a problem.
```ts
import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
import { mergeMap } from 'rxjs/operators';
@Component({
selector: 'app-root',
template: `
<button (click)="deleteToken()">
Delete my token
</button>
`
})
export class AppComponent {
constructor(private afMessaging: AngularFireMessaging) { }
deleteToken() {
this.afMessaging.getToken
.pipe(mergeMap(token => this.afMessaging.deleteToken(token)))
.subscribe(
(token) => { console.log('Token deleted!'); },
);
}
}
```
The code above requests the current user's token and passes it to the `deleteToken()` observable.
### Subscribing to foreground messages
Once you have a user's token and they are subscribed, you can listen to messages in the foreground. The Firebase Messaging Service Worker handles background push notifications.
```ts
import { Component } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
@Component({
selector: 'app-root',
template: `
<button (click)="listen()">
Get notified!
</button>
`
})
export class AppComponent {
constructor(private afMessaging: AngularFireMessaging) { }
listen() {
this.afMessaging.messages
.subscribe((message) => { console.log(message); });
}
}
```
### Sending notifications
[Sending a notification](https://firebase.google.com/docs/cloud-messaging/js/first-message) requires a call to a server. You can do this directly with an HTTP call or you can even build a Cloud Function to do this in response to an event. A Cloud Function trigger is ideal because you have trusted access to the database and can securely look up tokens to send to the right user. If you want to send push notifications via HTTP requests you'll need to secure the API call. This is usually done with a Firebase Auth UID. On the server you can verify the UID with the Firebase Admin SDK and allow access to get a user's push id.
The [Firebase Admin SDK has helper functions for sending notifications](https://firebase.google.com/docs/cloud-messaging/admin/send-messages) to the user and subscribing them to topics, which [simplifies sending grouped messages](https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions).
================================================
FILE: docs/compat/performance/getting-started.md
================================================
# Getting started with Performance Monitoring
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
## Automatic page load tracing
Understand your Angular application's real-world performance with [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon). Performance Monitoring automatically provides a trace for **page load** when you add `AngularFirePerformanceModule` into your App Module's imports.
```ts
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirePerformanceModule, PerformanceMonitoringService } from '@angular/fire/compat/performance';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFirePerformanceModule,
...
],
providers: [
PerformanceMonitoringService
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
The page load trace breaks down into the following default metrics:
* [first paint traces](https://firebase.google.com/docs/perf-mon/automatic-web#first-paint) — measure the time between when the user navigates to a page and when any visual change happens
* [first contentful paint traces](https://firebase.google.com/docs/perf-mon/automatic-web#contentful-paint) — measure the time between when a user navigates to a page and when meaningful content displays, like an image or text
* [domInteractive traces](https://firebase.google.com/docs/perf-mon/automatic-web#domInteractive) — measure the time between when the user navigates to a page and when the page is considered interactive for the user
* [domContentLoadedEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#domContentLoaded) — measure the time between when the user navigates to a page and when the initial HTML document is completely loaded and parsed
* [loadEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#loadEventEnd) — measure the time between when the user navigates to the page and when the current document's load event completes
* [first input delay traces](https://firebase.google.com/docs/perf-mon/automatic-web#input-delay) — measure the time between when the user interacts with a page and when the browser is able to respond to that input
* **Angular specific traces** - `PerformanceMonitoringService` will measure the time needed for `ApplicationRef.isStable` to be true, an important metric to track if you're concerned about solving Zone.js issues for proper functionality of NGSW and Server Side Rendering
### Measuring First Input Delay
> First Input Delay (FID) measures the time from when a user first interacts with your site (i.e. when they click a link, tap on a button, or use a custom, JavaScript-powered control) to the time when the browser is actually able to respond to that interaction. [See the article on the Google Developer's Blog for more information on FID.](https://developers.google.com/web/updates/2018/05/first-input-delay)
In order to track first input delay, you'll want to [polyfill the browser performance API](https://github.com/GoogleChromeLabs/first-input-delay):
`npm install --save-dev first-input-delay`
Then add `import 'first-input-delay';` to your `src/polyfills.ts`.
## Manual traces
You can inject `AngularFirePerformance` to perform manual traces.
```ts
constructor(private performance: AngularFirePerformance) {}
...
const trace = await this.performance.trace('some-trace');
trace.start();
...
trace.stop();
```
## RXJS operators
AngularFire provides a number of RXJS operators which wrap the User Timing API. These are picked up by performance monitoring tools such as Chrome Inspector and Firebase Performance Monitoring.
```ts
import { trace } from '@angular/fire/compat/performance';
...
constructor(private performance: AngularFirePerformance, private afs: AngularFirestore) {}
ngOnInit() {
this.articles = afs.collection('articles')
.collection('articles', ref => ref.orderBy('publishedAt', 'desc'))
.snapshotChanges()
.pipe(
// measure the amount of time between the Observable being subscribed to and first emission (or completion)
trace('getArticles'),
map(articles => ...)
);
}
```
### `trace(name: string)`
The most basic operator, `trace` will measure the amount of time it takes for your observable to either complete or emit its first value. Beyond the basic trace there are several other operators:
<h3>
<pre>
traceUntil(
name: string,
test: (T) => Boolean,
options?: { orComplete?: true }
)
</pre>
</h3>
Trace the observable until the first emission that passes the provided test.
If the `orComplete` option is passed it will complete the trace when the observable completes, even if an emission never passed the provided test.
<h3>
<pre>
traceWhile(
name: string,
test: (T) => Boolean,
options?: { orComplete?: true }
)
</pre>
</h3>
Starting with an emission that passes the provided test, trace until an emission fails the test.
If the `orComplete` option is passed it will complete any existing trace when the observable completes.
### `traceUntilLast(name: string)`
Trace the observable until completion.
### `traceUntilFirst(name: string)`
Traces the observable until the first emission.
## Advanced usage
### Configuration via Dependency Injection
Set `INSTRUMENTATION_ENABLED` or `DATA_COLLECTION_ENABLED` to false disable all automatic and custom traces respectively.
================================================
FILE: docs/compat/remote-config/getting-started.md
================================================
<h1>Getting started with Remote Config <em><abbr title="beta">β<abbr></em></h1>
`AngularFireRemoteConfig` dynamically imports the `firebase/remote-config` library on demand, provides convenience observables, pipes, and a promisified version of the [Firebase Remote Config SDK (`firebase.remoteConfig.RemoteConfig`)](https://firebase.google.com/docs/reference/js/firebase.remoteconfig.RemoteConfig).
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
### API:
```ts
class AngularFireRemoteConfigModule { }
interface ConfigTemplate {[key:string]: string|number|boolean}
type Parameter extends remoteConfig.Value {
key: string,
fetchTimeMillis: number
}
class AngularFireRemoteConfig {
changes: Observable<Parameter>;
parameters: Observable<Parameter[]>;
numbers: Observable<{[key:string]: number|undefined}> & {[key:string]: Observable<number>};
booleans: Observable<{[key:string]: boolean|undefined}> & {[key:string]: Observable<boolean>};
strings: Observable<{[key:string]: string|undefined}> & {[key:string]: Observable<string|undefined>};
// from firebase.remoteConfig() proxy:
activate: () => Promise<boolean>;
ensureInitialized: () => Promise<void>;
fetch: () => Promise<void>;
fetchAndActivate: () => Promise<boolean>;
getAll: () => Promise<{[key:string]: remoteConfig.Value}>;
getBoolean: (key:string) => Promise<boolean>;
getNumber: (key:string) => Promise<number>;
getString: (key:string) => Promise<string>;
getValue: (key:string) => Promise<remoteConfig.Value>;
setLogLevel: (logLevel: remoteConfig.LogLevel) => Promise<void>;
settings: Promise<remoteConfig.Settings>;
defaultConfig: Promise<{[key: string]: string | number | boolean}>;
fetchTimeMillis: Promise<number>;
lastFetchStatus: Promise<remoteConfig.FetchStatus>;
}
// Pipes for working with .changes and .parameters
filterRemote: () => MonoTypeOperatorFunction<Parameter | Parameter[]>
filterFresh: (interval: number) => MonoTypeOperatorFunction<Parameter | Parameter[]>
budget: <T>(interval: number) => MonoTypeOperatorFunction<T>
// scanToObject is for use with .changes
scanToObject: () => OperatorFunction<Parameter, {[key: string]: string|undefined}>
// mapToObject is the same behavior as scanToObject but for use with .parameters
mapToObject: () => OperatorFunction<Parameter[], {[key: string]: string|undefined}>
SETTINGS = InjectionToken<remoteConfig.Settings>;
DEFAULTS = InjectionToken<ConfigTemplate>;
```
## Configuration with Dependency Injection
### Configure Remote Config with `SETTINGS`
Using the `SETTINGS` DI Token (*default: {}*) will allow you to [configure Firebase Remote Config](https://firebase.google.com/docs/reference/js/firebase.remoteconfig.Settings.html).
### Configure default values with `DEFAULTS`
Providing `DEFAULTS ({[key: string]: string | number | boolean})` tells `AngularFireRemoteConfig` to emit the provided defaults first. This allows you to count on Remote Config when the user is offline or in environments that the Remote Config service does not handle (i.e. Server Side Rendering).
## Putting it all together
```ts
import { AngularFireRemoteConfigModule, DEFAULTS, SETTINGS } from '@angular/fire/compat/remote-config';
@NgModule({
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireRemoteConfigModule
],
providers: [
{ provide: DEFAULTS, useValue: { enableAwesome: true } },
{
provide: SETTINGS,
useFactory: () => isDevMode() ? { minimumFetchIntervalMillis: 10_000 } : {}
}
]
})
export class AppModule { }
...
constructor(remoteConfig: AngularFireRemoteConfig) {
remoteConfig.changes.pipe(
filterFresh(172_800_000), // ensure we have values from at least 48 hours ago
first(),
// scanToObject when used this way is similar to defaults
// but most importantly smart-casts remote config values and adds type safety
scanToObject({
enableAwesome: true,
titleBackgroundColor: 'blue',
titleFontSize: 12
})
).subscribe(…);
// all remote config values cast as strings
remoteConfig.strings.subscribe(...)
remoteConfig.booleans.subscribe(...); // as booleans
remoteConfig.numbers.subscribe(...); // as numbers
// convenience for observing a single string
remoteConfig.strings.titleBackgroundColor.subscribe(...);
remoteConfig.booleans.enableAwesome.subscribe(...); // boolean
remoteConfig.numbers.titleBackgroundColor.subscribe(...); // number
// however those may emit more than once as the remote config cache fires and gets fresh values
// from the server. You can filter it out of .changes for more control:
remoteConfig.changes.pipe(
filter(param => param.key === 'titleBackgroundColor'),
map(param => param.asString())
// budget at most 800ms and return the freshest value possible in that time
// our budget pipe is similar to timeout but won't error or abort the pending server fetch
// (it won't emit it, if the deadline is exceeded, but it will have been fetched so can use the
// freshest values on next subscription)
budget(800),
last()
).subscribe(...)
// just like .changes, but scanned into an array
remoteConfig.parameters.subscribe(all => ...);
// or make promisified firebase().remoteConfig() calls direct off AngularFireRemoteConfig
// using our proxy
remoteConfig.getAll().then(all => ...);
remoteConfig.lastFetchStatus.then(status => ...);
}
```
================================================
FILE: docs/compat/rtdb/lists.md
================================================
# 3. Retrieving data as lists
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
> AngularFire synchronizes data as lists using the `AngularFireList` service.
The `AngularFireList` service is not created by itself, but through the `AngularFireDatabase` service.
The guide below demonstrates how to retrieve, save, and remove data as lists.
## Injecting the `AngularFireDatabase` service
**Make sure you have bootstrapped your application for AngularFire. See the Installation guide for bootstrap setup.**
AngularFireDatabase is a service which can be injected through the constructor of your Angular component or `@Injectable()` service.
In the previous step, we modified the `/src/app/app.component.ts` to retrieve data as an object. In this step, let's start with a clean slate.
Replace your `/src/app/app.component.ts` from previous step to look like below.
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
constructor(db: AngularFireDatabase) { }
}
```
In this section, we're going to modify the `/src/app/app.component.ts` to retrieve data as list, but before that let's look at ways around how to bind to a list.
## Create a list binding
Data is retrieved through the `AngularFireDatabase` service. The service is also generic. Provide the singular type and not the array type.
```ts
const listRef = db.list('items');
const shirtsRef = db.list<Shirt>('shirts');
```
### Retrieve data
To get the list in realtime, create a list binding as a property of your component or service.
Then in your template, you can use the `async` pipe to unwrap the binding.
Update `/src/app/app.component.ts` to import `AngularFireList` from `@angular/fire` and iterate through the list once data is retrieved. Also note the change in attribute `templateUrl` to inline `template` below.
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
{{ item | json }}
</li>
</ul>
`,
})
export class AppComponent {
items: Observable<any[]>;
constructor(db: AngularFireDatabase) {
this.items = db.list('items').valueChanges();
}
}
```
## `AngularFireAction` - Action based API
AngularFire provides methods that stream data back as redux compatible actions. This gives you extra horsepower when using libraries like Animations, ngrx, and ReactiveForms.
### `valueChanges()`
**What is it?** - Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the method provides only the data.
**Why would you use it?** - When you just need a list of data. No snapshot metadata is attached to the resulting array which makes it simple to render to a view.
**When would you not use it?** - When you need a more complex data structure than an array or you need the `key` of each snapshot for data manipulation methods. This method assumes you either are saving the `key` for the snapshot data or using a "readonly" approach.
### `snapshotChanges()`
**What is it?** - Returns an Observable of data as a synchronized array of `AngularFireAction<DatabaseSnapshot>[]`.
**Why would you use it?** - When you need a list of data but also want to keep around metadata. Metadata provides you the underyling `DatabaseReference` and snapshot key. Having the snapshot's `key` around makes it easier to use data manipulation methods. This method gives you more horsepower with other Angular integrations such as ngrx, forms, and animations due to the `type` property. The `type` property on each `AngularFireAction` is useful for ngrx reducers, form states, and animation states.
**When would you not use it?** - When you need a more complex data structure than an array or if you need to process changes as they occur. This array is synchronized with the remote and local changes in the Firebase Database.
### `stateChanges()`
**What is it?** - Returns an Observable of the most recent change as an `AngularFireAction`.
**Why would you use it?** - The above methods return a singular `AngularFireAction` from each child event that occurs. `stateChanges()` emits changes as they occur rather than syncing the query order. This works well for ngrx integrations as you can build your own data structure in your reducer methods.
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of `AngularFireDatabase`.
### `auditTrail()`
**What is it?** - Returns an Observable of `AngularFireAction[]` as they occur. Similar to `stateChanges()`, but instead it keeps around the trail of events as an array.
**Why would you use it?** - This method is like `stateChanges()` except it is not ephemeral. It collects each change in an array as they occur. This is useful for ngrx integrations where you need to replay the entire state of an application. This also works as a great debugging tool for all applications. You can simple write `db.list('items').auditTrail().subscribe(console.log)` and check the events in the console as they occur.
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of AngularFireDatabase.
### Limiting events
There are four child events: `"child_added"`, `"child_changed"`, `"child_removed"`, and `"child_moved"`. Each streaming method listens to all four by default. However, your site may only be intrested in one of these events. You can specify which events you'd like to use through the first parameter of each method:
```ts
this.itemsRef = db.list('items');
this.itemsRef.snapshotChanges(['child_added'])
.subscribe(actions => {
actions.forEach(action => {
console.log(action.type);
console.log(action.key);
console.log(action.payload.val());
});
});
```
## Saving data
### API Summary
The table below highlights some of the common methods on the `AngularFireList`.
| method | |
| ---------|--------------------|
| `push(value: T)` | Creates a new record on the list, using the Realtime Database's push-ids. |
| `update(keyRefOrSnap: string, value: T)` | Firebase | AFUnwrappedSnapshot, value: Object) | Updates an existing item in the array. Accepts a key, database reference, or an unwrapped snapshot. |
| `remove(key: string?)` | Deletes the item by key. If no parameter is provided, the entire list will be deleted. |
## Returning promises
Each data operation method in the table above returns a promise. However,
you should rarely need to use the completion promise to indicate success,
because the realtime database keeps the list in sync.
The promise can be useful to chain multiple operations, catching possible errors
from security rules denials, or for debugging.
```ts
const promise = db.list('items').remove();
promise
.then(_ => console.log('success'))
.catch(err => console.log(err, 'You do not have access!'));
```
### Adding new items
Use the `push()` method to add new items on the list.
```ts
const itemsRef = db.list('items');
itemsRef.push({ name: newName });
```
### Replacing items in the list using `set`
Use the `set()` method to update existing items.
```ts
const itemsRef = db.list('items');
// to get a key, check the Example app below
itemsRef.set('key-of-some-data', { size: newSize });
```
Replaces the current value in the database with the new value specified as the parameter. This is called a destructive update, because it deletes everything currently in place and saves the new value.
### Updating items in the list using `update`
Use the `update()` method to update existing items.
```ts
const itemsRef = db.list('items');
// to get a key, check the Example app below
itemsRef.update('key-of-some-data', { size: newSize });
```
Note that this updates the current value with in the database with the new value specified as the parameter. This is called a non-destructive update, because it only updates the values specified.
### Removing items from the list
Use the `remove()` method to remove data at the list item's location.
```ts
const itemsRef = db.list('items');
// to get a key, check the Example app below
itemsRef.remove('key-of-some-data');
```
## Deleting the entire list
If you omit the `key` parameter from `.remove()` it deletes the entire list.
```ts
const itemsRef = db.list('items');
itemsRef.remove();
```
### Example
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from '@angular/fire/compat/database';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
<input type="text" #updatetext [value]="item.text" />
<button (click)="updateItem(item.key, updatetext.value)">Update</button>
<button (click)="deleteItem(item.key)">Delete</button>
</li>
</ul>
<input type="text" #newitem />
<button (click)="addItem(newitem.value)">Add</button>
<button (click)="deleteEverything()">Delete All</button>
`,
})
export class AppComponent {
itemsRef: AngularFireList<any>;
items: Observable<any[]>;
constructor(db: AngularFireDatabase) {
this.itemsRef = db.list('messages');
// Use snapshotChanges().map() to store the key
this.items = this.itemsRef.snapshotChanges().pipe(
map(changes =>
changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
)
);
}
addItem(newName: string) {
this.itemsRef.push({ text: newName });
}
updateItem(key: string, newText: string) {
this.itemsRef.update(key, { text: newText });
}
deleteItem(key: string) {
this.itemsRef.remove(key);
}
deleteEverything() {
this.itemsRef.remove();
}
}
```
### [Next Step: Querying lists](querying-lists.md)
================================================
FILE: docs/compat/rtdb/objects.md
================================================
# 2. Retrieving data as objects
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
> The `AngularFireObject` is a service for manipulating and streaming object data.
The `AngularFireObject` service is not created by itself, but through the `AngularFireDatabase` service.
The guide below demonstrates how to retrieve, save, and remove data as objects.
## Injecting the `AngularFireDatabase` service
**Make sure you have bootstrapped your application for AngularFire. See the Installation guide for bootstrap setup.**
`AngularFireDatabase` is a service which can be injected through the constructor of your Angular component or `@Injectable()` service.
If you've followed the earlier step "Installation and Setup" your `/src/app/app.component.ts` should look like below.
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
items: Observable<any[]>;
constructor(db: AngularFireDatabase) {
this.items = db.list('items').valueChanges();
}
}
```
In this section, we're going to modify the `/src/app/app.component.ts` to retrieve data as object.
## Create an object binding
```ts
const relative = db.object('item').valueChanges();
```
### Retrieve data
To get the object in realtime, create an object binding as a property of your component or service.
Then in your template, you can use the `async` pipe to unwrap the binding.
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<h1>{{ (item | async)?.name }}</h1>
`,
})
export class AppComponent {
item: Observable<any>;
constructor(db: AngularFireDatabase) {
this.item = db.object('item').valueChanges();
}
}
```
## Saving data
### API Summary
The table below highlights some of the common methods on the `AngularFireObject`.
| method | |
| ---------|--------------------|
| `set(value: T)` | Replaces the current value in the database with the new value specified as the parameter. This is called a **destructive** update, because it deletes everything currently in place and saves the new value. |
| `update(value: T)` | Updates the current value with in the database with the new value specified as the parameter. This is called a **non-destructive** update, because it only updates the values specified. |
| `remove()` | Deletes all data present at that location. Same as calling `set(null)`. |
## Returning promises
Each data operation method in the table above returns a promise. However,
you should rarely need to use the completion promise to indicate success,
because the realtime database keeps the object in sync.
The promise can be useful to chain multiple operations, catching possible errors from security rules denials, or for debugging.
```ts
const promise = db.object('item').remove();
promise
.then(_ => console.log('success'))
.catch(err => console.log(err, 'You dont have access!'));
```
### Saving data
Use the `set()` method for **destructive updates**.
```ts
const itemRef = db.object('item');
itemRef.set({ name: 'new name!'});
```
### Updating data
Use the `update()` method for **non-destructive updates**.
```ts
const itemRef = db.object('item');
itemRef.update({ age: newAge });
```
**Only objects are allowed for updates, not primitives**. This is because
using an update with a primitive is the exact same as doing a `.set()` with a primitive.
### Deleting data
Use the `remove()` method to remove data at the object's location.
```ts
const itemRef = db.object('item');
itemRef.remove();
```
**Example app**:
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/compat/database';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
template: `
<h1>{{ item | async | json }}</h1>
<input type="text" #newname placeholder="Name" />
<input type="text" #newsize placeholder="Size" />
<br />
<button (click)="save(newname.value)">Set Name</button>
<button (click)="update(newsize.value)">Update Size</button>
<button (click)="delete()">Delete</button>
`,
})
export class AppComponent {
itemRef: AngularFireObject<any>;
item: Observable<any>;
constructor(db: AngularFireDatabase) {
this.itemRef = db.object('item');
this.item = this.itemRef.valueChanges();
}
save(newName: string) {
this.itemRef.set({ name: newName });
}
update(newSize: string) {
this.itemRef.update({ size: newSize });
}
delete() {
this.itemRef.remove();
}
}
```
## Retrieving the snapshot
AngularFire `valueChanges()` unwraps the Firebase DataSnapshot by default, but you can get the data as the original snapshot by using the `snapshotChanges()` option.
```ts
this.itemRef = db.object('item');
this.itemRef.snapshotChanges().subscribe(action => {
console.log(action.type);
console.log(action.key)
console.log(action.payload.val())
});
```
## Querying?
Because `AngularFireObject` synchronizes objects from the realtime database, sorting will have no effect for queries that are not also limited by a range. For example, when paginating you would provide a query with a sort and filter. Both the sort operation and the filter operation affect which subset of the data is returned by the query; however, because the resulting object is simply json, the sort order will not be preseved locally. Hence, for operations that require sorting, you are probably looking for a [list](lists.md)
### [Next Step: Retrieving data as lists](lists.md)
================================================
FILE: docs/compat/rtdb/querying-lists.md
================================================
# 4. Querying lists
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
## Creating a query with primitive/scalar values
Queries are created by building on the [`firebase.database.Reference`](https://firebase.google.com/docs/reference/js/firebase.database.Reference).
```ts
db.list('/items', ref => ref.orderByChild('size').equalTo('large'))
```
### Query options
| Method | Purpose |
| ---------|--------------------|
| `orderByChild` | Specify a child to order by. |
| `orderByKey` | Boolean to order by Firebase Database keys. |
| `orderByValue` | Specify a value to order by. |
| ~~`orderByPriority`~~<sup>1</sup> | Boolean to order by Firebase Database priority.|
| `equalTo`<sup>2</sup> | Limit list to items that contain certain value. |
| `limitToFirst` | Sets the maximum number of items to return from the beginning of the ordered list of results. |
| `limitToLast` | Sets the maximum number of items to return from the end of the ordered list of results. |
| `startAt`<sup>2</sup> | Return items greater than or equal to the specified key or value, depending on the order-by method chosen. |
| `endAt`<sup>2</sup> | Return items less than or equal to the specified key or value, depending on the order-by method chosen. |
<sup>1</sup> [This is the old way of doing things and is no longer recommended for use](https://youtu.be/3WTQZV5-roY?t=3m). Anything you can achieve with `orderByPriority` you should be doing with `orderByChild`.
<sup>2</sup> The Firebase SDK supports an optional `key` parameter for [`startAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#startAt), [`endAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#endAt), and [`equalTo`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#equalTo) when ordering by child, value, or priority. You can specify the `key` parameter using an object literal that contains the `value` and the `key`. For example: `startAt: { value: 'some-value', key: 'some-key' }`.
To learn more about how sorting and ordering data works in Firebase, check out the Firebase documentation on [working with lists of data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data).
## Invalid query combinations
**Queries can only be ordered by one method.** This means you can only specify
`orderByChild`, `orderByKey`, `orderByPriority`, or `orderByValue`.
```ts
// WARNING: Do not copy and paste. This will not work!
ref.orderByChild('size').equalTo('large').orderByKey(true)
```
You can only use `limitToFirst` or `limitToLast`, but not both in combination.
```ts
// WARNING: Do not copy and paste. This will not work!
ref.limitToFirst(10).limitToLast(100)
```
## Dynamic querying
To enable dynamic queries one should lean on RxJS Operators like `switchMap`.
An RxJS Subject is imported below. A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners. See, [What is a Subject](http://reactivex.io/rxjs/manual/overview.html#subject) for more information.
When we call [`switchMap` on the Subject](https://www.learnrxjs.io/operators/transformation/switchmap.html), we can map each value to a new Observable; in this case a database query.
```ts
const size$ = new Subject<string>();
const queryObservable = size$.pipe(
switchMap(size =>
db.list('/items', ref => ref.orderByChild('size').equalTo(size)).valueChanges()
)
);
// subscribe to changes
queryObservable.subscribe(queriedItems => {
console.log(queriedItems);
});
// trigger the query
size$.next('large');
// re-trigger the query!!!
size$.next('small');
```
**Example app:**
[See this example in action on StackBlitz](https://stackblitz.com/edit/angularfire-db-api-s8ip7m).
```ts
import { Component } from '@angular/core';
import { AngularFireDatabase, AngularFireAction } from '@angular/fire/compat/database';
import { Observable, Subscription, BehaviorSubject } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Component({
selector: 'app-root',
template: `
<h1>Firebase widgets!</h1>
<div *ngIf="items$ | async; let items; else loading">
<ul>
<li *ngFor="let item of items">
{{ item.payload.val().text }}
<code>{{ item.payload.key }}</code>
</li>
</ul>
<div *ngIf="items.length === 0">No results, try clearing filters</div>
</div>
<ng-template #loading>Loading…</ng-template>
<div>
<h4>Filter by size</h4>
<button (click)="filterBy('small')">Small</button>
<button (click)="filterBy('medium')">Medium</button>
<button (click)="filterBy('large')">Large</button>
<button (click)="filterBy('x-large')">Extra Large</button>
<button (click)="filterBy(null)" *ngIf="this.size$.getValue()">
<em>clear filter</em>
</button>
</div>
`,
})
export class AppComponent {
items$: Observable<AngularFireAction<firebase.database.DataSnapshot>[]>;
size$: BehaviorSubject<string|null>;
constructor(db: AngularFireDatabase) {
this.size$ = new BehaviorSubject(null);
this.items$ = this.size$.pipe(
switchMap(size =>
db.list('/items', ref =>
size ? ref.orderByChild('size').equalTo(size) : ref
).snapshotChanges()
)
);
}
filterBy(size: string|null) {
this.size$.next(size);
}
}
```
**To run the above example as is, you need to have sample data in you firebase database with the following structure:**
```json
{
"items": {
"a" : {
"size" : "small",
"text" : "small thing"
},
"b" : {
"size" : "medium",
"text" : "medium sample"
},
"c" : {
"size" : "large",
"text" : "large widget"
}
}
}
```
### [Next Step: Getting started with Firebase Authentication](../auth/getting-started.md)
================================================
FILE: docs/compat/storage/storage.md
================================================
# AngularFireStorage
> Cloud Storage is designed to help you quickly and easily store and serve user-generated content, such as photos and videos.
> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're looking at the documentation for the compatability version of the library. [See the v7 upgrade guide for more information on this change.](../../version-7-upgrade.md).
### Import the `NgModule`
Cloud Storage for AngularFire is contained in the `@angular/fire/storage` module namespace. Import the `AngularFireStorageModule` in your `NgModule`. This sets up the `AngularFireStorage` service for dependency injection.
```ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireStorageModule } from '@angular/fire/compat/storage';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireStorageModule
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
The `BUCKET` injection token can be used to customise the storage bucket.
```ts
import {AngularFireStorageModule, BUCKET } from '@angular/fire/compat/storage';
@NgModule({
providers: [
{ provide: BUCKET, useValue: 'my-bucket-name' }
],
...
})
export class AppModule {}
```
### Injecting the AngularFireStorage service
Once the `AngularFireStorageModule` is registered you can inject the `AngularFireStorage` service.
```ts
import { Component } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
@Component({
selector: 'app-component',
template: ``
})
export class AppComponent {
constructor(private storage: AngularFireStorage) { }
}
```
### Uploading blobs
There are three options for uploading files.
| method | |
| ---------|--------------------|
| `put(data: Blob, metadata?: storage.UploadMetadata): AngularFireUploadTask` | Starts the upload of the blob to the storage reference's path. Returns an `AngularFireUploadTask` for upload monitoring. |
| `putString(data: string, format?: StringFormat, metadata?: UploadMetadata): AngularFireUploadTask` | Updates an existing item in the array. Accepts a key, database reference, or an unwrapped snapshot. |
| `upload(path: string, data: StringFormat, metadata?: UploadMetadata): AngularFireUploadTask` | Upload or update a new file to the storage reference's path. Returns an `AngularFireUploadTask` for upload monitoring. |
### Examples
#### Uploading blobs with put
```ts
import { Component } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
@Component({
selector: 'app-root',
template: `
<input type="file" (change)="uploadFile($event)">
`
})
export class AppComponent {
constructor(private storage: AngularFireStorage) { }
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'name-your-file-path-here';
const ref = this.storage.ref(filePath);
const task = ref.put(file);
}
}
```
#### Uploading blobs with putString
```ts
import { Component } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
@Component({
selector: 'app-root',
template: `
<input type="file" (change)="uploadFile($event)">
`
})
export class AppComponent {
constructor(private storage: AngularFireStorage) { }
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'name-your-file-path-here';
const ref = this.storage.ref(filePath);
const task = ref.putString(file);
}
}
```
#### Uploading files with upload
```ts
import { Component } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/compat/storage';
@Component({
selector: 'app-root',
template: `
<input type="file" (change)="uploadFile($event)">
`
})
export class AppComponent {
constructor(private storage: AngularFireStorage) { }
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'name-your-file-path-here';
const task = this.storage.upload(filePath, file);
}
}
```
### Monitoring upload percentage
An `AngularFireUploadTask` has methods for observing upload percentage as well as the final download URL.
| method | |
| ---------|--------------------|
| `snapshotChanges(): Observable<FirebaseStorage.UploadTaskSnapshot>` | Emits the raw `UploadTaskSnapshot` as the file upload progresses. |
| `percentageChanges(): Observable<number>` | Emits the upload completion percentage. |
| `getDownloadURL(): Observable<any>` | Emits the download url when available |
#### Example Usage
The method `getDownloadURL()` doesn't rely on the task anymore, hence, in order to get the url we should use the finalize method from RxJS on top of the storage ref.
```ts
import { finalize } from 'rxjs/operators';
@Component({
selector: 'app-root',
template: `
<input type="file" (change)="uploadFile($event)" />
<div>{{ uploadPercent | async }}</div>
<a [href]="downloadURL | async">{{ downloadURL | async }}</a>
`
})
export class AppComponent {
uploadPercent: Observable<number>;
downloadURL: Observable<string>;
constructor(private storage: AngularFireStorage) {}
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'name-your-file-path-here';
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
task.snapshotChanges().pipe(
finalize(() => this.downloadURL = fileRef.getDownloadURL() )
)
.subscribe()
}
}
```
### Downloading Files
A convenient pipe exists for simple in page references.
```ts
@Component({
selector: 'app-root',
template: `<img [src]="'users/davideast.jpg' | getDownloadURL" />`
})
export class AppComponent {}
```
To download a file you'll need to create a reference and call the `getDownloadURL()` method on an `AngularFireStorageReference`.
```ts
@Component({
selector: 'app-root',
template: `<img [src]="profileUrl | async" />`
})
export class AppComponent {
profileUrl: Observable<string | null>;
constructor(private storage: AngularFireStorage) {
const ref = this.storage.ref('users/davideast.jpg');
this.profileUrl = ref.getDownloadURL();
}
}
```
### Managing Metadata
Cloud Storage for Firebase allows you to upload and download metadata associated with files. This is useful because you can store important metadata and download it without needing to download the entire file.
### Examples
#### Downloading metadata
```ts
@Component({
selector: 'app-root',
template: `<pre><code>{{ meta | async }}</code></pre>`
})
export class AppComponent {
meta: Observable<any>;
constructor(private storage: AngularFireStorage) {
const ref = this.storage.ref('users/davideast.jpg');
this.meta = ref.getMetadata();
}
}
```
#### Uploading metadata with files
```ts
@Component({
selector: 'app-root',
template: `
<input type="file" (change)="uploadFile($event)" />
`
})
export class AppComponent {
constructor(private storage: AngularFireStorage) {}
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'name-your-file-path-here';
const ref = this.storage.ref(filePath);
const task = ref.put(file, { customMetadata: { blah: 'blah' } });
}
}
```
================================================
FILE: docs/compat.md
================================================
# AngularFire
The official [Angular](https://angular.io/) library for [Firebase](https://firebase.google.com/).
<strong><pre>ng add @angular/fire</pre></strong>
## Compatibility Developer Guide
AngularFire has a new tree-shakable API, you're looking at the documentation for the compatability version of the library. [Find the new developer guide here](../README.md#developer-guide).
[See the v7 upgrade guide for more information on this change.](version-7-upgrade.md).
### Monitor usage of your application in production
> `AngularFireAnalytics` provides a convenient method of interacting with Google Analytics in your Angular application. The provided `ScreenTrackingService` and `UserTrackingService` automatically log events when you're using the Angular Router or Firebase Authentication respectively. [Learn more about Google Analytics](https://firebase.google.com/docs/analytics).
- [Getting started with Google Analytics](compat/analytics/getting-started.md)
### Interacting with your database(s)
Firebase offers two cloud-based, client-accessible database solutions that support realtime data syncing. [Learn about the differences between them in the Firebase Documentation](https://firebase.google.com/docs/firestore/rtdb-vs-firestore).
#### Cloud Firestore
> `AngularFirestore` allows you to work with Cloud Firestore, the new flagship database for mobile app development. It improves on the successes of Realtime Database with a new, more intuitive data model. Cloud Firestore also features richer, faster queries and scales better than Realtime Database.
- [Documents](compat/firestore/documents.md)
- [Collections](compat/firestore/collections.md)
- [Querying Collections](compat/firestore/querying-collections.md)
- [Offline data](compat/firestore/offline-data.md)
#### Realtime Database
> `AngularFireDatabase` allows you to work with the Realtime Database, Firebase's original database. It's an efficient, low-latency solution for mobile apps that require synced states across clients in realtime.
- [Objects](compat/rtdb/objects.md)
- [Lists](compat/rtdb/lists.md)
- [Querying lists](compat/rtdb/querying-lists.md)
### Authenticate users
- [Getting started with Firebase Authentication](compat/auth/getting-started.md)
- [Route users with AngularFire guards](compat/auth/router-guards.md)
### Local Emulator Suite
- [Getting started with Firebase Emulator Suite](compat/emulators/emulators.md)
### Upload files
- [Getting started with Cloud Storage](compat/storage/storage.md)
### Receive push notifications
- [Getting started with Firebase Messaging](compat/messaging/messaging.md)
### **BETA:** Change behavior and appearance of your application without deploying
> Firebase Remote Config is a cloud service that lets you change the behavior and appearance of your app without requiring users to download an app update. [Learn more about Remote Config](https://firebase.google.com/docs/remote-config).
- [Getting started with Remote Config](compat/remote-config/getting-started.md)
### Monitor your application performance in production
> Firebase Performance Monitoring is a service that helps you to gain insight into the performance characteristics of your iOS, Android, and web apps. [Learn more about Performance Monitoring](https://firebase.google.com/docs/perf-mon).
- [Getting started with Performance Monitoring](compat/performance/getting-started.md)
### Directly call Cloud Functions
- [Getting started with Callable Functions](compat/functions/functions.md)
================================================
FILE: docs/database.md
================================================
<img align="right" width="30%" src="images/database-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Realtime Database
</small>
# Realtime Database
Store and sync data with our NoSQL cloud database. Data is synced across all clients in realtime, and remains available when your app goes offline.
The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client. When you build cross-platform apps with our iOS, Android, and JavaScript SDKs, all of your clients share one Realtime Database instance and automatically receive updates with the newest data. [Learn more about the Realtime Database](https://firebase.google.com/docs/database).
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Database instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideDatabase, getDatabase } from '@angular/fire/database';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideDatabase(() => getDatabase()),
...
],
...
})
```
Next inject `Database` into your component:
```ts
import { Component, inject } from '@angular/core';
import { Database } from '@angular/fire/database';
@Component({...})
export class DepartmentComponent {
private database = inject(Database);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Just change your imports from `import { ... } from 'firebase/database'` to `import { ... } from '@angular/fire/database'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/database/web/start) | [API Reference](https://firebase.google.com/docs/reference/js/database)
## Convenience observables
AngularFire provides observables to allow convenient use of the Realtime Database with RXJS.
### `object`
The `object()` function creates an observable that emits object changes.
| | |
|-----------------|------------------------------------------|
| **function** | `object(ref)` |
| **params** | ref: `Reference` |
| **return** | `Observable<QueryChange>` |
### `objectVal`
The `objectVal` function creates an observable that emits an array of object values, optionally with a mapped key.
| | |
|-----------------|-------------------------------------------------------|
| **function** | `objectVal(query, options?)` |
| **params** | query: `Reference\|Query`, options?: { keyField?: `string` } |
| **return** | `Observable<T>` |
### `list`
The `list()` function creates an observable that emits a sorted array for each child event change. The optional `events` parameter will filter which child events populate the array.
| | |
|-----------------|-------------------------------------------------------|
| **function** | `list(ref, options?)` |
| **params** | ref: `Reference\|Query`, options?: { events?: `ListenEvent[]` } |
| **return** | `Observable<QueryChange[]>` |
### `listVal`
The `listVal()` function creates an observable that emits an object mapped to its value, and optionally its key.
| | |
|-----------------|-------------------------------------------------------|
| **function** | `listVal(query, options?)` |
| **params** | ref: `Reference\|Query`, options?: { keyField?: `string` } |
| **return** | `Observable<T \| null>` |
### `stateChanges`
The `stateChanges()` function creates an observable that emits each time a change occurs at the reference or query passed. This is useful for tracking the changes in your list. The optional `events` parameter will filter which child events populate the array.
| | |
|-----------------|------------------------------------------------------|
| **function** | `stateChanges(ref, options?)` |
| **params** | ref: `Reference\|Query`, options:? { events?: `ListenEvent[]` } |
| **return** | `Observable<QueryChange>` |
### `auditTrail`
The `auditTrail()` function creates an observable that emits the entire state trail. This is useful for debugging or replaying the state of a list in your app. The optional `events` parameter will filter which child events populate the array.
| | |
|-----------------|------------------------------------------------------|
| **function** | `auditTrail(ref, options?)` |
| **params** | ref: `Reference\|Query`, options?: { events?: `ListenEvent[]` } |
| **return** | `Observable<QueryChange[]>` |
### `fromRef`
The `fromRef()` function creates an observable that emits reference changes.
| | |
|-----------------|------------------------------------------|
| **function** | `fromRef(ref, event)` |
| **params** | ref: `Reference\|Query`, event: `ListenEvent` |
| **return** | `Observable<QueryChange>` |
## Connecting to the emulator suite
```ts
import { connectDatabaseEmulator, getDatabase, provideDatabase } from '@angular/fire/database';
@NgModule({
imports: [
provideDatabase(() => {
const database = getDatabase();
connectDatabaseEmulator(database, 'localhost', 9000);
return database;
}),
]
})
```
## Working with multiple instances
```ts
import { provideFirebaseApp, FirebaseApp, initializeApp } from '@angular/fire/app';
import { getDatabase, provideDatabase } from '@angular/fire/database';
const DATABASE_SHARD_URLS = [
'https://FOO.firebaseio.com',
'https://BAR.firebaseio.com',
'https://BAZ.firebaseio.com',
];
@NgModule({
imports: [
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideDatabase((app: FirebaseApp) => getDatabase(app, DATABASE_SHARD_URLS[0])),
provideDatabase((app: FirebaseApp) => getDatabase(app, DATABASE_SHARD_URLS[1])),
provideDatabase((app: FirebaseApp) => getDatabase(app, DATABASE_SHARD_URLS[2])),
]
})
```
```ts
import { DatabaseInstances } from '@angular/fire/database';
constructor(databases: DatabaseInstances) {
// databases => Database[]
}
```
================================================
FILE: docs/deploy/getting-started.md
================================================
# Deploy your application on Firebase Hosting & Functions
In this guide, we'll look at how to use `@angular/fire` to automatically deploy an Angular application to Firebase hosting or functions by using the Angular CLI.
`@angular/fire` uses Firebase functions to deploy your Angular universal projects, with server-side rendering enabled.
**Angular Universal deployments work with `@nguniversal/*` version 9.0.0 and above**.
## Step 1: add `@angular/fire` to your project
First, you need to add the `@angular/fire` package to your project. In your Angular CLI project run:
```shell
ng add @angular/fire
```
*Note that the command above assumes you have global Angular CLI installed. To install Angular CLI globally run `npm i -g @angular/cli`.*
First, the command above will check if you have an Angular universal project. It'll do so by looking at your `angular.json` project, looking for a `server` target for the specified project. If it finds one, it'll ask you if you want to deploy the project in a firebase function.
After that it will trigger the `@angular/fire` `ng-add` schematics. The schematics will open a web browser and guide you through the Firebase authentication flow (if you're not signed in already). After you authenticate, you'll see a prompt to select a Firebase hosting project.
The schematics will do the following:
- Add `@angular/fire` to your list of dependencies
- Create `firebase.json`, `.firebaserc` files in the root of your workspace. You can use them to configure your firebase hosting deployment. Find more about them [here](https://firebase.google.com/docs/hosting/full-config)
- Update your workspace file (`angular.json`) by inserting the `deploy` builder
In the end, your `angular.json` project will look like below:
```json5
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"sample-app": {
// ...
"deploy": {
"builder": "@angular/fire:deploy",
"options": {} // Here you may find an "ssr": true option if you've
// selected that you want to deploy your Angular universal project
// as a firebase function.
}
}
},
// ...
"defaultProject": "sample-app"
}
```
If you want to add deployment capabilities to a different project in your workspace, you can run:
```
ng add @angular/fire --project=[PROJECT_NAME]
```
## Step 2: deploying the project
As the second step, to deploy your project run:
```
ng deploy --project=[PROJECT_NAME]
```
*The `--project` option is optional. Learn more [here](https://angular.io/cli/deploy).*
The command above will trigger:
1. Production build of your application
2. Deployment of the produced assets to the firebase hosting project you selected during `ng add`
If you've specified that you want a server-side rendering enabled deployment in a firebase function, the command will also:
1. Create a firebase function in `dist`, which directly consumes `main.js` from your server output directory.
2. Create `package.json` for the firebase function with the required dependencies.
3. Deploy the static assets to firebase hosting and your universal server as a Firebase function.
If you want to preview your Angular Universal project before we deploy it as a Firebase Function you can run:
```
ng deploy --preview
```
We'll create the function and a `package.json` in your project output directory. This way, you can later run `firebase serve` in your project root so you can test everything before deploying.
## Step 3: customization
To customize the deployment flow, you can use the configuration files you're already familiar with from `firebase-tools`. You can find more in the [firebase documentation](https://firebase.google.com/docs/hosting/full-config).
### Configuring Cloud Functions
Setting `functionsNodeVersion` and `functionsRuntimeOptions` in your `angular.json` allow you to customize the version of Node.js Cloud Functions is running and run-time settings like timeout, VPC connectors, and memory.
```json
"deploy": {
"builder": "@angular/fire:deploy",
"options": {
"functionsNodeVersion": 12,
"functionsRuntimeOptions": {
"memory": "2GB",
"timeoutSeconds": 10,
"vpcConnector": "my-vpc-connector",
"vpcConnectorEgressSettings": "PRIVATE_RANGES_ONLY"
}
}
}
```
### Working with multiple Firebase Projects
If you have multiple build targets and deploy targets, it is possible to specify them in your `angular.json` or `workspace.json`.
It is possible to use either your project name or project alias in `firebaseProject`. The setting provided here is equivalent to passing a project name or alias to `firebase deploy --project projectNameOrAlias`.
The `buildTarget` simply points to an existing build configuration for your project. Most projects have a default configuration and a production configuration (commonly activated by using the `--prod` flag) but it is possible to specify as many build configurations as needed.
You may specify a `buildTarget` and `firebaseProject` in your `options` as follows:
```json
"deploy": {
"builder": "@angular/fire:deploy",
"options": {
"buildTarget": "projectName:build",
"firebaseProject": "developmentProject"
},
"configurations": {
"production": {
"buildTarget": "projectName:build:production",
"firebaseProject": "productionProject"
}
}
}
```
The above configuration specifies the following:
1. `ng deploy` will deploy the default project with default configuration.
2. `ng deploy projectName` will deploy the specified project with default configuration.
3. `ng deploy projectName --prod` or `ng deploy projectName --configuration='production'` will deploy `projectName` with production build settings to your production environment.
All of the options are optional. If you do not specify a `buildTarget`, it defaults to a production build (`projectName:build:production`). If you do not specify a `firebaseProject`, it defaults to the first matching deploy target found in your `.firebaserc` (where your projectName is the same as your Firebase deploy target name). The `configurations` section is also optional.
### Working with multiple project sites
For example, if you have muti sites config in firebase.json like this:
```
{
"hosting": [
{
"target": "custom-site",
"public": "public/my-custom-site",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
```
If you have multiple build targets and deploy targets, it is possible to specify them in your `angular.json` or `workspace.json`.
It is possible to use either your project name or project alias in `siteTarget`.
You may specify a `siteTarget` in your `options` as follows:
```json
"deploy": {
"builder": "@angular/fire:deploy",
"options": {
"buildTarget": "projectName:build",
"firebaseProject": "developmentProject",
"siteTarget": "yourDefaultSiteTarget"
},
"configurations": {
"production": {
"buildTarget": "projectName:build:production",
"firebaseProject": "productionProject",
"siteTarget": "yourProdSiteTarget"
},
"storybook": {
"buildTarget": "projectName:build-storybook",
"firebaseProject": "developmentProject",
"siteTarget": "yourStorybookSiteTarget"
}
}
}
```
The above configuration specifies the following:
1. `ng deploy` will deploy the default project with default configuration.
2. `ng deploy projectName` will deploy the specified project with default configuration.
3. `ng deploy projectName --configuration=storybook --siteTarget=mySiteTarget` will deploy `projectName` to `mySiteTarget` with configuration`storybook`.
All of the options are optional
================================================
FILE: docs/firebase.json
================================================
{
"firebase": "angular-fire-2",
"public": ".",
"redirects": [
{
"source": "/",
"destination": "/api",
"type": 302
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
================================================
FILE: docs/firestore.md
================================================
<img align="right" width="30%" src="images/firestore-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Cloud Firestore
</small>
# Cloud Firestore
Cloud Firestore is a flexible, scalable NoSQL database for mobile, web, and server development from Firebase and Google Cloud. It keeps your data in sync across client apps through realtime listeners and offers offline support for mobile and web so you can build responsive apps that work regardless of network latency or Internet connectivity.
[Learn more](https://firebase.google.com/docs/firestore)
Cloud Firestore is the API that gives your application access to your database in the cloud or locally in your [emulator](https://firebase.google.com/docs/emulator-suite).
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Firestore instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideFirestore(() => getFirestore()),
...
],
...
}
```
Next inject `Firestore` into your component:
```typescript
import { Component, inject } from '@angular/core';
import { Firestore } from '@angular/fire/firestore';
@Component({ ... })
export class UserProfileComponent {
private firestore = inject(Firestore);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/firestore'` to `import { ... } from '@angular/fire/firestore'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/firestore/quickstart#web-modular-api) | [API Reference](https://firebase.google.com/docs/reference/js/firestore)
### Reading data
In Cloud Firestore data is stored in `documents` and `documents` are stored in `collections`. The path to data follows `<collection_name>/<document_id>` and continues if there are subcollections. For example, `"users/ABC12345/posts/XYZ6789"` represents:
* `users` collection
* document id `ABC12345`
* `posts` collection
* document id `XYZ6789`
Let's explore reading data in Angular using the `collection` and `collectionData` functions.
In `user-profile.component.ts`:
```typescript
import { Firestore, collection, collectionData} from '@angular/fire/firestore';
import { Component, inject } from '@angular/core';
@Component ({
selector: 'app-user-profile',
standalone: true,
...
})
export class UserProfileComponent {
private firestore: Firestore = inject(Firestore); // inject Cloud Firestore
users$: Observable<UserProfile[]>;
constructor() {
// get a reference to the user-profile collection
const userProfileCollection = collection(this.firestore, 'users');
// get documents (data) from the collection using collectionData
this.users$ = collectionData(userProfileCollection) as Observable<UserProfile[]>;
}
}
export Interface UserProfile {
username: string;
}
```
`collectionData` returns an `observable` that can we can use to display the data in the template. In `user-profile.component.html`:
```html
<section>
<h1>User Profiles</h1>
<ul>
<li *ngFor="let user of users$ | async">
{{user.username}}
</li>
</ul>
</section>
```
The `async` pipe handles unsubscribing from observables.
### Writing data
To write to Cloud Firestore use the `addDoc` function. It will create a new document at the path specified by the collection. In `user-profile.component.ts`, we'll update the code to add a new document on a `<button>` click.
```typescript
import { Firestore, collection, collectionData, addDoc} from '@angular/fire/firestore';
import { Component, inject } from '@angular/core';
@Component ({
selector: 'app-user-profile',
standalone: true,
...
})
export class UserProfileComponent {
private firestore: Firestore = inject(Firestore); // inject Cloud Firestore
users$: Observable<UserProfile[]>;
usersCollection: CollectionReference;
constructor() {...}
addUserProfile(username: string) {
if (!username) return;
addDoc(this.usersCollection, <UserProfile> { username }).then((documentReference: DocumentReference) => {
// the documentReference provides access to the newly created document
});
}
}
export Interface UserProfile {
username: string;
}
```
In the `addUserProfile` method we use a reference to the `this.usersCollection` and provide `UserProfile` data to the the `addDoc` function. `addDoc` returns a promise that can be used to respond to the successful addition of the data. Errors can also be caught here.
## Learn More
More information on API methods and other functions can be found on the [Firebase Official Docs](https://firebase.google.com/docs/reference/js/firestore_)
================================================
FILE: docs/functions.md
================================================
<img align="right" width="30%" src="images/functions-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Cloud Functions
</small>
# Cloud Functions
The Cloud Functions for Firebase client SDKs let you call functions directly from a Firebase app. To call a function from your app in this way, write and deploy an HTTPS Callable function in Cloud Functions, and then add client logic to call the function from your app.
[Learn More](https://firebase.google.com/docs/functions/get-started)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Cloud Functions instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideFunctions, getFunctions } from '@angular/fire/functions';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideFunctions(() => getFunctions()),
...
],
...
})
```
Next inject `Functions` into your component:
```ts
import { Component, inject} from '@angular/core';
import { Functions } from '@angular/fire/functions';
@Component({ ... })
export class AppComponent {
private functions = inject(Functions);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/functions'` to `import { ... } from '@angular/fire/functions'` and follow the official documentation.
[Call functions from your app](https://firebase.google.com/docs/functions/callable?gen=2nd#web-modular-api) | [API Reference](https://firebase.google.com/docs/reference/js/functions)
================================================
FILE: docs/install-and-setup.md
================================================
# AngularFire Quickstart
### 1. Create a new project
```bash
# Using yarn create
yarn create @angular <project-name>
cd <project-name>
```
or
```bash
# Using npm create
npm create @angular <project-name>
cd <project-name>
```
optionally installing the tooling directly:
```bash
# Installing the tooling directly
npm install -g @angular/cli
ng new <project-name>
cd <project-name>
```
The Angular CLI's `new` command will set up the latest Angular build in a new project structure.
### 2. Install AngularFire and Firebase
```bash
ng add @angular/fire
```
Now that you have a new project setup, install AngularFire and Firebase from npm. This will complete the following tasks:
1. Add Firebase config to environments variables
2. Configure `@NgModule` for the `AngularFireModule`
### 3. Inject `Firestore`
Open `/src/app/app.component.ts`, and make the following changes to :
```ts
import { Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { Firestore } from '@angular/fire/firestore';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
imports: [AsyncPipe],
})
export class AppComponent {
firestore: Firestore = inject(Firestore);
constructor() {
}
}
```
### 4. Bind a Firestore collection to a list
In `/src/app/app.component.ts`:
```ts
import { Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { Observable } from 'rxjs';
import { Firestore, collection, collectionData } from '@angular/fire/firestore';
@Component({
selector: 'app-root',
standalone: true,
imports: [AsyncPipe],
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
firestore: Firestore = inject(Firestore);
items$: Observable<any[]>;
constructor() {
const aCollection = collection(this.firestore, 'items')
this.items$ = collectionData(aCollection);
}
}
```
Open `/src/app/app.component.html`:
```html
<ul>
@for (item of items$ | async; track item) {
<li>{{ item.name }}</li>
}
</ul>
```
### 5. Run your app locally
```bash
ng serve
```
Your Angular app will compile and serve locally, visit it we should find an empty list.
In another tab [start adding data to an `items` collection in Firestore](https://firebase.google.com/docs/firestore/manage-data/add-data). *As we're not authenticating users yet, be sure to start Firestore in **test mode** or allow reading from the `items` collection in Security Rules (`allow read: if true`).*
Once you've created a `items` collection and are inserting documents, you should find data streaming into your Angular application and being rendered in your browser.
### 6. Deploy your app
Finally, we can deploy the application to Firebase hosting:
```bash
ng deploy
```
================================================
FILE: docs/install-angular-cli-windows10.md
================================================
# Installing Angular CLI on Windows 10
> There had been installation issues of `@angular/cli` on Windows 10 system. Most of the time these errors are related to Python dependencies and node-gyp.
Something as below :
```bash
execSync@1.0.2 install C:\Users\User\AppData\Roaming\npm\node_modules\angu
lar-cli\node_modules\angular2-template-loader\node_modules\codecov\node_modules\
execSync
node install.js
[execsync v1.0.2] Attempting to compile native extensions.
{ [Error: spawn node-gyp ENOENT]
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn node-gyp',
path: 'node-gyp',
spawnargs: [ 'rebuild' ] }
[execSync v1.0.2]
Native code compile failed!!
Will try to use win32 extension.
npm WARN deprecated tough-cookie@2.2.2: ReDoS vulnerability parsing Set-Cookie h
ttps://nodesecurity.io/advisories/130
npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher
to avoid a RegExp DoS issue
npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher
to avoid a RegExp DoS issue
node-zopfli@2.0.1 install C:\Users\User\AppData\Roaming\npm\node_modules\a
ngular-cli\node_modules\compression-webpack-plugin\node_modules\node-zopfli
node-pre-gyp install --fallback-to-build
.......................
```
To resolve this issue, make sure you've upgraded to the latest version of **NPM** and try installing `@angular/cli` again. This seems to have worked on certain scenarios.
If the above doesn't work then the below steps should help. Please ensure all the commands are executed as an **Administrator**.
## Steps:
### 1) Install `node-gyp` from [here](https://github.com/nodejs/node-gyp) using NPM
```bash
npm install -g node-gyp
```
### 2) Install Windows build tools from [here](https://github.com/felixrieseberg/windows-build-tools) using NPM
```bash
npm install --global windows-build-tools
```
*This will also install Python
### 3) Install Angular CLI
```bash
npm install -g @angular/cli
```
This should install `@angular/cli` without errors.
#### Post this installation, follow the installation [guide](https://github.com/angular/angularfire2/blob/master/docs/install-and-setup.md) to install AngularFire and everything should work as expected.
### Note:
When you start your app using `ng serve` in the console, you might still see the below errors. Despite these errors, the application should work as expected and should be able to talk to Firebase.
```bash
ERROR in [default] C:\angularFire2Test\node_modules\angularfire2\interfaces.d.ts:12:34
Cannot find namespace 'firebase'.
ERROR in [default] C:\angularFire2Test\src\typings.d.ts:6:12
Subsequent variable declarations must have the same type. Variable 'require' must be of type 'NodeRequire',
but here has type 'any'.
ERROR in [default] C:\angularFire2Test\src\typings.d.ts:7:12
Subsequent variable declarations must have the same type. Variable 'module' must be of type 'NodeModule',
but here has type 'any'.
```
================================================
FILE: docs/install-firebase-tools.md
================================================
# Firebase Tools Install and Setup
### 1. Install package
```bash
npm install -g firebase-tools
```
or with `yarn`
```bash
yarn global add firebase-tools
```
You can also choose to install it as a dependency for your project rather than globally
```bash
npm install --save-dev firebase-tools
```
or with `yarn`
```bash
yarn add -D firebase-tools
```
### 2. Configure Firebase Tools
In your projects root directory run:
```bash
firebase init
```
or if your installed it within your project rather than globally
```bash
npx firebase init
```
or with `yarn`
```bash
yarn firebase init
```
This will ask you to login if you are not logged in already, the process will take you through a browser
redirect to log you into Firebase.
### 3. Choose what Firebase features
`firebase-tools` displays Firebase features you want to configure.
```bash
? Which Firebase features do you want to set up for this directory? Press Space
to select features, then Enter to confirm your choices. (Press <space> to select
, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
◯ Realtime Database: Configure a security rules file for Realtime Database and
(optionally) provision default instance
◯ Firestore: Configure security rules and indexes files for Firestore
◯ Functions: Configure a Cloud Functions directory and its files
◯ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub
Action deploys
◯ Hosting: Set up GitHub Action deploys
(Move up and down to reveal more choices)
```
### 4. Connect your repo to a Firebase project
The CLI will then walk you through making sure your repo is configured with a Firebase project.
```bash
? Please select an option:
◯ Use an existing project
◯ Create a new project
◯ Add Firebase to an existing Google Cloud Platform project
◯ Don't set up a default project
```
================================================
FILE: docs/messaging.md
================================================
<img align="right" width="30%" src="images/cloud-messaging-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Cloud Messaging
</small>
# Cloud Messaging
Firebase FCM allows you to register devices with unique FCM tokens, that you can later programtically send notifications to using Firebase Cloud Functions. It is up to the application to update these tokens in Firebase if you want to use them in other layers of your application, i.e send a notification to all administrators, etc. In that case, you would likely want to store your fcm tokens on your user collection, or a sub collection or another collection with different permissions.
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Cloud Messaging instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideMessaging, getMessaging } from '@angular/fire/messaging';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideMessaging(() => getMessaging()),
...
],
...
})
```
Next inject `Messaging` into your component:
```ts
import { Component, inject} from '@angular/core';
import { Messaging } from '@angular/fire/messaging';
@Component({ ... })
export class AppComponent {
private messaging = inject(Messaging);
...
}
```
# Create a Firebase Messaging Service Worker
There are two parts to Firebase Messaging, a Service Worker and the DOM API. Angular Fire Messaging allows you to request permission, get tokens, delete tokens, and subscribe to messages on the DOM side. To register to receive notifications you need to set up the Service Worker. [The official Firebase documentation for setting up the details exactly how to do that](https://firebase.google.com/docs/cloud-messaging/js/client).
#### Create your firebase-messaging-sw.js file in your src/assets folder
*Note: When copying the below file, make sure your firebase version in your installation matches the version your are importing from below*
It may be wise to use file replacements or environments here for different environments
```
// This sample application is using 9.22, make sure you are importing the same version
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
import { getMessaging } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-messaging-sw.js";
const firebaseApp = initializeApp({
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
});
const messaging = getMessaging(firebaseApp);
```
# Example messaging service
```
import { Injectable } from "@angular/core";
import { Messaging, getToken, onMessage, deleteToken } from "@angular/fire/messaging";
import { Observable, tap } from "rxjs";
@Injectable({
providedIn: "root",
})
export class FcmService {
constructor(private msg: Messaging){
Notification.requestPermission().then(
(notificationPermissions: NotificationPermission) => {
if (notificationPermissions === "granted") {
console.log("Granted");
}
if (notificationPermissions === "denied") {
console.log("Denied");
}
});
navigator.serviceWorker
.register("/assets/firebase-messaging-sw.js", {
type: "module",
})
.then((serviceWorkerRegistration) => {
getToken(this.msg, {
vapidKey: `an optional key generated on Firebase for your fcm tokens`,
serviceWorkerRegistration: serviceWorkerRegistration,
}).then((x) => {
console.log('my fcm token', x);
// This is a good place to then store it on your database for each user
});
});
}
this.message$ = new Observable((sub) => onMessage(this.msg, (msg) =>
sub.next(msg))).pipe(
tap((msg) => {
console.log("My Firebase Cloud Message", msg);
})
);
}
deleteToken(){
// We can also delete fcm tokens, make sure to also update this on your firestore db if you are storing them as well
await deleteToken(this.msg);
}
```
# Testing and Sending Notifications
Firebase will allow you to send a test notification under Engage > Messaging > New Campaign > Notifications. Here you can click send a test message. Additionally, you can send them programmatically through Firebase cloud functions.
Here is a barebones Node example:
```
export const sendTestMessage = onRequest(async (_, res) => {
try {
const message = {
notification: {
title: "Test Title",
body: "Test Body",
},
token: "your token here, you can store these and retreive as you please",
};
await admin.messaging().send(message);
res.sendStatus(200);
} catch (error) {
console.error(error);
res.sendStatus(500);
}
});
```
Here is a Node example that listens for a new comment on a collection, then sends a notification, and also adds it to a cache on Firebase so users can click through them.
```
exports.onPostReply =
onDocumentCreated("comments/{commentId}", async (event) => {
if (!event) throw new Error("No event found for document creation");
const snapshot = event.data;
if (!snapshot) {
throw new Error("No data associated with the event");
}
const data = snapshot.data();
if (!data.postId) {
throw new Error("No post ID found");
}
const postRef = await firestore.collection("posts").doc(data.postId).get();
const postData = postRef.data();
if (!postData) {
throw new Error("No postData found");
}
// userUid will be the post author's id.
const {userUid} = postData;
if (!userUid) {
throw new Error(
"Could not find the userUid for the post author for post reply"
);
}
const messageForNotification = {
title: "You have a new reply on your post",
body: "",
};
await createNotificationAndCache(messageForNotification, userUid);
});
// If you want to cache notifications a number of times, abstracting this
// to a function can bring a lot of value.
interface NotificationProps {
title: string;
body: string;
}
async function createNotificationAndCache(
notificationProps: NotificationProps, userAuthUid: string) {
const userRef = await firestore.collection("users").where("authUid", "==",
userAuthUid).get();
const userData = userRef.docs[0].data();
const promises: Promise<any>[] = [];
// This sample application has seperate fcm tokens for web and mobile
if (userData.mobileToken) {
const message = {
notification: notificationProps,
token: userData.mobileToken,
};
const promise = admin.messaging().send(message);
promises.push(promise);
}
if (userData.webToken) {
const message = {
notification: notificationProps,
token: userData.webToken,
};
const promise = admin.messaging().send(message);
promises.push(promise);
}
const notificationCacheValue = {
userAuthUid: userAuthUid,
tokenTitle: notificationProps.title,
tokenBody: notificationProps.body,
isActive: true, // This determines whether a notification has been seen
};
promises.push(
firestore.collection("notificationCache").add(notificationCacheValue));
await Promise.all(promises);
} ```
================================================
FILE: docs/performance.md
================================================
<img align="right" width="30%" src="images/performance-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Performance Monitoring
</small>
# Performance Monitoring
Firebase Performance Monitoring is a service that helps you to gain insight into the performance characteristics of your Apple, Android, and web apps.
[Learn More](https://firebase.google.com/docs/perf-mon)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Performance instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { providePerformance, getPerformance } from '@angular/fire/performance';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
providePerformance(() => getPerformance()),
...
],
...
})
```
Next inject `Performance` into your component:
```ts
import { Component, inject} from '@angular/core';
import { Performance } from '@angular/fire/performance';
@Component({ ... })
export class PerformanceComponent {
private performance = inject(Performance);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/performance'` to `import { ... } from '@angular/fire/performance'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/perf-mon/get-started-web) | [API Reference](https://firebase.google.com/docs/reference/js/performance)
================================================
FILE: docs/remote-config.md
================================================
<img align="right" width="30%" src="images/remote-config-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Remote Config
</small>
# Remote Config
Firebase Remote Config is a cloud service that lets you change the behavior and appearance of your app without requiring users to download an app update.
[Learn More](https://firebase.google.com/docs/remote-config/)
## Dependency Injection
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Remote Config instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideRemoteConfig, getRemoteConfig } from '@angular/fire/remote-config';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideRemoteConfig(() => getRemoteConfig()),
...
],
...
})
```
Next inject `RemoteConfig` into your component:
```ts
import { Component, inject} from '@angular/core';
import { RemoteConfig } from '@angular/fire/remote-config';
@Component({ ... })
export class RemoteConfigComponent {
private remoteConfig = inject(RemoteConfig);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/remote-config'` to `import { ... } from '@angular/fire/remote-config'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/remote-config/get-started?platform=web) | [API Reference](https://firebase.google.com/docs/reference/js/remote-config)
================================================
FILE: docs/storage.md
================================================
<img align="right" width="30%" src="images/storage-illo_1x.png">
<small>
<a href="https://github.com/angular/angularfire">AngularFire</a> ❱ <a href="../README.md#developer-guide">Developer Guide</a> ❱ Cloud Storage
</small>
# Cloud Storage
Cloud Storage allows developers to upload and share user generated content such as images, video and more. Data is stored in Google Cloud Storage.
[Learn more](https://firebase.google.com/docs/storage)
## Dependency Injection
AngularFire allows you to work with Firebase Storage via Angular's Dependency Injection.
As a prerequisite, ensure that `AngularFire` has been added to your project via
```bash
ng add @angular/fire
```
Provide a Cloud Storage instance in the application's `app.config.ts`:
```ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideStorage, getStorage } from '@angular/fire/storage';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ ... })),
provideStorage(() => getStorage()),
...
],
...
})
```
Next inject `Storage` into your component:
```ts
import { Component, inject} from '@angular/core';
import { Storage } from '@angular/fire/storage';
@Component({ ... })
export class StorageComponent {
private storage = inject(Storage);
...
}
```
## Firebase API
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.
Update the imports from `import { ... } from 'firebase/storage'` to `import { ... } from '@angular/fire/storage'` and follow the official documentation.
[Getting Started](https://firebase.google.com/docs/storage/web/start) | [API Reference](https://firebase.google.com/docs/reference/js/storage)
## File Upload Example
```ts
import { Component, inject } from '@angular/core';
import { Storage, ref, uploadBytesResumable } from '@angular/fire/storage';
@Component({
selector: 'app-storage',
template: `
<h1>Storage</h1>
<label for="fileUpload">Choose a File</label>
<input id="fileUpload" type="file" #upload>
<button (click)="uploadFile(upload)">Upload</button>
`,
})
export class StorageComponent {
private readonly storage: Storage = inject(Storage);
uploadFile(input: HTMLInputElement) {
if (!input.files) return
const files: FileList = input.files;
for (let i = 0; i < files.length; i++) {
const file = files.item(i);
if (file) {
const storageRef = ref(this.storage, file.name);
uploadBytesResumable(storageRef,
gitextract_l7_cun8a/ ├── .editorconfig ├── .firebaserc ├── .gitattributes ├── .github/ │ └── workflows/ │ ├── codeql-analysis.yml │ └── test.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── SECURITY.md ├── angular.json ├── docs/ │ ├── analytics.md │ ├── app-check.md │ ├── auth.md │ ├── compat/ │ │ ├── analytics/ │ │ │ └── getting-started.md │ │ ├── auth/ │ │ │ ├── getting-started.md │ │ │ └── router-guards.md │ │ ├── emulators/ │ │ │ └── emulators.md │ │ ├── firestore/ │ │ │ ├── collections.md │ │ │ ├── documents.md │ │ │ ├── offline-data.md │ │ │ └── querying-collections.md │ │ ├── functions/ │ │ │ └── functions.md │ │ ├── messaging/ │ │ │ └── messaging.md │ │ ├── performance/ │ │ │ └── getting-started.md │ │ ├── remote-config/ │ │ │ └── getting-started.md │ │ ├── rtdb/ │ │ │ ├── lists.md │ │ │ ├── objects.md │ │ │ └── querying-lists.md │ │ └── storage/ │ │ └── storage.md │ ├── compat.md │ ├── database.md │ ├── deploy/ │ │ └── getting-started.md │ ├── firebase.json │ ├── firestore.md │ ├── functions.md │ ├── install-and-setup.md │ ├── install-angular-cli-windows10.md │ ├── install-firebase-tools.md │ ├── messaging.md │ ├── performance.md │ ├── remote-config.md │ ├── storage.md │ ├── universal/ │ │ ├── cloud-functions.md │ │ ├── getting-started.md │ │ └── prerendering.md │ ├── version-4-upgrade.md │ ├── version-5-upgrade.md │ ├── version-6-upgrade.md │ ├── version-7-upgrade.md │ ├── vertexai.md │ └── zones.md ├── eslint.config.js ├── firebase.json ├── karma.conf.js ├── mise.toml ├── package.json ├── sample/ │ ├── .editorconfig │ ├── .firebaserc │ ├── .gitignore │ ├── README.md │ ├── angular.json │ ├── database.rules.json │ ├── firebase.json │ ├── firestore.indexes.json │ ├── firestore.rules │ ├── functions/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── package.json │ ├── seed/ │ │ ├── auth_export/ │ │ │ ├── accounts.json │ │ │ └── config.json │ │ ├── database_export/ │ │ │ └── angularfire2-test.json │ │ ├── firebase-export-metadata.json │ │ ├── firestore_export/ │ │ │ ├── all_namespaces/ │ │ │ │ └── all_kinds/ │ │ │ │ ├── all_namespaces_all_kinds.export_metadata │ │ │ │ └── output-0 │ │ │ └── firestore_export.overall_export_metadata │ │ └── storage_export/ │ │ ├── buckets.json │ │ └── metadata/ │ │ └── angularfire2-test.appspot.com/ │ │ └── google-g.png.json │ ├── src/ │ │ ├── app/ │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.config.client.ts │ │ │ ├── app.config.server.ts │ │ │ ├── app.config.ts │ │ │ ├── app.routes.server.ts │ │ │ ├── app.routes.ts │ │ │ ├── auth/ │ │ │ │ └── auth.component.ts │ │ │ ├── database/ │ │ │ │ └── database.component.ts │ │ │ ├── firestore/ │ │ │ │ └── firestore.component.ts │ │ │ ├── functions/ │ │ │ │ └── functions.component.ts │ │ │ ├── messaging/ │ │ │ │ └── messaging.component.ts │ │ │ ├── remote-config/ │ │ │ │ └── remote-config.component.ts │ │ │ ├── storage/ │ │ │ │ └── storage.component.ts │ │ │ └── upboats/ │ │ │ └── upboats.component.ts │ │ ├── environments/ │ │ │ └── environment.ts │ │ ├── index.html │ │ ├── main.server.ts │ │ ├── main.ts │ │ ├── server.ts │ │ └── styles.css │ ├── storage.rules │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── site/ │ ├── .eleventy.js │ ├── .firebaserc │ ├── .gitignore │ ├── firebase.json │ ├── package.json │ ├── postcss.config.js │ ├── scripts/ │ │ └── build.js │ └── src/ │ ├── _data/ │ │ └── nextprev.json │ ├── _includes/ │ │ ├── default.njk │ │ ├── guide.njk │ │ ├── next-prev.njk │ │ └── side-nav.njk │ ├── analytics/ │ │ ├── analytics.11tydata.json │ │ ├── getting-started.md │ │ └── index.md │ ├── auth/ │ │ ├── auth.11tydata.json │ │ ├── getting-started.md │ │ ├── index.md │ │ └── route-guards.md │ ├── firestore/ │ │ ├── collections.md │ │ ├── documents.md │ │ ├── firestore.11tydata.json │ │ └── index.md │ ├── functions/ │ │ ├── functions.11tydata.json │ │ ├── getting-started.md │ │ └── index.md │ ├── get-started/ │ │ ├── deploying.md │ │ ├── get-started.11tydata.json │ │ ├── index.md │ │ ├── local-development.md │ │ └── quick-start.md │ ├── index.md │ ├── ionic/ │ │ ├── authentication.md │ │ ├── getting-started.md │ │ ├── index.md │ │ └── ionic.11tydata.json │ ├── js/ │ │ ├── click-card.js │ │ ├── menu-button.js │ │ └── tab-switcher.js │ ├── messaging/ │ │ ├── getting-started.md │ │ ├── index.md │ │ └── messaging.11tydata.json │ ├── performance/ │ │ ├── getting-started.md │ │ ├── index.md │ │ └── performance.11tydata.json │ ├── remote-config/ │ │ ├── getting-started.md │ │ ├── index.md │ │ └── remote-config.11tydata.json │ ├── rtdb/ │ │ ├── index.md │ │ ├── lists.md │ │ ├── objects.md │ │ ├── querying.md │ │ └── rtdb.11tydata.json │ ├── shortcodes/ │ │ ├── buttons/ │ │ │ └── index.js │ │ ├── disclaimerprod/ │ │ │ └── index.js │ │ ├── filters/ │ │ │ └── index.js │ │ ├── headings/ │ │ │ └── index.js │ │ ├── includecode/ │ │ │ ├── fetch.js │ │ │ ├── from-local.js │ │ │ ├── index.js │ │ │ ├── snippets.js │ │ │ └── transform.js │ │ ├── index.js │ │ └── version/ │ │ └── index.js │ ├── storage/ │ │ ├── getting-started.md │ │ ├── index.md │ │ └── storage.11tydata.json │ ├── styles/ │ │ ├── prism.css │ │ ├── tailwind.config.js │ │ └── tailwind.css │ └── universal/ │ ├── cloud-functions.md │ ├── getting-started.md │ ├── index.md │ ├── prerendering.md │ └── universal.11tydata.json ├── src/ │ ├── ai/ │ │ ├── ai.module.ts │ │ ├── ai.spec.ts │ │ ├── ai.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── analytics/ │ │ ├── analytics.module.ts │ │ ├── analytics.spec.ts │ │ ├── analytics.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── screen-tracking.service.ts │ │ └── user-tracking.service.ts │ ├── app/ │ │ ├── app.module.ts │ │ ├── app.spec.ts │ │ ├── app.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── app-check/ │ │ ├── app-check.module.ts │ │ ├── app-check.spec.ts │ │ ├── app-check.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── auth/ │ │ ├── auth.module.ts │ │ ├── auth.spec.ts │ │ ├── auth.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ └── rxfire.ts │ ├── auth-guard/ │ │ ├── auth-guard.module.ts │ │ ├── auth-guard.spec.ts │ │ ├── auth-guard.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── compat/ │ │ ├── analytics/ │ │ │ ├── analytics.module.ts │ │ │ ├── analytics.spec.ts │ │ │ ├── analytics.ts │ │ │ ├── base.ts │ │ │ ├── index.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ ├── public_api.ts │ │ │ ├── screen-tracking.service.ts │ │ │ └── user-tracking.service.ts │ │ ├── angularfire2.spec.ts │ │ ├── auth/ │ │ │ ├── auth.module.ts │ │ │ ├── auth.spec.ts │ │ │ ├── auth.ts │ │ │ ├── base.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ └── public_api.ts │ │ ├── auth-guard/ │ │ │ ├── auth-guard.module.ts │ │ │ ├── auth-guard.spec.ts │ │ │ ├── auth-guard.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ └── public_api.ts │ │ ├── cache.ts │ │ ├── database/ │ │ │ ├── database.module.ts │ │ │ ├── database.spec.ts │ │ │ ├── database.ts │ │ │ ├── interfaces.ts │ │ │ ├── list/ │ │ │ │ ├── audit-trail.spec.ts │ │ │ │ ├── audit-trail.ts │ │ │ │ ├── changes.spec.ts │ │ │ │ ├── changes.ts │ │ │ │ ├── create-reference.ts │ │ │ │ ├── data-operation.ts │ │ │ │ ├── remove.ts │ │ │ │ ├── snapshot-changes.spec.ts │ │ │ │ ├── snapshot-changes.ts │ │ │ │ ├── state-changes.spec.ts │ │ │ │ ├── state-changes.ts │ │ │ │ └── utils.ts │ │ │ ├── ng-package.json │ │ │ ├── object/ │ │ │ │ ├── create-reference.ts │ │ │ │ └── snapshot-changes.ts │ │ │ ├── observable/ │ │ │ │ ├── fromRef.spec.ts │ │ │ │ └── fromRef.ts │ │ │ ├── package.json │ │ │ ├── public_api.ts │ │ │ ├── utils.spec.ts │ │ │ └── utils.ts │ │ ├── firebase.app.module.ts │ │ ├── firebase.app.ts │ │ ├── firestore/ │ │ │ ├── collection/ │ │ │ │ ├── changes.ts │ │ │ │ ├── collection.spec.ts │ │ │ │ └── collection.ts │ │ │ ├── collection-group/ │ │ │ │ ├── collection-group.spec.ts │ │ │ │ └── collection-group.ts │ │ │ ├── document/ │ │ │ │ ├── document.spec.ts │ │ │ │ └── document.ts │ │ │ ├── firestore.module.ts │ │ │ ├── firestore.spec.ts │ │ │ ├── firestore.ts │ │ │ ├── interfaces.ts │ │ │ ├── ng-package.json │ │ │ ├── observable/ │ │ │ │ └── fromRef.ts │ │ │ ├── package.json │ │ │ ├── public_api.ts │ │ │ └── utils.spec.ts │ │ ├── functions/ │ │ │ ├── base.ts │ │ │ ├── functions.module.ts │ │ │ ├── functions.spec.ts │ │ │ ├── functions.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ └── public_api.ts │ │ ├── messaging/ │ │ │ ├── base.ts │ │ │ ├── messaging.module.ts │ │ │ ├── messaging.spec.ts │ │ │ ├── messaging.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ └── public_api.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── performance/ │ │ │ ├── base.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ ├── performance.module.ts │ │ │ ├── performance.service.ts │ │ │ ├── performance.spec.ts │ │ │ ├── performance.ts │ │ │ └── public_api.ts │ │ ├── proxy.ts │ │ ├── public_api.ts │ │ ├── remote-config/ │ │ │ ├── base.ts │ │ │ ├── index.ts │ │ │ ├── interfaces.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ ├── public_api.ts │ │ │ ├── remote-config.module.ts │ │ │ ├── remote-config.spec.ts │ │ │ └── remote-config.ts │ │ └── storage/ │ │ ├── interfaces.ts │ │ ├── ng-package.json │ │ ├── observable/ │ │ │ └── fromTask.ts │ │ ├── package.json │ │ ├── pipes/ │ │ │ └── storageUrl.pipe.ts │ │ ├── public_api.ts │ │ ├── ref.ts │ │ ├── storage.module.ts │ │ ├── storage.spec.ts │ │ ├── storage.ts │ │ └── task.ts │ ├── core.ts │ ├── data-connect/ │ │ ├── data-connect.module.ts │ │ ├── data-connect.spec.ts │ │ ├── data-connect.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── overrides.ts │ │ ├── package.json │ │ └── public_api.ts │ ├── database/ │ │ ├── database.module.ts │ │ ├── database.spec.ts │ │ ├── database.ts │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ └── rxfire.ts │ ├── firestore/ │ │ ├── firebase.ts │ │ ├── firestore.module.ts │ │ ├── firestore.spec.ts │ │ ├── firestore.ts │ │ ├── lite/ │ │ │ ├── firebase.ts │ │ │ ├── lite.module.ts │ │ │ ├── lite.spec.ts │ │ │ ├── lite.ts │ │ │ ├── ng-package.json │ │ │ ├── package.json │ │ │ ├── public_api.ts │ │ │ └── rxfire.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ └── rxfire.ts │ ├── functions/ │ │ ├── firebase.ts │ │ ├── functions.module.ts │ │ ├── functions.spec.ts │ │ ├── functions.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ └── rxfire.ts │ ├── messaging/ │ │ ├── firebase.ts │ │ ├── messaging.module.ts │ │ ├── messaging.spec.ts │ │ ├── messaging.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── ng-package.json │ ├── package.json │ ├── performance/ │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── performance.module.ts │ │ ├── performance.spec.ts │ │ ├── performance.ts │ │ ├── public_api.ts │ │ └── rxfire.ts │ ├── public_api.ts │ ├── remote-config/ │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── remote-config.module.ts │ │ ├── remote-config.spec.ts │ │ ├── remote-config.ts │ │ └── rxfire.ts │ ├── schematics/ │ │ ├── add/ │ │ │ ├── index.ts │ │ │ └── schema.json │ │ ├── builders.json │ │ ├── collection.json │ │ ├── common.ts │ │ ├── deploy/ │ │ │ ├── actions.jasmine.ts │ │ │ ├── actions.ts │ │ │ ├── builder.ts │ │ │ ├── functions-templates.ts │ │ │ └── schema.json │ │ ├── firebaseTools.ts │ │ ├── interfaces.ts │ │ ├── migration.json │ │ ├── setup/ │ │ │ ├── index.ts │ │ │ ├── prompts.ts │ │ │ └── schema.json │ │ ├── tsconfig.json │ │ ├── update/ │ │ │ ├── index.ts │ │ │ └── v7/ │ │ │ └── index.ts │ │ ├── utils.ts │ │ └── versions.json │ ├── storage/ │ │ ├── firebase.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── rxfire.ts │ │ ├── storage.module.ts │ │ ├── storage.spec.ts │ │ └── storage.ts │ ├── test-config.ts │ ├── test.ts │ ├── utils.ts │ └── zones.ts ├── test/ │ ├── database.rules.json │ ├── firestore.indexes.json │ ├── firestore.rules │ ├── functions/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ └── storage.rules ├── tools/ │ ├── build.sh │ ├── build.ts │ └── jasmine.ts ├── tsconfig.base.json ├── tsconfig.build.json ├── tsconfig.jasmine.json ├── tsconfig.json ├── tsconfig.spec.json └── typedoc.json
SYMBOL INDEX (674 symbols across 131 files)
FILE: sample/src/app/app.component.ts
class AppComponent (line 38) | class AppComponent {
FILE: sample/src/app/auth/auth.component.ts
function _authState (line 11) | function _authState(auth: Auth): Observable<User|null> {
class AuthComponent (line 44) | class AuthComponent implements OnDestroy {
method constructor (line 65) | constructor() {
method ngOnDestroy (line 97) | ngOnDestroy(): void {
method logout (line 102) | async logout() {
method loginAnonymously (line 106) | async loginAnonymously() {
method loginWithGoogle (line 110) | async loginWithGoogle() {
FILE: sample/src/app/database/database.component.ts
class DatabaseComponent (line 18) | class DatabaseComponent {
method constructor (line 26) | constructor() {
FILE: sample/src/app/firestore/firestore.component.ts
class FirestoreComponent (line 17) | class FirestoreComponent {
method constructor (line 27) | constructor() {
FILE: sample/src/app/functions/functions.component.ts
class FunctionsComponent (line 18) | class FunctionsComponent {
method request (line 25) | async request() {
method constructor (line 34) | constructor() {
FILE: sample/src/app/messaging/messaging.component.ts
class MessagingComponent (line 20) | class MessagingComponent {
method request (line 28) | async request() {
FILE: sample/src/app/remote-config/remote-config.component.ts
class RemoteConfigComponent (line 13) | class RemoteConfigComponent {
FILE: sample/src/app/storage/storage.component.ts
constant TRANSPARENT_PNG (line 9) | const TRANSPARENT_PNG
class StorageComponent (line 22) | class StorageComponent {
method constructor (line 38) | constructor() {
FILE: sample/src/app/upboats/upboats.component.ts
type Animal (line 12) | type Animal = {
class UpboatsComponent (line 40) | class UpboatsComponent implements OnInit {
method constructor (line 59) | constructor() {
method ngOnInit (line 86) | ngOnInit(): void {
method upboat (line 89) | async upboat(id: string) {
method downboat (line 96) | async downboat(id: string) {
method newAnimal (line 103) | async newAnimal() {
FILE: site/.eleventy.js
function configureMarkdownIt (line 51) | function configureMarkdownIt() {
function registerShortcodes (line 86) | function registerShortcodes(eleventyConfig) {
FILE: site/scripts/build.js
function runExec (line 20) | function runExec(command) {
FILE: site/src/js/click-card.js
method connectedCallback (line 2) | connectedCallback() {
FILE: site/src/js/menu-button.js
method connectedCallback (line 2) | connectedCallback() {
FILE: site/src/js/tab-switcher.js
method connectedCallback (line 3) | connectedCallback() {
FILE: site/src/shortcodes/buttons/index.js
method create (line 20) | create (content, href, type='primary', external=false) {
FILE: site/src/shortcodes/disclaimerprod/index.js
method create (line 21) | create() {
FILE: site/src/shortcodes/filters/index.js
method create (line 7) | create(list, name) {
method create (line 15) | create(object, logName) {
method create (line 24) | create(object, spacer = 3) {
method create (line 47) | create(children, eleventyNavigation) {
method create (line 57) | create(children, eleventyNavigation) {
method create (line 78) | create(eleventyNavigation) {
FILE: site/src/shortcodes/headings/index.js
method create (line 21) | create (content) {
method create (line 29) | create (content) {
FILE: site/src/shortcodes/includecode/fetch.js
function convertToGitHubApiUrl (line 19) | function convertToGitHubApiUrl(githubPath) {
function fetchCode (line 27) | async function fetchCode(githubPath) {
FILE: site/src/shortcodes/includecode/from-local.js
function convertGitHubPathToLocal (line 6) | function convertGitHubPathToLocal(githubPath) {
function fetchCode (line 10) | async function fetchCode(githubPath = '') {
FILE: site/src/shortcodes/includecode/index.js
function embedInCodeticks (line 24) | function embedInCodeticks(code) {
method create (line 32) | create({ github_path }) {
method create (line 44) | async create({ eap_github_path, current_github_path }) {
method create (line 86) | async create({ title, eap_github_path, current_github_path, github_path ...
FILE: site/src/shortcodes/includecode/snippets.js
constant RE_START_SNIPPET (line 4) | const RE_START_SNIPPET = /\[START\s+([A-Za-z_]+)\s*\]/;
constant RE_END_SNIPPET (line 5) | const RE_END_SNIPPET = /\[END\s+([A-Za-z_]+)\s*\]/;
function isBlank (line 7) | function isBlank(line) {
function removeSectionsFromSnippet (line 14) | function removeSectionsFromSnippet(lines/* string[]*/) {
function adjustIndentation (line 27) | function adjustIndentation(lines /*: string[]*/) {
function removeFirstLineAfterComments (line 46) | function removeFirstLineAfterComments(lines /*: string[]*/) {
function processSnippet (line 60) | function processSnippet(code /*: string[]*/) /*: string*/ {
FILE: site/src/shortcodes/includecode/transform.js
function transform (line 21) | function transform(githubCode) {
FILE: site/src/shortcodes/version/index.js
method create (line 21) | create () {
FILE: src/ai/ai.module.ts
constant PROVIDED_AI_INSTANCES (line 17) | const PROVIDED_AI_INSTANCES = new InjectionToken<AI[]>('angularfire2.ai-...
function defaultAIInstanceFactory (line 19) | function defaultAIInstanceFactory(provided: FirebaseAI[]|undefined, defa...
function AIInstanceFactory (line 24) | function AIInstanceFactory(fn: (injector: Injector) => FirebaseAI) {
constant AI_INSTANCES_PROVIDER (line 31) | const AI_INSTANCES_PROVIDER = {
constant DEFAULT_AI_INSTANCE_PROVIDER (line 38) | const DEFAULT_AI_INSTANCE_PROVIDER = {
class AIModule (line 53) | class AIModule {
method constructor (line 54) | constructor() {
function provideAI (line 59) | function provideAI(fn: (injector: Injector) => FirebaseAI, ...deps: any[...
FILE: src/ai/ai.ts
type AI (line 8) | interface AI extends FirebaseAI {}
method constructor (line 11) | constructor(ai: FirebaseAI) {
class AI (line 10) | class AI {
method constructor (line 11) | constructor(ai: FirebaseAI) {
constant AI_PROVIDER_NAME (line 16) | const AI_PROVIDER_NAME = 'AI';
type AIInstances (line 19) | interface AIInstances extends Array<FirebaseAI> {}
method constructor (line 22) | constructor() {
class AIInstances (line 21) | class AIInstances {
method constructor (line 22) | constructor() {
FILE: src/analytics/analytics.module.ts
constant PROVIDED_ANALYTICS_INSTANCES (line 20) | const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken<Analytics[]>('an...
function defaultAnalyticsInstanceFactory (line 22) | function defaultAnalyticsInstanceFactory(provided: FirebaseAnalytics[]|u...
function analyticsInstanceFactory (line 28) | function analyticsInstanceFactory(fn: (injector: Injector) => FirebaseAn...
constant ANALYTICS_INSTANCES_PROVIDER (line 36) | const ANALYTICS_INSTANCES_PROVIDER = {
constant DEFAULT_ANALYTICS_INSTANCE_PROVIDER (line 43) | const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = {
class AnalyticsModule (line 59) | class AnalyticsModule {
method constructor (line 60) | constructor(
function provideAnalytics (line 68) | function provideAnalytics(fn: (injector: Injector) => FirebaseAnalytics,...
FILE: src/analytics/analytics.ts
type Analytics (line 8) | interface Analytics extends FirebaseAnalytics {}
method constructor (line 11) | constructor(analytics: FirebaseAnalytics) {
class Analytics (line 10) | class Analytics {
method constructor (line 11) | constructor(analytics: FirebaseAnalytics) {
constant ANALYTICS_PROVIDER_NAME (line 16) | const ANALYTICS_PROVIDER_NAME = 'analytics';
type AnalyticsInstances (line 19) | interface AnalyticsInstances extends Array<FirebaseAnalytics> {}
method constructor (line 22) | constructor() {
class AnalyticsInstances (line 21) | class AnalyticsInstances {
method constructor (line 22) | constructor() {
FILE: src/analytics/screen-tracking.service.ts
constant FIREBASE_EVENT_ORIGIN_KEY (line 12) | const FIREBASE_EVENT_ORIGIN_KEY = 'firebase_event_origin';
constant FIREBASE_PREVIOUS_SCREEN_CLASS_KEY (line 13) | const FIREBASE_PREVIOUS_SCREEN_CLASS_KEY = 'firebase_previous_class';
constant FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY (line 14) | const FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY = 'firebase_previous_id';
constant FIREBASE_PREVIOUS_SCREEN_NAME_KEY (line 15) | const FIREBASE_PREVIOUS_SCREEN_NAME_KEY = 'firebase_previous_screen';
constant FIREBASE_SCREEN_CLASS_KEY (line 16) | const FIREBASE_SCREEN_CLASS_KEY = 'firebase_screen_class';
constant FIREBASE_SCREEN_INSTANCE_ID_KEY (line 17) | const FIREBASE_SCREEN_INSTANCE_ID_KEY = 'firebase_screen_id';
constant FIREBASE_SCREEN_NAME_KEY (line 18) | const FIREBASE_SCREEN_NAME_KEY = 'firebase_screen';
constant OUTLET_KEY (line 19) | const OUTLET_KEY = 'outlet';
constant PAGE_PATH_KEY (line 20) | const PAGE_PATH_KEY = 'page_path';
constant PAGE_TITLE_KEY (line 21) | const PAGE_TITLE_KEY = 'page_title';
constant SCREEN_CLASS_KEY (line 22) | const SCREEN_CLASS_KEY = 'screen_class';
constant SCREEN_NAME_KEY (line 23) | const SCREEN_NAME_KEY = 'screen_name';
constant SCREEN_VIEW_EVENT (line 24) | const SCREEN_VIEW_EVENT = 'screen_view';
constant EVENT_ORIGIN_AUTO (line 25) | const EVENT_ORIGIN_AUTO = 'auto';
constant SCREEN_INSTANCE_DELIMITER (line 26) | const SCREEN_INSTANCE_DELIMITER = '#';
class ScreenTrackingService (line 144) | class ScreenTrackingService implements OnDestroy {
method constructor (line 148) | constructor(
method ngOnDestroy (line 174) | ngOnDestroy() {
FILE: src/analytics/user-tracking.service.ts
class UserTrackingService (line 10) | class UserTrackingService implements OnDestroy {
method constructor (line 15) | constructor(
method ngOnDestroy (line 42) | ngOnDestroy() {
FILE: src/app-check/app-check.module.ts
constant PROVIDED_APP_CHECK_INSTANCES (line 19) | const PROVIDED_APP_CHECK_INSTANCES = new InjectionToken<AppCheck[]>('ang...
function defaultAppCheckInstanceFactory (line 21) | function defaultAppCheckInstanceFactory(provided: FirebaseAppCheck[]|und...
constant LOCALHOSTS (line 26) | const LOCALHOSTS = ['localhost', '0.0.0.0', '127.0.0.1'];
function appCheckInstanceFactory (line 29) | function appCheckInstanceFactory(fn: (injector: Injector) => FirebaseApp...
constant APP_CHECK_INSTANCES_PROVIDER (line 40) | const APP_CHECK_INSTANCES_PROVIDER = {
constant DEFAULT_APP_CHECK_INSTANCE_PROVIDER (line 47) | const DEFAULT_APP_CHECK_INSTANCE_PROVIDER = {
class AppCheckModule (line 63) | class AppCheckModule {
method constructor (line 64) | constructor() {
function provideAppCheck (line 69) | function provideAppCheck(fn: (injector: Injector) => FirebaseAppCheck, ....
FILE: src/app-check/app-check.ts
constant APP_CHECK_PROVIDER_NAME (line 6) | const APP_CHECK_PROVIDER_NAME = 'app-check';
type AppCheck (line 10) | interface AppCheck extends FirebaseAppCheck {}
method constructor (line 13) | constructor(appCheck: FirebaseAppCheck) {
class AppCheck (line 12) | class AppCheck {
method constructor (line 13) | constructor(appCheck: FirebaseAppCheck) {
type AppCheckInstances (line 19) | interface AppCheckInstances extends Array<AppCheck> {}
method constructor (line 22) | constructor() {
class AppCheckInstances (line 21) | class AppCheckInstances {
method constructor (line 22) | constructor() {
FILE: src/app/app.module.ts
function defaultFirebaseAppFactory (line 17) | function defaultFirebaseAppFactory(provided: FirebaseApp[]|undefined) {
constant PROVIDED_FIREBASE_APPS (line 26) | const PROVIDED_FIREBASE_APPS = new InjectionToken<FirebaseApp[]>('angula...
constant DEFAULT_FIREBASE_APP_PROVIDER (line 31) | const DEFAULT_FIREBASE_APP_PROVIDER = {
constant FIREBASE_APPS_PROVIDER (line 39) | const FIREBASE_APPS_PROVIDER = {
function firebaseAppFactory (line 46) | function firebaseAppFactory(fn: (injector: Injector) => IFirebaseApp) {
class FirebaseAppModule (line 65) | class FirebaseAppModule {
method constructor (line 66) | constructor(@Inject(PLATFORM_ID) platformId: object) {
function provideFirebaseApp (line 77) | function provideFirebaseApp(fn: (injector: Injector) => IFirebaseApp, .....
FILE: src/app/app.ts
type FirebaseApp (line 19) | interface FirebaseApp extends IFirebaseApp {}
method constructor (line 22) | constructor(app: IFirebaseApp) {
class FirebaseApp (line 21) | class FirebaseApp {
method constructor (line 22) | constructor(app: IFirebaseApp) {
type FirebaseApps (line 28) | interface FirebaseApps extends Array<IFirebaseApp> {}
method constructor (line 31) | constructor() {
class FirebaseApps (line 30) | class FirebaseApps {
method constructor (line 31) | constructor() {
FILE: src/auth-guard/auth-guard.module.ts
class AuthGuardModule (line 9) | class AuthGuardModule {
method constructor (line 10) | constructor() {
FILE: src/auth-guard/auth-guard.spec.ts
class TestComponent (line 10) | class TestComponent { }
FILE: src/auth-guard/auth-guard.ts
type AuthPipeGenerator (line 8) | type AuthPipeGenerator = (next: ActivatedRouteSnapshot, state: RouterSta...
type AuthPipe (line 9) | type AuthPipe = UnaryFunction<Observable<User|null>, Observable<boolean|...
class AuthGuard (line 16) | class AuthGuard implements CanActivate {
method constructor (line 18) | constructor(private router: Router, private auth: Auth) {}
FILE: src/auth/auth.module.ts
constant PROVIDED_AUTH_INSTANCES (line 17) | const PROVIDED_AUTH_INSTANCES = new InjectionToken<Auth[]>('angularfire2...
function defaultAuthInstanceFactory (line 19) | function defaultAuthInstanceFactory(provided: FirebaseAuth[]|undefined, ...
function authInstanceFactory (line 24) | function authInstanceFactory(fn: (injector: Injector) => FirebaseAuth) {
constant AUTH_INSTANCES_PROVIDER (line 31) | const AUTH_INSTANCES_PROVIDER = {
constant DEFAULT_AUTH_INSTANCE_PROVIDER (line 38) | const DEFAULT_AUTH_INSTANCE_PROVIDER = {
class AuthModule (line 53) | class AuthModule {
method constructor (line 54) | constructor() {
function provideAuth (line 59) | function provideAuth(fn: (injector: Injector) => FirebaseAuth, ...deps: ...
FILE: src/auth/auth.ts
constant AUTH_PROVIDER_NAME (line 6) | const AUTH_PROVIDER_NAME = 'auth';
type Auth (line 10) | interface Auth extends FirebaseAuth {}
method constructor (line 13) | constructor(auth: FirebaseAuth) {
class Auth (line 12) | class Auth {
method constructor (line 13) | constructor(auth: FirebaseAuth) {
type AuthInstances (line 19) | interface AuthInstances extends Array<FirebaseAuth> {}
method constructor (line 22) | constructor() {
class AuthInstances (line 21) | class AuthInstances {
method constructor (line 22) | constructor() {
FILE: src/compat/analytics/analytics.module.ts
class AngularFireAnalyticsModule (line 11) | class AngularFireAnalyticsModule {
method constructor (line 12) | constructor(
FILE: src/compat/analytics/analytics.ts
type Config (line 12) | type Config = Record<string, any>;
constant COLLECTION_ENABLED (line 14) | const COLLECTION_ENABLED = new InjectionToken<boolean>('angularfire2.ana...
constant APP_VERSION (line 15) | const APP_VERSION = new InjectionToken<string>('angularfire2.analytics.a...
constant APP_NAME (line 16) | const APP_NAME = new InjectionToken<string>('angularfire2.analytics.appN...
constant DEBUG_MODE (line 17) | const DEBUG_MODE = new InjectionToken<boolean>('angularfire2.analytics.d...
constant CONFIG (line 18) | const CONFIG = new InjectionToken<Config>('angularfire2.analytics.config');
constant APP_NAME_KEY (line 20) | const APP_NAME_KEY = 'app_name';
constant APP_VERSION_KEY (line 21) | const APP_VERSION_KEY = 'app_version';
constant DEBUG_MODE_KEY (line 22) | const DEBUG_MODE_KEY = 'debug_mode';
constant GTAG_CONFIG_COMMAND (line 23) | const GTAG_CONFIG_COMMAND = 'config';
constant GTAG_FUNCTION_NAME (line 24) | const GTAG_FUNCTION_NAME = 'gtag';
constant DATA_LAYER_NAME (line 25) | const DATA_LAYER_NAME = 'dataLayer';
constant SEND_TO_KEY (line 26) | const SEND_TO_KEY = 'send_to';
type AngularFireAnalytics (line 29) | interface AngularFireAnalytics extends ɵPromiseProxy<firebase.analytics....
method updateConfig (line 40) | async updateConfig(config: Config) {
method constructor (line 45) | constructor(
class AngularFireAnalytics (line 35) | class AngularFireAnalytics {
method updateConfig (line 40) | async updateConfig(config: Config) {
method constructor (line 45) | constructor(
FILE: src/compat/analytics/screen-tracking.service.ts
constant SCREEN_VIEW_EVENT (line 12) | const SCREEN_VIEW_EVENT = 'screen_view';
class ScreenTrackingService (line 15) | class ScreenTrackingService implements OnDestroy {
method constructor (line 19) | constructor(
method ngOnDestroy (line 41) | ngOnDestroy() {
FILE: src/compat/analytics/user-tracking.service.ts
class UserTrackingService (line 10) | class UserTrackingService implements OnDestroy {
method constructor (line 16) | constructor(
method ngOnDestroy (line 48) | ngOnDestroy() {
FILE: src/compat/auth-guard/auth-guard.module.ts
class AngularFireAuthGuardModule (line 9) | class AngularFireAuthGuardModule {
method constructor (line 10) | constructor() {
FILE: src/compat/auth-guard/auth-guard.spec.ts
class TestComponent (line 9) | class TestComponent { }
FILE: src/compat/auth-guard/auth-guard.ts
type AuthPipeGenerator (line 8) | type AuthPipeGenerator = (next: ActivatedRouteSnapshot, state: RouterSta...
type AuthPipe (line 9) | type AuthPipe = UnaryFunction<Observable<firebase.User|null>, Observable...
class AngularFireAuthGuard (line 16) | class AngularFireAuthGuard implements CanActivate {
method constructor (line 18) | constructor(private router: Router, private auth: AngularFireAuth) {}
FILE: src/compat/auth/auth.module.ts
class AngularFireAuthModule (line 9) | class AngularFireAuthModule {
method constructor (line 10) | constructor() {
FILE: src/compat/auth/auth.ts
type AngularFireAuth (line 15) | interface AngularFireAuth extends ɵPromiseProxy<firebase.auth.Auth> {}
method constructor (line 87) | constructor(
type UseEmulatorArguments (line 17) | type UseEmulatorArguments = Parameters<firebase.auth.Auth['useEmulator']>;
constant USE_EMULATOR (line 18) | const USE_EMULATOR = new InjectionToken<UseEmulatorArguments>('angularfi...
constant SETTINGS (line 20) | const SETTINGS = new InjectionToken<firebase.auth.AuthSettings>('angular...
constant TENANT_ID (line 21) | const TENANT_ID = new InjectionToken<string>('angularfire2.auth.tenant-i...
constant LANGUAGE_CODE (line 22) | const LANGUAGE_CODE = new InjectionToken<string>('angularfire2.auth.lang...
constant USE_DEVICE_LANGUAGE (line 23) | const USE_DEVICE_LANGUAGE = new InjectionToken<boolean>('angularfire2.au...
constant PERSISTENCE (line 24) | const PERSISTENCE = new InjectionToken<string>('angularfire.auth.persist...
class AngularFireAuth (line 56) | class AngularFireAuth {
method constructor (line 87) | constructor(
FILE: src/compat/cache.ts
function ɵcacheInstance (line 3) | function ɵcacheInstance<T>(cacheKey: any, moduleName: string, appName: s...
function matchDep (line 18) | function matchDep(a: any, b: any) {
constant IS_HMR (line 26) | const IS_HMR = typeof module !== 'undefined' && !!(module as any).hot;
FILE: src/compat/database/database.module.ts
class AngularFireDatabaseModule (line 9) | class AngularFireDatabaseModule {
method constructor (line 10) | constructor() {
FILE: src/compat/database/database.ts
constant URL (line 24) | const URL = new InjectionToken<string>('angularfire2.realtimeDatabaseURL');
type UseEmulatorArguments (line 26) | type UseEmulatorArguments = Parameters<firebase.database.Database['useEm...
constant USE_EMULATOR (line 27) | const USE_EMULATOR = new InjectionToken<UseEmulatorArguments>('angularfi...
class AngularFireDatabase (line 32) | class AngularFireDatabase {
method constructor (line 36) | constructor(
method list (line 71) | list<T>(pathOrRef: PathReference, queryFn?: QueryFn): AngularFireList<...
method object (line 80) | object<T>(pathOrRef: PathReference): AngularFireObject<T> {
method createPushId (line 85) | createPushId() {
FILE: src/compat/database/interfaces.ts
type FirebaseOperation (line 4) | type FirebaseOperation = string | firebase.database.Reference | firebase...
type AngularFireList (line 6) | interface AngularFireList<T> {
type AngularFireObject (line 19) | interface AngularFireObject<T> {
type FirebaseOperationCases (line 28) | interface FirebaseOperationCases {
type QueryFn (line 35) | type QueryFn = (ref: DatabaseReference) => DatabaseQuery;
type ChildEvent (line 36) | type ChildEvent = 'child_added' | 'child_removed' | 'child_changed' | 'c...
type ListenEvent (line 37) | type ListenEvent = 'value' | ChildEvent;
type Action (line 39) | interface Action<T> {
type AngularFireAction (line 44) | interface AngularFireAction<T> extends Action<T> {
type SnapshotAction (line 49) | type SnapshotAction<T> = AngularFireAction<DatabaseSnapshot<T>>;
type Primitive (line 51) | type Primitive = number | string | boolean;
type DatabaseSnapshotExists (line 53) | interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapsh...
type DatabaseSnapshotDoesNotExist (line 59) | interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.Data...
type DatabaseSnapshot (line 65) | type DatabaseSnapshot<T> = DatabaseSnapshotExists<T> | DatabaseSnapshotD...
type DatabaseReference (line 67) | type DatabaseReference = firebase.database.Reference;
type DatabaseQuery (line 68) | type DatabaseQuery = firebase.database.Query;
type DataSnapshot (line 69) | type DataSnapshot = firebase.database.DataSnapshot;
type QueryReference (line 70) | type QueryReference = DatabaseReference | DatabaseQuery;
type PathReference (line 71) | type PathReference = QueryReference | string;
FILE: src/compat/database/list/audit-trail.spec.ts
function prepareAuditTrail (line 36) | function prepareAuditTrail(opts: { events?: ChildEvent[], skipnumber: nu...
FILE: src/compat/database/list/audit-trail.ts
function auditTrail (line 8) | function auditTrail<T>(query: DatabaseQuery, events?: ChildEvent[], sche...
type LoadedMetadata (line 16) | interface LoadedMetadata {
function loadedData (line 21) | function loadedData<T>(query: DatabaseQuery, scheduler?: SchedulerLike):...
function waitForLoaded (line 40) | function waitForLoaded<T>(query: DatabaseQuery, action$: Observable<Snap...
FILE: src/compat/database/list/changes.ts
function listChanges (line 8) | function listChanges<T = any>(ref: DatabaseQuery, events: ChildEvent[], ...
function positionFor (line 19) | function positionFor<T>(changes: SnapshotAction<T>[], key) {
function positionAfter (line 29) | function positionAfter<T>(changes: SnapshotAction<T>[], prevKey?: string) {
function buildView (line 42) | function buildView(current, action) {
FILE: src/compat/database/list/create-reference.ts
function createListReference (line 13) | function createListReference<T= any>(query: DatabaseQuery, afDatabase: A...
FILE: src/compat/database/list/data-operation.ts
function createDataOperationMethod (line 4) | function createDataOperationMethod(ref: DatabaseReference, operation: st...
FILE: src/compat/database/list/remove.ts
function createRemoveMethod (line 6) | function createRemoveMethod<T>(ref: DatabaseReference) {
FILE: src/compat/database/list/snapshot-changes.spec.ts
function prepareSnapshotChanges (line 37) | function prepareSnapshotChanges(opts: { events?: ChildEvent[], skipnumbe...
FILE: src/compat/database/list/snapshot-changes.ts
function snapshotChanges (line 6) | function snapshotChanges<T>(
FILE: src/compat/database/list/state-changes.spec.ts
function prepareStateChanges (line 36) | function prepareStateChanges(opts: { events?: ChildEvent[], skipnumber: ...
FILE: src/compat/database/list/state-changes.ts
function stateChanges (line 6) | function stateChanges<T>(query: DatabaseQuery, events?: ChildEvent[], sc...
FILE: src/compat/database/list/utils.ts
function validateEventsArray (line 3) | function validateEventsArray(events?: any[]) {
FILE: src/compat/database/object/create-reference.ts
function createObjectReference (line 8) | function createObjectReference<T= any>(query: DatabaseQuery, afDatabase:...
FILE: src/compat/database/object/snapshot-changes.ts
function createObjectSnapshotChanges (line 5) | function createObjectSnapshotChanges<T>(query: DatabaseQuery, scheduler?...
FILE: src/compat/database/observable/fromRef.ts
type SnapshotPrevKey (line 5) | interface SnapshotPrevKey<T> {
function fromRef (line 17) | function fromRef<T>(ref: DatabaseQuery,
FILE: src/compat/database/utils.ts
function isString (line 4) | function isString(value: any): boolean {
function isFirebaseDataSnapshot (line 8) | function isFirebaseDataSnapshot(value: any): boolean {
function isNil (line 12) | function isNil(obj: any): boolean {
function isFirebaseRef (line 16) | function isFirebaseRef(value: any): boolean {
function getRef (line 26) | function getRef(database: firebase.database.Database, pathRef: PathRefer...
function checkOperationCases (line 32) | function checkOperationCases(item: FirebaseOperation, cases: FirebaseOpe...
FILE: src/compat/firebase.app.module.ts
constant FIREBASE_OPTIONS (line 9) | const FIREBASE_OPTIONS = new InjectionToken<FirebaseOptions>('angularfir...
constant FIREBASE_APP_NAME (line 10) | const FIREBASE_APP_NAME = new InjectionToken<string | undefined>('angula...
function ɵfirebaseAppFactory (line 13) | function ɵfirebaseAppFactory(options: FirebaseOptions, zone: NgZone, nam...
constant FIREBASE_APP_PROVIDER (line 38) | const FIREBASE_APP_PROVIDER = {
class AngularFireModule (line 51) | class AngularFireModule {
method initializeApp (line 52) | static initializeApp(options: FirebaseOptions, nameOrConfig?: string |...
method constructor (line 62) | constructor(@Inject(PLATFORM_ID) platformId: object) {
FILE: src/compat/firebase.app.ts
type FirebaseApp (line 4) | interface FirebaseApp extends firebase.app.App {}
method constructor (line 7) | constructor(app: firebase.app.App) {
class FirebaseApp (line 6) | class FirebaseApp {
method constructor (line 7) | constructor(app: firebase.app.App) {
FILE: src/compat/firestore/collection-group/collection-group.spec.ts
function collectionHarness (line 19) | async function collectionHarness(afs: AngularFirestore, items: number, q...
FILE: src/compat/firestore/collection-group/collection-group.ts
class AngularFirestoreCollectionGroup (line 30) | class AngularFirestoreCollectionGroup<T = DocumentData> {
method constructor (line 37) | constructor(
method stateChanges (line 46) | stateChanges(events?: DocumentChangeType[]): Observable<DocumentChange...
method auditTrail (line 64) | auditTrail(events?: DocumentChangeType[]): Observable<DocumentChangeAc...
method snapshotChanges (line 72) | snapshotChanges(events?: DocumentChangeType[]): Observable<DocumentCha...
method valueChanges (line 90) | valueChanges<K extends string>(options: {idField?: K} = {}): Observabl...
method get (line 111) | get(options?: firebase.firestore.GetOptions) {
FILE: src/compat/firestore/collection/changes.ts
type ActionTupe (line 8) | type ActionTupe = [Action<QuerySnapshot<firebase.firestore.DocumentData>...
function docChanges (line 13) | function docChanges<T>(query: Query, scheduler?: SchedulerLike): Observa...
function sortedChanges (line 53) | function sortedChanges<T>(
function combineChanges (line 68) | function combineChanges<T>(current: DocumentChange<T>[], changes: Docume...
function sliceAndSplice (line 82) | function sliceAndSplice<T>(
function combineChange (line 98) | function combineChange<T>(combined: DocumentChange<T>[], change: Documen...
FILE: src/compat/firestore/collection/collection.spec.ts
function collectionHarness (line 20) | async function collectionHarness(afs: AngularFirestore, items: number, q...
function setup (line 180) | async function setup() {
FILE: src/compat/firestore/collection/collection.ts
type DocumentChangeTuple (line 12) | type DocumentChangeTuple<T> = [DocumentChangeAction<T>[], DocumentChange...
function validateEventsArray (line 14) | function validateEventsArray(events?: DocumentChangeType[]) {
class AngularFirestoreCollection (line 44) | class AngularFirestoreCollection<T = DocumentData> {
method constructor (line 56) | constructor(
method stateChanges (line 66) | stateChanges(events?: DocumentChangeType[]): Observable<DocumentChange...
method auditTrail (line 88) | auditTrail(events?: DocumentChangeType[]): Observable<DocumentChangeAc...
method snapshotChanges (line 96) | snapshotChanges(events?: DocumentChangeType[]): Observable<DocumentCha...
method valueChanges (line 114) | valueChanges<K extends string>(options: {idField?: K} = {}): Observabl...
method get (line 134) | get(options?: firebase.firestore.GetOptions) {
method add (line 147) | add(data: T): Promise<DocumentReference<T>> {
method doc (line 154) | doc<T2 = T>(path?: string): AngularFirestoreDocument<T2> {
FILE: src/compat/firestore/document/document.ts
class AngularFirestoreDocument (line 33) | class AngularFirestoreDocument<T = DocumentData> {
method constructor (line 40) | constructor(public ref: DocumentReference<T>, private afs: AngularFire...
method set (line 45) | set(data: T, options?: SetOptions): Promise<void> {
method update (line 52) | update(data: Partial<T>): Promise<void> {
method delete (line 59) | delete(): Promise<void> {
method collection (line 67) | collection<R = DocumentData>(path: string, queryFn?: QueryFn): Angular...
method snapshotChanges (line 76) | snapshotChanges(): Observable<Action<DocumentSnapshot<T>>> {
method valueChanges (line 91) | valueChanges<K extends string>(options: { idField?: K } = {}): Observa...
method get (line 105) | get(options?: firebase.firestore.GetOptions) {
FILE: src/compat/firestore/firestore.module.ts
class AngularFirestoreModule (line 10) | class AngularFirestoreModule {
method constructor (line 11) | constructor() {
method enablePersistence (line 17) | static enablePersistence(persistenceSettings?: PersistenceSettings): M...
FILE: src/compat/firestore/firestore.ts
constant ENABLE_PERSISTENCE (line 38) | const ENABLE_PERSISTENCE = new InjectionToken<boolean>('angularfire2.ena...
constant PERSISTENCE_SETTINGS (line 39) | const PERSISTENCE_SETTINGS = new InjectionToken<PersistenceSettings | un...
constant SETTINGS (line 40) | const SETTINGS = new InjectionToken<Settings>('angularfire2.firestore.se...
type UseEmulatorArguments (line 42) | type UseEmulatorArguments = Parameters<firebase.firestore.Firestore['use...
constant USE_EMULATOR (line 43) | const USE_EMULATOR = new InjectionToken<UseEmulatorArguments>('angularfi...
function associateQuery (line 57) | function associateQuery<T>(collectionRef: CollectionReference<T>, queryF...
class AngularFirestore (line 121) | class AngularFirestore {
method constructor (line 131) | constructor(
method collection (line 193) | collection<T>(pathOrRef: string | CollectionReference<T>, queryFn?: Qu...
method collectionGroup (line 210) | collectionGroup<T>(collectionId: string, queryGroupFn?: QueryGroupFn<T...
method doc (line 224) | doc<T>(pathOrRef: string | DocumentReference<T>): AngularFirestoreDocu...
method createId (line 238) | createId() {
FILE: src/compat/firestore/interfaces.ts
type Settings (line 4) | type Settings = firebase.firestore.Settings;
type CollectionReference (line 5) | type CollectionReference<T = DocumentData> = firebase.firestore.Collecti...
type DocumentReference (line 6) | type DocumentReference<T = DocumentData> = firebase.firestore.DocumentRe...
type PersistenceSettings (line 7) | type PersistenceSettings = firebase.firestore.PersistenceSettings;
type DocumentChangeType (line 8) | type DocumentChangeType = firebase.firestore.DocumentChangeType;
type SnapshotOptions (line 9) | type SnapshotOptions = firebase.firestore.SnapshotOptions;
type FieldPath (line 10) | type FieldPath = firebase.firestore.FieldPath;
type Query (line 11) | type Query<T = DocumentData> = firebase.firestore.Query<T>;
type SetOptions (line 13) | type SetOptions = firebase.firestore.SetOptions;
type DocumentData (line 14) | type DocumentData = firebase.firestore.DocumentData;
type DocumentSnapshotExists (line 16) | interface DocumentSnapshotExists<T> extends firebase.firestore.DocumentS...
type DocumentSnapshotDoesNotExist (line 21) | interface DocumentSnapshotDoesNotExist extends firebase.firestore.Docume...
type DocumentSnapshot (line 27) | type DocumentSnapshot<T> = DocumentSnapshotExists<T> | DocumentSnapshotD...
type QueryDocumentSnapshot (line 29) | interface QueryDocumentSnapshot<T> extends firebase.firestore.QueryDocum...
type QuerySnapshot (line 33) | interface QuerySnapshot<T> extends firebase.firestore.QuerySnapshot<T> {
type DocumentChange (line 37) | interface DocumentChange<T> extends firebase.firestore.DocumentChange<T> {
type DocumentChangeAction (line 41) | interface DocumentChangeAction<T> {
type Action (line 46) | interface Action<T> {
type Reference (line 51) | interface Reference {
type QueryFn (line 57) | type QueryFn<T = DocumentData> = (ref: CollectionReference<T>) => Query<T>;
type QueryGroupFn (line 59) | type QueryGroupFn<T = DocumentData> = (query: Query<T>) => Query<T>;
type AssociatedReference (line 83) | interface AssociatedReference<T = DocumentData> {
FILE: src/compat/firestore/observable/fromRef.ts
function _fromRef (line 5) | function _fromRef<R>(ref: Reference, scheduler: SchedulerLike = asyncSch...
function fromRef (line 24) | function fromRef<R, T>(ref: DocumentReference<T> | Query<T>, scheduler?:...
function fromDocRef (line 28) | function fromDocRef<T>(ref: DocumentReference<T>, scheduler?: SchedulerL...
function fromCollectionRef (line 46) | function fromCollectionRef<T>(ref: Query<T>, scheduler?: SchedulerLike):...
FILE: src/compat/firestore/utils.spec.ts
type Stock (line 5) | interface Stock {
constant FAKE_STOCK_DATA (line 10) | const FAKE_STOCK_DATA = { name: 'FAKE', price: 1 };
function deleteThemAll (line 34) | function deleteThemAll(names, ref) {
function delayUpdate (line 39) | function delayUpdate<T>(collection: AngularFirestoreCollection<T>|fireba...
function delayAdd (line 45) | function delayAdd<T>(collection: AngularFirestoreCollection<T>|firebase....
function delayDelete (line 51) | function delayDelete<T>(collection: AngularFirestoreCollection<T>|fireba...
FILE: src/compat/functions/functions.module.ts
class AngularFireFunctionsModule (line 9) | class AngularFireFunctionsModule {
method constructor (line 10) | constructor() {
FILE: src/compat/functions/functions.ts
constant ORIGIN (line 13) | const ORIGIN = new InjectionToken<string>('angularfire2.functions.origin');
constant REGION (line 14) | const REGION = new InjectionToken<string>('angularfire2.functions.region');
type UseEmulatorArguments (line 16) | type UseEmulatorArguments = Parameters<firebase.functions.Functions['use...
constant USE_EMULATOR (line 17) | const USE_EMULATOR = new InjectionToken<UseEmulatorArguments>('angularfi...
type AngularFireFunctions (line 21) | interface AngularFireFunctions extends Omit<ɵPromiseProxy<firebase.funct...
method constructor (line 31) | constructor(
class AngularFireFunctions (line 27) | class AngularFireFunctions {
method constructor (line 31) | constructor(
FILE: src/compat/messaging/messaging.module.ts
class AngularFireMessagingModule (line 9) | class AngularFireMessagingModule {
method constructor (line 10) | constructor() {
FILE: src/compat/messaging/messaging.spec.ts
constant FIREBASE_APP_NAME_TOO (line 31) | const FIREBASE_APP_NAME_TOO = (Math.random() + 1).toString(36).substring...
FILE: src/compat/messaging/messaging.ts
constant VAPID_KEY (line 12) | const VAPID_KEY = new InjectionToken<string>('angularfire2.messaging.vap...
constant SERVICE_WORKER (line 13) | const SERVICE_WORKER = new InjectionToken<Promise<ServiceWorkerRegistrat...
type AngularFireMessaging (line 16) | interface AngularFireMessaging extends Omit<ɵPromiseProxy<firebase.messa...
method constructor (line 31) | constructor(
class AngularFireMessaging (line 22) | class AngularFireMessaging {
method constructor (line 31) | constructor(
FILE: src/compat/performance/performance.module.ts
class AngularFirePerformanceModule (line 10) | class AngularFirePerformanceModule {
method constructor (line 11) | constructor(
FILE: src/compat/performance/performance.service.ts
constant IS_STABLE_START_MARK (line 5) | const IS_STABLE_START_MARK = 'Zone';
constant IS_STABLE_END_MARK (line 6) | const IS_STABLE_END_MARK = '_isStableEnd';
class PerformanceMonitoringService (line 9) | class PerformanceMonitoringService implements OnDestroy {
method constructor (line 13) | constructor(appRef: ApplicationRef) {
method ngOnDestroy (line 26) | ngOnDestroy() {
FILE: src/compat/performance/performance.ts
constant INSTRUMENTATION_ENABLED (line 10) | const INSTRUMENTATION_ENABLED = new InjectionToken<boolean>('angularfire...
constant DATA_COLLECTION_ENABLED (line 11) | const DATA_COLLECTION_ENABLED = new InjectionToken<boolean>('angularfire...
type AngularFirePerformance (line 14) | interface AngularFirePerformance extends ɵPromiseProxy<firebase.performa...
method constructor (line 24) | constructor(
class AngularFirePerformance (line 20) | class AngularFirePerformance {
method constructor (line 24) | constructor(
FILE: src/compat/proxy.ts
type MyFunction (line 4) | type MyFunction = (...args: any[]) => any;
type FunctionPropertyNames (line 5) | type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends MyFunctio...
type ReturnTypeOrNever (line 6) | type ReturnTypeOrNever<T> = T extends MyFunction ? ReturnType<T> : never;
type ParametersOrNever (line 7) | type ParametersOrNever<T> = T extends MyFunction ? Parameters<T> : never;
type PromiseReturningFunctionPropertyNames (line 8) | type PromiseReturningFunctionPropertyNames<T> = {
type NonPromiseReturningFunctionPropertyNames (line 11) | type NonPromiseReturningFunctionPropertyNames<T> = {
type NonFunctionPropertyNames (line 14) | type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends MyFunc...
type ɵPromiseProxy (line 16) | type ɵPromiseProxy<T> = { [K in NonFunctionPropertyNames<T>]: Promise<T[...
FILE: src/compat/remote-config/interfaces.ts
type Settings (line 3) | type Settings = firebase.remoteConfig.Settings;
FILE: src/compat/remote-config/remote-config.module.ts
class AngularFireRemoteConfigModule (line 9) | class AngularFireRemoteConfigModule {
method constructor (line 10) | constructor() {
FILE: src/compat/remote-config/remote-config.spec.ts
constant FIREBASE_APP_NAME_TOO (line 31) | const FIREBASE_APP_NAME_TOO = (Math.random() + 1).toString(36).substring...
FILE: src/compat/remote-config/remote-config.ts
type ConfigTemplate (line 27) | type ConfigTemplate = Record<string, string | number | boolean>;
constant SETTINGS (line 29) | const SETTINGS = new InjectionToken<Settings>('angularfire2.remoteConfig...
constant DEFAULTS (line 30) | const DEFAULTS = new InjectionToken<ConfigTemplate>('angularfire2.remote...
type AngularFireRemoteConfig (line 33) | interface AngularFireRemoteConfig extends ɵPromiseProxy<firebase.remoteC...
method constructor (line 126) | constructor(
constant AS_TO_FN (line 36) | const AS_TO_FN = { strings: 'asString', numbers: 'asNumber', booleans: '...
constant STATIC_VALUES (line 37) | const STATIC_VALUES = { numbers: 0, booleans: false, strings: undefined };
class Value (line 51) | class Value implements firebase.remoteConfig.Value {
method asBoolean (line 52) | asBoolean() {
method asString (line 56) | asString() {
method asNumber (line 60) | asNumber() {
method getSource (line 64) | getSource() {
method constructor (line 68) | constructor(public _source: firebase.remoteConfig.ValueSource, public ...
class Parameter (line 73) | class Parameter extends Value {
method constructor (line 74) | constructor(public key: string, public fetchTimeMillis: number, source...
class AngularFireRemoteConfig (line 116) | class AngularFireRemoteConfig {
method constructor (line 126) | constructor(
method next (line 219) | next(val) {
method error (line 224) | error(err) {
method complete (line 230) | complete() {
function scanToObject (line 259) | function scanToObject<T extends ConfigTemplate>(to: 'numbers' | 'boolean...
function mapToObject (line 285) | function mapToObject<T extends ConfigTemplate>(to: 'numbers' | 'booleans...
FILE: src/compat/storage/interfaces.ts
type UploadTask (line 3) | type UploadTask = firebase.storage.UploadTask;
type UploadTaskSnapshot (line 4) | type UploadTaskSnapshot = firebase.storage.UploadTaskSnapshot;
type UploadMetadata (line 5) | type UploadMetadata = firebase.storage.UploadMetadata;
type SettableMetadata (line 7) | type SettableMetadata = firebase.storage.SettableMetadata;
type Reference (line 8) | type Reference = firebase.storage.Reference;
type StringFormat (line 9) | type StringFormat = firebase.storage.StringFormat;
type ListResult (line 10) | type ListResult = firebase.storage.ListResult;
type ListOptions (line 11) | type ListOptions = firebase.storage.ListOptions;
FILE: src/compat/storage/observable/fromTask.ts
function fromTask (line 10) | function fromTask(task: UploadTask) {
FILE: src/compat/storage/pipes/storageUrl.pipe.ts
class GetDownloadURLPipe (line 12) | class GetDownloadURLPipe implements PipeTransform, OnDestroy {
method constructor (line 18) | constructor(
method transform (line 26) | transform(path: string) {
method ngOnDestroy (line 38) | ngOnDestroy() {
class GetDownloadURLPipeModule (line 48) | class GetDownloadURLPipeModule {}
FILE: src/compat/storage/ref.ts
type AngularFireStorageReference (line 9) | interface AngularFireStorageReference {
function createStorageRef (line 25) | function createStorageRef(
FILE: src/compat/storage/storage.module.ts
class AngularFireStorageModule (line 12) | class AngularFireStorageModule {
method constructor (line 13) | constructor() {
FILE: src/compat/storage/storage.ts
constant BUCKET (line 11) | const BUCKET = new InjectionToken<string>('angularfire2.storageBucket');
constant MAX_UPLOAD_RETRY_TIME (line 12) | const MAX_UPLOAD_RETRY_TIME = new InjectionToken<number>('angularfire2.s...
constant MAX_OPERATION_RETRY_TIME (line 13) | const MAX_OPERATION_RETRY_TIME = new InjectionToken<number>('angularfire...
type UseEmulatorArguments (line 15) | type UseEmulatorArguments = Parameters<firebase.storage.Storage['useEmul...
constant USE_EMULATOR (line 16) | const USE_EMULATOR = new InjectionToken<UseEmulatorArguments>('angularfi...
class AngularFireStorage (line 28) | class AngularFireStorage {
method constructor (line 32) | constructor(
method ref (line 62) | ref(path: string) {
method refFromURL (line 66) | refFromURL(path: string) {
method upload (line 70) | upload(path: string, data: any, metadata?: UploadMetadata) {
FILE: src/compat/storage/task.ts
type AngularFireUploadTask (line 6) | interface AngularFireUploadTask {
function createUploadTask (line 25) | function createUploadTask(task: UploadTask): AngularFireUploadTask {
FILE: src/core.ts
constant VERSION (line 5) | const VERSION = new Version('ANGULARFIRE2_VERSION');
type FirebaseAppWithContainer (line 13) | interface FirebaseAppWithContainer extends FirebaseApp {
function ɵgetDefaultInstanceOf (line 17) | function ɵgetDefaultInstanceOf<T= unknown>(identifier: string, provided:...
FILE: src/data-connect/data-connect.module.ts
constant PROVIDED_DATA_CONNECT_INSTANCES (line 15) | const PROVIDED_DATA_CONNECT_INSTANCES = new InjectionToken<DataConnect[]...
function defaultDataConnectInstanceFactory (line 17) | function defaultDataConnectInstanceFactory(provided: DataConnect[]|undef...
function dataConnectInstanceFactory (line 21) | function dataConnectInstanceFactory(fn: (injector: Injector) => DataConn...
constant DATA_CONNECT_INSTANCES_PROVIDER (line 27) | const DATA_CONNECT_INSTANCES_PROVIDER = {
constant DEFAULT_DATA_CONNECT_INSTANCE_PROVIDER (line 34) | const DEFAULT_DATA_CONNECT_INSTANCE_PROVIDER = {
class DataConnectModule (line 49) | class DataConnectModule {
method constructor (line 50) | constructor() {
function provideDataConnect (line 55) | function provideDataConnect(fn: (injector: Injector) => DataConnect, ......
FILE: src/data-connect/data-connect.ts
constant DATA_CONNECT_PROVIDER_NAME (line 8) | const DATA_CONNECT_PROVIDER_NAME = 'data-connect';
type DataConnectInstances (line 11) | interface DataConnectInstances extends Array<DataConnect> {}
method constructor (line 14) | constructor() {
class DataConnectInstances (line 13) | class DataConnectInstances {
method constructor (line 14) | constructor() {
FILE: src/database/database.module.ts
constant PROVIDED_DATABASE_INSTANCES (line 18) | const PROVIDED_DATABASE_INSTANCES = new InjectionToken<Database[]>('angu...
function defaultDatabaseInstanceFactory (line 20) | function defaultDatabaseInstanceFactory(provided: FirebaseDatabase[]|und...
function databaseInstanceFactory (line 25) | function databaseInstanceFactory(fn: (injector: Injector) => FirebaseDat...
constant DATABASE_INSTANCES_PROVIDER (line 32) | const DATABASE_INSTANCES_PROVIDER = {
constant DEFAULT_DATABASE_INSTANCE_PROVIDER (line 39) | const DEFAULT_DATABASE_INSTANCE_PROVIDER = {
class DatabaseModule (line 54) | class DatabaseModule {
method constructor (line 55) | constructor() {
function provideDatabase (line 60) | function provideDatabase(fn: (injector: Injector) => FirebaseDatabase, ....
FILE: src/database/database.ts
type Database (line 8) | interface Database extends FirebaseDatabase {}
method constructor (line 11) | constructor(database: FirebaseDatabase) {
class Database (line 10) | class Database {
method constructor (line 11) | constructor(database: FirebaseDatabase) {
constant DATABASE_PROVIDER_NAME (line 16) | const DATABASE_PROVIDER_NAME = 'database';
type DatabaseInstances (line 19) | interface DatabaseInstances extends Array<FirebaseDatabase> {}
method constructor (line 22) | constructor() {
class DatabaseInstances (line 21) | class DatabaseInstances {
method constructor (line 22) | constructor() {
FILE: src/firestore/firestore.module.ts
constant PROVIDED_FIRESTORE_INSTANCES (line 18) | const PROVIDED_FIRESTORE_INSTANCES = new InjectionToken<Firestore[]>('an...
function defaultFirestoreInstanceFactory (line 20) | function defaultFirestoreInstanceFactory(provided: FirebaseFirestore[]|u...
function firestoreInstanceFactory (line 25) | function firestoreInstanceFactory(fn: (injector: Injector) => FirebaseFi...
constant FIRESTORE_INSTANCES_PROVIDER (line 32) | const FIRESTORE_INSTANCES_PROVIDER = {
constant DEFAULT_FIRESTORE_INSTANCE_PROVIDER (line 39) | const DEFAULT_FIRESTORE_INSTANCE_PROVIDER = {
class FirestoreModule (line 54) | class FirestoreModule {
method constructor (line 55) | constructor() {
function provideFirestore (line 60) | function provideFirestore(fn: (injector: Injector) => FirebaseFirestore,...
FILE: src/firestore/firestore.ts
type Firestore (line 8) | interface Firestore extends FirebaseFirestore {}
method constructor (line 11) | constructor(firestore: FirebaseFirestore) {
class Firestore (line 10) | class Firestore {
method constructor (line 11) | constructor(firestore: FirebaseFirestore) {
constant FIRESTORE_PROVIDER_NAME (line 16) | const FIRESTORE_PROVIDER_NAME = 'firestore';
type FirestoreInstances (line 19) | interface FirestoreInstances extends Array<FirebaseFirestore> {}
method constructor (line 22) | constructor() {
class FirestoreInstances (line 21) | class FirestoreInstances {
method constructor (line 22) | constructor() {
FILE: src/firestore/lite/lite.module.ts
constant PROVIDED_FIRESTORE_INSTANCES (line 18) | const PROVIDED_FIRESTORE_INSTANCES = new InjectionToken<Firestore[]>('an...
function defaultFirestoreInstanceFactory (line 20) | function defaultFirestoreInstanceFactory(provided: FirebaseFirestore[]|u...
function firestoreInstanceFactory (line 25) | function firestoreInstanceFactory(fn: (injector: Injector) => FirebaseFi...
constant FIRESTORE_INSTANCES_PROVIDER (line 32) | const FIRESTORE_INSTANCES_PROVIDER = {
constant DEFAULT_FIRESTORE_INSTANCE_PROVIDER (line 39) | const DEFAULT_FIRESTORE_INSTANCE_PROVIDER = {
class FirestoreModule (line 54) | class FirestoreModule {
method constructor (line 55) | constructor() {
function provideFirestore (line 60) | function provideFirestore(fn: (injector: Injector) => FirebaseFirestore,...
FILE: src/firestore/lite/lite.ts
type Firestore (line 8) | interface Firestore extends FirebaseFirestore {}
method constructor (line 11) | constructor(firestore: FirebaseFirestore) {
class Firestore (line 10) | class Firestore {
method constructor (line 11) | constructor(firestore: FirebaseFirestore) {
constant FIRESTORE_PROVIDER_NAME (line 16) | const FIRESTORE_PROVIDER_NAME = 'firestore/lite';
type FirestoreInstances (line 19) | interface FirestoreInstances extends Array<FirebaseFirestore> {}
method constructor (line 22) | constructor() {
class FirestoreInstances (line 21) | class FirestoreInstances {
method constructor (line 22) | constructor() {
FILE: src/functions/functions.module.ts
constant PROVIDED_FUNCTIONS_INSTANCES (line 18) | const PROVIDED_FUNCTIONS_INSTANCES = new InjectionToken<Functions[]>('an...
function defaultFunctionsInstanceFactory (line 20) | function defaultFunctionsInstanceFactory(provided: FirebaseFunctions[]|u...
function functionsInstanceFactory (line 25) | function functionsInstanceFactory(fn: (injector: Injector) => FirebaseFu...
constant FUNCTIONS_INSTANCES_PROVIDER (line 32) | const FUNCTIONS_INSTANCES_PROVIDER = {
constant DEFAULT_FUNCTIONS_INSTANCE_PROVIDER (line 39) | const DEFAULT_FUNCTIONS_INSTANCE_PROVIDER = {
class FunctionsModule (line 54) | class FunctionsModule {
method constructor (line 55) | constructor() {
function provideFunctions (line 60) | function provideFunctions(fn: (injector: Injector) => FirebaseFunctions,...
FILE: src/functions/functions.ts
type Functions (line 8) | interface Functions extends FirebaseFunctions {}
method constructor (line 11) | constructor(functions: FirebaseFunctions) {
class Functions (line 10) | class Functions {
method constructor (line 11) | constructor(functions: FirebaseFunctions) {
constant FUNCTIONS_PROVIDER_NAME (line 16) | const FUNCTIONS_PROVIDER_NAME = 'functions';
type FunctionsInstances (line 19) | interface FunctionsInstances extends Array<FirebaseFunctions> {}
method constructor (line 22) | constructor() {
class FunctionsInstances (line 21) | class FunctionsInstances {
method constructor (line 22) | constructor() {
FILE: src/messaging/messaging.module.ts
constant PROVIDED_MESSAGING_INSTANCES (line 18) | const PROVIDED_MESSAGING_INSTANCES = new InjectionToken<Messaging[]>('an...
function defaultMessagingInstanceFactory (line 20) | function defaultMessagingInstanceFactory(provided: FirebaseMessaging[]|u...
function messagingInstanceFactory (line 26) | function messagingInstanceFactory(fn: (injector: Injector) => FirebaseMe...
constant MESSAGING_INSTANCES_PROVIDER (line 34) | const MESSAGING_INSTANCES_PROVIDER = {
constant DEFAULT_MESSAGING_INSTANCE_PROVIDER (line 41) | const DEFAULT_MESSAGING_INSTANCE_PROVIDER = {
class MessagingModule (line 57) | class MessagingModule {
method constructor (line 58) | constructor() {
function provideMessaging (line 63) | function provideMessaging(fn: (injector: Injector) => FirebaseMessaging,...
FILE: src/messaging/messaging.ts
type Messaging (line 8) | interface Messaging extends FirebaseMessaging {}
method constructor (line 11) | constructor(messaging: FirebaseMessaging) {
class Messaging (line 10) | class Messaging {
method constructor (line 11) | constructor(messaging: FirebaseMessaging) {
constant MESSAGING_PROVIDER_NAME (line 16) | const MESSAGING_PROVIDER_NAME = 'messaging';
type MessagingInstances (line 19) | interface MessagingInstances extends Array<FirebaseMessaging> {}
method constructor (line 22) | constructor() {
class MessagingInstances (line 21) | class MessagingInstances {
method constructor (line 22) | constructor() {
FILE: src/performance/performance.module.ts
constant PROVIDED_PERFORMANCE_INSTANCES (line 18) | const PROVIDED_PERFORMANCE_INSTANCES = new InjectionToken<Performance[]>...
function defaultPerformanceInstanceFactory (line 20) | function defaultPerformanceInstanceFactory(
function performanceInstanceFactory (line 31) | function performanceInstanceFactory(fn: (injector: Injector) => Firebase...
constant PERFORMANCE_INSTANCES_PROVIDER (line 40) | const PERFORMANCE_INSTANCES_PROVIDER = {
constant DEFAULT_PERFORMANCE_INSTANCE_PROVIDER (line 47) | const DEFAULT_PERFORMANCE_INSTANCE_PROVIDER = {
class PerformanceModule (line 63) | class PerformanceModule {
method constructor (line 64) | constructor() {
function providePerformance (line 69) | function providePerformance(
FILE: src/performance/performance.ts
type Performance (line 8) | interface Performance extends FirebasePerformance {}
method constructor (line 11) | constructor(performance: FirebasePerformance) {
class Performance (line 10) | class Performance {
method constructor (line 11) | constructor(performance: FirebasePerformance) {
constant PERFORMANCE_PROVIDER_NAME (line 16) | const PERFORMANCE_PROVIDER_NAME = 'performance';
type PerformanceInstances (line 19) | interface PerformanceInstances extends Array<FirebasePerformance> {}
method constructor (line 22) | constructor() {
class PerformanceInstances (line 21) | class PerformanceInstances {
method constructor (line 22) | constructor() {
FILE: src/remote-config/remote-config.module.ts
constant PROVIDED_REMOTE_CONFIG_INSTANCES (line 18) | const PROVIDED_REMOTE_CONFIG_INSTANCES = new InjectionToken<RemoteConfig...
function defaultRemoteConfigInstanceFactory (line 20) | function defaultRemoteConfigInstanceFactory(
function remoteConfigInstanceFactory (line 30) | function remoteConfigInstanceFactory(fn: (injector: Injector) => Firebas...
constant REMOTE_CONFIG_INSTANCES_PROVIDER (line 38) | const REMOTE_CONFIG_INSTANCES_PROVIDER = {
constant DEFAULT_REMOTE_CONFIG_INSTANCE_PROVIDER (line 45) | const DEFAULT_REMOTE_CONFIG_INSTANCE_PROVIDER = {
class RemoteConfigModule (line 61) | class RemoteConfigModule {
method constructor (line 62) | constructor() {
function provideRemoteConfig (line 67) | function provideRemoteConfig(
FILE: src/remote-config/remote-config.ts
type RemoteConfig (line 8) | interface RemoteConfig extends FirebaseRemoteConfig {}
method constructor (line 11) | constructor(remoteConfig: FirebaseRemoteConfig) {
class RemoteConfig (line 10) | class RemoteConfig {
method constructor (line 11) | constructor(remoteConfig: FirebaseRemoteConfig) {
constant REMOTE_CONFIG_PROVIDER_NAME (line 16) | const REMOTE_CONFIG_PROVIDER_NAME = 'remote-config';
type RemoteConfigInstances (line 19) | interface RemoteConfigInstances extends Array<FirebaseRemoteConfig> {}
method constructor (line 22) | constructor() {
class RemoteConfigInstances (line 21) | class RemoteConfigInstances {
method constructor (line 22) | constructor() {
FILE: src/schematics/common.ts
function safeReadJSON (line 21) | function safeReadJSON(path: string, tree: Tree) {
FILE: src/schematics/deploy/actions.jasmine.ts
constant FIREBASE_PROJECT (line 13) | const FIREBASE_PROJECT = 'ikachu-aa3ef';
constant PROJECT (line 14) | const PROJECT = 'pirojok-project';
constant STATIC_BUILD_TARGET (line 15) | const STATIC_BUILD_TARGET: BuildTarget = {
constant FIREBASE_TOKEN (line 19) | const FIREBASE_TOKEN = 'kkasllkascnkjnskjsdcskdckskdksdkjc';
constant SERVER_BUILD_TARGET (line 21) | const SERVER_BUILD_TARGET: BuildTarget = {
method moveSync (line 34) | moveSync(_: string, __: string) {
method renameSync (line 36) | renameSync(_: string, __: string) {
method writeFileSync (line 38) | writeFileSync(_: string, __: string) {
method copySync (line 40) | copySync(_: string, __: string) {
method removeSync (line 42) | removeSync(_: string) {
method existsSync (line 44) | existsSync(_: string) {
method init (line 66) | init() {
FILE: src/schematics/deploy/actions.ts
constant DEFAULT_EMULATOR_PORT (line 21) | const DEFAULT_EMULATOR_PORT = 5000;
constant DEFAULT_EMULATOR_HOST (line 22) | const DEFAULT_EMULATOR_HOST = 'localhost';
constant DEFAULT_CLOUD_RUN_OPTIONS (line 24) | const DEFAULT_CLOUD_RUN_OPTIONS: Partial<CloudRunOptions> = {
type DeployBuilderOptions (line 62) | type DeployBuilderOptions = DeployBuilderSchema & Record<string, any>;
function deploy (line 389) | async function deploy(
FILE: src/schematics/deploy/functions-templates.ts
constant DEFAULT_NODE_VERSION (line 3) | const DEFAULT_NODE_VERSION = 14;
constant DEFAULT_FUNCTION_NAME (line 4) | const DEFAULT_FUNCTION_NAME = 'ssr';
constant DEFAULT_FUNCTION_REGION (line 6) | const DEFAULT_FUNCTION_REGION = 'us-central1';
constant DEFAULT_RUNTIME_OPTIONS (line 8) | const DEFAULT_RUNTIME_OPTIONS = {
FILE: src/schematics/interfaces.ts
type FEATURES (line 3) | const enum FEATURES {
type PROJECT_TYPE (line 33) | const enum PROJECT_TYPE { Static, CloudFunctions, CloudRun, WebFrameworks }
type NgAddOptions (line 35) | interface NgAddOptions {
type NgAddNormalizedOptions (line 40) | interface NgAddNormalizedOptions {
type DeployOptions (line 51) | interface DeployOptions {
type FirebaseProject (line 55) | interface FirebaseProject {
type FirebaseDeployConfig (line 64) | interface FirebaseDeployConfig {
type FirebaseApp (line 71) | interface FirebaseApp {
type FirebaseHostingSite (line 79) | interface FirebaseHostingSite {
type FirebaseSDKConfig (line 86) | interface FirebaseSDKConfig {
type FirebaseTools (line 92) | interface FirebaseTools {
type FirebaseHostingRewrite (line 139) | interface FirebaseHostingRewrite {
type FirebaseHostingConfig (line 145) | interface FirebaseHostingConfig {
type FirebaseFunctionsConfig (line 152) | type FirebaseFunctionsConfig = Record<string, any>;
type DataConnectConfig (line 154) | interface DataConnectConfig {
type FirebaseJSON (line 158) | interface FirebaseJSON {
type FirebaseRcTarget (line 164) | interface FirebaseRcTarget {
type FirebaseRc (line 168) | interface FirebaseRc {
type DeployBuilderSchema (line 173) | interface DeployBuilderSchema {
type CloudRunOptions (line 195) | interface CloudRunOptions {
type BuildTarget (line 205) | interface BuildTarget {
type FSHost (line 210) | interface FSHost {
type WorkspaceProject (line 219) | interface WorkspaceProject {
type Workspace (line 231) | interface Workspace {
type ConnectorConfig (line 236) | interface ConnectorConfig {
type ConnectorYaml (line 241) | interface ConnectorYaml {
type DataConnectYaml (line 252) | interface DataConnectYaml {
type DataConnectConnectorConfig (line 257) | interface DataConnectConnectorConfig {
type PackageJson (line 264) | interface PackageJson {
FILE: src/schematics/setup/index.ts
type SetupConfig (line 21) | interface SetupConfig extends DeployOptions {
FILE: src/schematics/setup/prompts.ts
constant NEW_OPTION (line 11) | const NEW_OPTION = '~~angularfire-new~~';
method extract (line 31) | extract(el) {
method extract (line 57) | extract(el: FirebaseApp) {
type Prompt (line 75) | type Prompt = <K extends string, U= unknown>(questions: { name: K, sourc...
FILE: src/schematics/update/v7/index.ts
constant IMPORT_REGEX (line 7) | const IMPORT_REGEX = /(?<key>import|export)\s+(?:(?<alias>[\w,{}\s*]+)\s...
type ImportRegexMatch (line 8) | interface ImportRegexMatch {
FILE: src/schematics/utils.ts
function getWorkspace (line 30) | function getWorkspace(host: Tree): {
function getFirebaseProjectNameFromHost (line 81) | function getFirebaseProjectNameFromHost(
function getFirebaseProjectNameFromFs (line 93) | function getFirebaseProjectNameFromFs(
function addFixesToServer (line 120) | function addFixesToServer(host: Tree) {
function featureToRules (line 151) | function featureToRules(
function parseDataConnectConfig (line 339) | function parseDataConnectConfig(
function setupTanstackDependencies (line 384) | function setupTanstackDependencies(
FILE: src/storage/storage.module.ts
constant PROVIDED_STORAGE_INSTANCES (line 18) | const PROVIDED_STORAGE_INSTANCES = new InjectionToken<Storage[]>('angula...
function defaultStorageInstanceFactory (line 20) | function defaultStorageInstanceFactory(provided: FirebaseStorage[]|undef...
function storageInstanceFactory (line 25) | function storageInstanceFactory(fn: (injector: Injector) => FirebaseStor...
constant STORAGE_INSTANCES_PROVIDER (line 32) | const STORAGE_INSTANCES_PROVIDER = {
constant DEFAULT_STORAGE_INSTANCE_PROVIDER (line 39) | const DEFAULT_STORAGE_INSTANCE_PROVIDER = {
class StorageModule (line 54) | class StorageModule {
method constructor (line 55) | constructor() {
function provideStorage (line 60) | function provideStorage(fn: (injector: Injector) => FirebaseStorage, ......
FILE: src/storage/storage.ts
type Storage (line 8) | interface Storage extends FirebaseStorage {}
method constructor (line 11) | constructor(auth: FirebaseStorage) {
class Storage (line 10) | class Storage {
method constructor (line 11) | constructor(auth: FirebaseStorage) {
constant STORAGE_PROVIDER_NAME (line 16) | const STORAGE_PROVIDER_NAME = 'storage';
type StorageInstances (line 19) | interface StorageInstances extends Array<FirebaseStorage> {}
method constructor (line 22) | constructor() {
class StorageInstances (line 21) | class StorageInstances {
method constructor (line 22) | constructor() {
FILE: src/test-config.ts
constant COMMON_CONFIG (line 1) | const COMMON_CONFIG = {
constant COMMON_CONFIG_TOO (line 13) | const COMMON_CONFIG_TOO = {
type Window (line 26) | interface Window {
FILE: src/zones.ts
type LogLevel (line 24) | enum LogLevel {
class ɵZoneScheduler (line 38) | class ɵZoneScheduler implements SchedulerLike {
method constructor (line 39) | constructor(private zone: any, private delegate: any = queueScheduler) {
method now (line 42) | now() {
method schedule (line 46) | schedule(work: (this: SchedulerAction<any>, state?: any) => void, dela...
class ɵAngularFireSchedulers (line 70) | class ɵAngularFireSchedulers {
method constructor (line 74) | constructor() {
function warnOutsideInjectionContext (line 89) | function warnOutsideInjectionContext(original: any, logLevel: LogLevel) {
function runOutsideAngular (line 99) | function runOutsideAngular<T>(fn: (...args: any[]) => T): T {
function run (line 105) | function run<T>(fn: (...args: any[]) => T): T {
FILE: tools/build.ts
type LogLevel (line 7) | enum LogLevel {
type OverrideOptions (line 12) | interface OverrideOptions {
function zoneWrapExports (line 64) | function zoneWrapExports() {
function replacePackageCoreVersion (line 264) | async function replacePackageCoreVersion() {
function replaceSchematicVersions (line 276) | async function replaceSchematicVersions() {
function spawnPromise (line 289) | function spawnPromise(command: string, args: string[]) {
function compileSchematics (line 300) | async function compileSchematics() {
function buildLibrary (line 342) | async function buildLibrary() {
Condensed preview — 459 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (968K chars).
[
{
"path": ".editorconfig",
"chars": 244,
"preview": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert"
},
{
"path": ".firebaserc",
"chars": 59,
"preview": "{\n \"projects\": {\n \"default\": \"angularfire2-test\"\n }\n}\n"
},
{
"path": ".gitattributes",
"chars": 200,
"preview": "src/**/firebase.ts linguist-generated=true\nsrc/**/rxfire.ts linguist-generated=true\nsrc/compat/**/base.ts linguist-gener"
},
{
"path": ".github/workflows/codeql-analysis.yml",
"chars": 2350,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/test.yml",
"chars": 7281,
"preview": "name: Test and publish\n\non:\n push:\n branches:\n - main\n paths-ignore:\n - \"**/*.md\"\n pull_request:\n b"
},
{
"path": ".gitignore",
"chars": 335,
"preview": "node_modules/\ndist/\ndist-test/\ndocs/api/\ntypings/\nnpm-debug.log\n.idea/\n.vscode/settings.json\nangular-fire-*.tgz\nangularf"
},
{
"path": ".npmignore",
"chars": 86,
"preview": "*.spec.*\ntest-config.*\npublish.sh\n__ivy_ngcc__/\n*.min.js\n*.min.js.map\n*.__ivy_ngcc_bak"
},
{
"path": ".nvmrc",
"chars": 5,
"preview": "lts/*"
},
{
"path": "CONTRIBUTING.md",
"chars": 7148,
"preview": "# Contributing to AngularFire\n\nWe would love for you to contribute to AngularFire and help make it even better than it i"
},
{
"path": "ISSUE_TEMPLATE.md",
"chars": 2489,
"preview": "<!--\n\nIMPORTANT! YOU MUST FOLLOW THESE INSTRUCTIONS OR YOUR ISSUE WILL BE CLOSED.\n\nThank you for contributing to the Ang"
},
{
"path": "LICENSE",
"chars": 1096,
"preview": "The MIT License\n\nCopyright (c) 2014-2016 Google, Inc. http://angular.io\n\nPermission is hereby granted, free of charge, t"
},
{
"path": "PULL_REQUEST_TEMPLATE.md",
"chars": 1392,
"preview": "<!--\n\nThank you for contributing to the Firebase community! Please fill out the pull request form below\nand make note of"
},
{
"path": "README.md",
"chars": 5628,
"preview": "\n# AngularFire\n\nAngularFire smooths over the rough edges an Angular developer might encounter when implementing the fram"
},
{
"path": "SECURITY.md",
"chars": 436,
"preview": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported |\n| ------- | ------------------ |\n| 6.0+ | "
},
{
"path": "angular.json",
"chars": 972,
"preview": "{\n\t\"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n\t\"version\": 1,\n\t\"newProjectRoot\": \".\",\n\t\"projects\": "
},
{
"path": "docs/analytics.md",
"chars": 1712,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/analytics-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularf"
},
{
"path": "docs/app-check.md",
"chars": 1923,
"preview": "<small>\n<a href=\"https://github.com/angular/angularfire\">AngularFire</a> ❱ <a href=\"../README.md#developer-guide\""
},
{
"path": "docs/auth.md",
"chars": 6228,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/auth-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularfire\">"
},
{
"path": "docs/compat/analytics/getting-started.md",
"chars": 5545,
"preview": "# Getting started with Google Analytics\n\n`AngularFireAnalytics` dynamically imports the `firebase/analytics` library and"
},
{
"path": "docs/compat/auth/getting-started.md",
"chars": 5138,
"preview": "# 5. Getting started with Firebase Authentication\n\n`AngularFireAuth.user` provides you an `Observable<User|null>` to mon"
},
{
"path": "docs/compat/auth/router-guards.md",
"chars": 5282,
"preview": "# Route users with AngularFire guards\n\n`AngularFireAuthGuard` provides a prebuilt [`canActivate` Router Guard](https://a"
},
{
"path": "docs/compat/emulators/emulators.md",
"chars": 6088,
"preview": "# Connect your app and start prototyping\n\nIn this guide, we'll look at how to use `@angular/fire` to connect an Angular "
},
{
"path": "docs/compat/firestore/collections.md",
"chars": 13199,
"preview": "# 3. Collections in AngularFirestore\n\n> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, t"
},
{
"path": "docs/compat/firestore/documents.md",
"chars": 5115,
"preview": "# 2. Documents in AngularFirestore\n\n> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, the"
},
{
"path": "docs/compat/firestore/offline-data.md",
"chars": 2515,
"preview": "# Offline Data in Firestore\n\n> Cloud Firestore supports offline data persistence. This feature caches a copy of the Clou"
},
{
"path": "docs/compat/firestore/querying-collections.md",
"chars": 7320,
"preview": "# 4. Querying Collections in AngularFirestore\n\n> Firestore has [powerful querying syntax](https://firebase.google.com/do"
},
{
"path": "docs/compat/functions/functions.md",
"chars": 5302,
"preview": "# AngularFireFunctions\n\n> The Cloud Functions for Firebase client SDKs let you call functions directly from a Firebase a"
},
{
"path": "docs/compat/messaging/messaging.md",
"chars": 9731,
"preview": "# AngularFireMessaging\n\n> The FCM JavaScript API lets you receive notification messages in web apps running in browsers "
},
{
"path": "docs/compat/performance/getting-started.md",
"chars": 5727,
"preview": "# Getting started with Performance Monitoring\n\n> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#"
},
{
"path": "docs/compat/remote-config/getting-started.md",
"chars": 5658,
"preview": "<h1>Getting started with Remote Config <em><abbr title=\"beta\">β<abbr></em></h1>\n\n`AngularFireRemoteConfig` dynamically i"
},
{
"path": "docs/compat/rtdb/lists.md",
"chars": 10299,
"preview": "# 3. Retrieving data as lists\n\n> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide)"
},
{
"path": "docs/compat/rtdb/objects.md",
"chars": 6046,
"preview": "# 2. Retrieving data as objects\n\n> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guid"
},
{
"path": "docs/compat/rtdb/querying-lists.md",
"chars": 6082,
"preview": "# 4. Querying lists\n\n> **NOTE**: [AngularFire has a new tree-shakable API](../../../README.md#developer-guide), you're l"
},
{
"path": "docs/compat/storage/storage.md",
"chars": 7706,
"preview": "# AngularFireStorage\n\n> Cloud Storage is designed to help you quickly and easily store and serve user-generated content,"
},
{
"path": "docs/compat.md",
"chars": 3523,
"preview": "# AngularFire\nThe official [Angular](https://angular.io/) library for [Firebase](https://firebase.google.com/).\n\n<strong"
},
{
"path": "docs/database.md",
"chars": 7159,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/database-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularfi"
},
{
"path": "docs/deploy/getting-started.md",
"chars": 8081,
"preview": "# Deploy your application on Firebase Hosting & Functions\n\nIn this guide, we'll look at how to use `@angular/fire` to au"
},
{
"path": "docs/firebase.json",
"chars": 232,
"preview": "{\n \"firebase\": \"angular-fire-2\",\n \"public\": \".\",\n \"redirects\": [\n {\n \"source\": \"/\",\n \"destination\": \"/ap"
},
{
"path": "docs/firestore.md",
"chars": 5262,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/firestore-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularf"
},
{
"path": "docs/functions.md",
"chars": 1883,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/functions-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularf"
},
{
"path": "docs/install-and-setup.md",
"chars": 2843,
"preview": "# AngularFire Quickstart\n\n### 1. Create a new project\n\n```bash\n# Using yarn create\nyarn create @angular <project-name>\nc"
},
{
"path": "docs/install-angular-cli-windows10.md",
"chars": 2958,
"preview": "# Installing Angular CLI on Windows 10\n\n> There had been installation issues of `@angular/cli` on Windows 10 system. Mos"
},
{
"path": "docs/install-firebase-tools.md",
"chars": 1870,
"preview": "# Firebase Tools Install and Setup\n\n### 1. Install package\n\n```bash\nnpm install -g firebase-tools\n```\n\nor with `yarn`\n\n`"
},
{
"path": "docs/messaging.md",
"chars": 7531,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/cloud-messaging-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/an"
},
{
"path": "docs/performance.md",
"chars": 1766,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/performance-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angula"
},
{
"path": "docs/remote-config.md",
"chars": 1794,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/remote-config-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angu"
},
{
"path": "docs/storage.md",
"chars": 2669,
"preview": "<img align=\"right\" width=\"30%\" src=\"images/storage-illo_1x.png\">\n\n<small>\n<a href=\"https://github.com/angular/angularfir"
},
{
"path": "docs/universal/cloud-functions.md",
"chars": 3646,
"preview": "# Deploying your Universal application on Cloud Functions for Firebase\n\nAfter [setting up your application with Angular "
},
{
"path": "docs/universal/getting-started.md",
"chars": 979,
"preview": "# Getting started with AngularFire and Universal\n\nServer-side rendering (SSR) is the process of converting a JavaScript "
},
{
"path": "docs/universal/prerendering.md",
"chars": 2573,
"preview": "# Prerendering your Universal application\n\nPrerendering a Universal application allows us to generate the HTML before th"
},
{
"path": "docs/version-4-upgrade.md",
"chars": 3929,
"preview": "# Upgrading to AngularFire2 4.0\n\nAngularFire2 4.0 is a refactor of the AngularFire2 package which implements\n@NgModule, "
},
{
"path": "docs/version-5-upgrade.md",
"chars": 2882,
"preview": "# Upgrading to AngularFire 5.0\n\nAngularFire 5.0 is a refactor of the `AngularFireDatabase` module. It removes the `Fireb"
},
{
"path": "docs/version-6-upgrade.md",
"chars": 1468,
"preview": "# Upgrading to AngularFire 6.0\n\nIntended to be run with Angular 9; version 6 of AngularFire drops support for Angular ve"
},
{
"path": "docs/version-7-upgrade.md",
"chars": 8488,
"preview": "# Upgrading to AngularFire 7.0\n\nIntended to be run with Angular 12, AngularFire 7.0 allows you to take full advantage of"
},
{
"path": "docs/vertexai.md",
"chars": 1620,
"preview": "<small>\n<a href=\"https://github.com/angular/angularfire\">AngularFire</a> ❱ <a href=\"../README.md#developer-guide\""
},
{
"path": "docs/zones.md",
"chars": 3046,
"preview": "<small>\n<a href=\"https://github.com/angular/angularfire\">AngularFire</a> ❱ <a href=\"../README.md#developer-guide\""
},
{
"path": "eslint.config.js",
"chars": 3882,
"preview": "const tsParser = require('@typescript-eslint/parser');\nconst js = require('@eslint/js');\nconst globals = require('global"
},
{
"path": "firebase.json",
"chars": 826,
"preview": "{\n \"database\": {\n \"rules\": \"test/database.rules.json\"\n },\n \"firestore\": {\n \"rules\": \"test/firestore.rules\",\n "
},
{
"path": "karma.conf.js",
"chars": 2757,
"preview": "const dns = require('node:dns');\n\n// The emulator suite fails in CI, only on Node 18.\n// This apparently fixes it.\n// ht"
},
{
"path": "mise.toml",
"chars": 24,
"preview": "[tools]\nnode = \"latest\"\n"
},
{
"path": "package.json",
"chars": 5258,
"preview": "{\n \"name\": \"@angular/fire\",\n \"version\": \"21.0.0-rc.0\",\n \"description\": \"Angular + Firebase = ❤️\",\n \"private\": true,\n"
},
{
"path": "sample/.editorconfig",
"chars": 314,
"preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
},
{
"path": "sample/.firebaserc",
"chars": 59,
"preview": "{\n \"projects\": {\n \"default\": \"angularfire2-test\"\n }\n}\n"
},
{
"path": "sample/.gitignore",
"chars": 641,
"preview": "# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.\n\n# Comp"
},
{
"path": "sample/README.md",
"chars": 1471,
"preview": "# Ng19Test\n\nThis project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.0.0.\n\n## D"
},
{
"path": "sample/angular.json",
"chars": 2722,
"preview": "{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \""
},
{
"path": "sample/database.rules.json",
"chars": 160,
"preview": "{\n /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */\n \"rules\": {\n "
},
{
"path": "sample/firebase.json",
"chars": 781,
"preview": "{\n \"database\": {\n \"rules\": \"database.rules.json\"\n },\n \"firestore\": {\n \"rules\": \"firestore.rules\",\n \"indexes\""
},
{
"path": "sample/firestore.indexes.json",
"chars": 330,
"preview": "{\n \"indexes\": [\n {\n \"collectionGroup\": \"animals\",\n \"queryScope\": \"COLLECTION\",\n \"fields\": [\n {"
},
{
"path": "sample/firestore.rules",
"chars": 331,
"preview": "service cloud.firestore {\n match /databases/{database}/documents {\n match /{document=**} {\n allow read;\n a"
},
{
"path": "sample/functions/.gitignore",
"chars": 190,
"preview": "# Compiled JavaScript files\n**/*.js\n**/*.js.map\n\n# Except the ESLint config file\n!.eslintrc.js\n\n# TypeScript v1 declarat"
},
{
"path": "sample/functions/package.json",
"chars": 546,
"preview": "{\n \"name\": \"functions\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"serve\": \"npm run build && firebase emulators:start --on"
},
{
"path": "sample/functions/src/index.ts",
"chars": 134,
"preview": "import { onCall } from \"firebase-functions/https\";\n\nexport const yada = onCall(() => {\n return { time: new Date().get"
},
{
"path": "sample/functions/tsconfig.json",
"chars": 258,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"commonjs\",\n \"noImplicitReturns\": true,\n \"noUnusedLocals\": true,\n \"outDi"
},
{
"path": "sample/package.json",
"chars": 1571,
"preview": "{\n \"name\": \"ng19-test\",\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"firebase emulators:exec --im"
},
{
"path": "sample/seed/auth_export/accounts.json",
"chars": 61,
"preview": "{\"kind\":\"identitytoolkit#DownloadAccountResponse\",\"users\":[]}"
},
{
"path": "sample/seed/auth_export/config.json",
"chars": 41,
"preview": "{\"signIn\":{\"allowDuplicateEmails\":false}}"
},
{
"path": "sample/seed/database_export/angularfire2-test.json",
"chars": 22,
"preview": "{\"test\":{\"foo\":\"bar\"}}"
},
{
"path": "sample/seed/firebase-export-metadata.json",
"chars": 402,
"preview": "{\n \"version\": \"9.18.0\",\n \"firestore\": {\n \"version\": \"1.13.1\",\n \"path\": \"firestore_export\",\n \"metadata_file\": "
},
{
"path": "sample/seed/storage_export/buckets.json",
"chars": 121,
"preview": "{\n \"buckets\": [\n {\n \"id\": \"default-bucket\"\n },\n {\n \"id\": \"angularfire2-test.appspot.com\"\n }\n ]\n}"
},
{
"path": "sample/seed/storage_export/metadata/angularfire2-test.appspot.com/google-g.png.json",
"chars": 516,
"preview": "{\n \"name\": \"google-g.png\",\n \"bucket\": \"angularfire2-test.appspot.com\",\n \"contentType\": \"image/png\",\n \"metageneration"
},
{
"path": "sample/src/app/app.component.spec.ts",
"chars": 925,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent"
},
{
"path": "sample/src/app/app.component.ts",
"chars": 1624,
"preview": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\nimport { AuthComponent } from"
},
{
"path": "sample/src/app/app.config.client.ts",
"chars": 913,
"preview": "import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';\nimport { initializeApp, provideFirebaseApp } "
},
{
"path": "sample/src/app/app.config.server.ts",
"chars": 1016,
"preview": "import { mergeApplicationConfig, ApplicationConfig, inject, REQUEST_CONTEXT } from '@angular/core';\nimport { initializeS"
},
{
"path": "sample/src/app/app.config.ts",
"chars": 980,
"preview": "import { ApplicationConfig, inject, provideExperimentalZonelessChangeDetection } from '@angular/core';\nimport { connectA"
},
{
"path": "sample/src/app/app.routes.server.ts",
"chars": 163,
"preview": "import { RenderMode, ServerRoute } from '@angular/ssr';\n\nexport const serverRoutes: ServerRoute[] = [\n {\n path: '**'"
},
{
"path": "sample/src/app/app.routes.ts",
"chars": 77,
"preview": "import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"
},
{
"path": "sample/src/app/auth/auth.component.ts",
"chars": 3913,
"preview": "import { Component, inject, makeStateKey, OnDestroy, PLATFORM_ID, TransferState } from '@angular/core';\nimport { Auth, s"
},
{
"path": "sample/src/app/database/database.component.ts",
"chars": 1478,
"preview": "import { Component, inject, makeStateKey, PLATFORM_ID, TransferState } from '@angular/core';\nimport { startWith, tap } f"
},
{
"path": "sample/src/app/firestore/firestore.component.ts",
"chars": 1629,
"preview": "import { Component, inject, makeStateKey, PLATFORM_ID, signal, TransferState } from '@angular/core';\nimport { traceUntil"
},
{
"path": "sample/src/app/functions/functions.component.ts",
"chars": 1294,
"preview": "import { JsonPipe } from '@angular/common';\nimport { afterNextRender, Component, inject, signal } from '@angular/core';\n"
},
{
"path": "sample/src/app/messaging/messaging.component.ts",
"chars": 896,
"preview": "import { AsyncPipe, JsonPipe, SlicePipe } from '@angular/common';\nimport { Component, inject, signal } from '@angular/co"
},
{
"path": "sample/src/app/remote-config/remote-config.component.ts",
"chars": 836,
"preview": "import { Component, inject, PLATFORM_ID } from '@angular/core';\nimport { getAllChanges, getRemoteConfig } from '@angular"
},
{
"path": "sample/src/app/storage/storage.component.ts",
"chars": 1590,
"preview": "import { Component, inject, makeStateKey, PLATFORM_ID, TransferState } from '@angular/core';\nimport { from, startWith, t"
},
{
"path": "sample/src/app/upboats/upboats.component.ts",
"chars": 3873,
"preview": "import { Component, inject, makeStateKey, OnInit, PLATFORM_ID, TransferState } from '@angular/core';\nimport { Observable"
},
{
"path": "sample/src/environments/environment.ts",
"chars": 784,
"preview": "export const environment = {\n firebase: {\n apiKey: \"AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA\",\n authDoma"
},
{
"path": "sample/src/index.html",
"chars": 294,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Ng19Test</title>\n <base href=\"/\">\n <meta nam"
},
{
"path": "sample/src/main.server.ts",
"chars": 264,
"preview": "import { bootstrapApplication } from '@angular/platform-browser';\nimport { AppComponent } from './app/app.component';\nim"
},
{
"path": "sample/src/main.ts",
"chars": 251,
"preview": "import { bootstrapApplication } from '@angular/platform-browser';\nimport { config } from './app/app.config.client';\nimpo"
},
{
"path": "sample/src/server.ts",
"chars": 1126,
"preview": "import {\n AngularNodeAppEngine,\n createNodeRequestHandler,\n isMainModule,\n writeResponseToNodeResponse,\n} from '@ang"
},
{
"path": "sample/src/styles.css",
"chars": 80,
"preview": "/* You can add global styles to this file, and also import other style files */\n"
},
{
"path": "sample/storage.rules",
"chars": 171,
"preview": "rules_version = '2';\nservice firebase.storage {\n match /b/{bucket}/o {\n match /{allPaths=**} {\n allow read;\n "
},
{
"path": "sample/tsconfig.app.json",
"chars": 489,
"preview": "/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. *"
},
{
"path": "sample/tsconfig.json",
"chars": 915,
"preview": "/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. *"
},
{
"path": "sample/tsconfig.spec.json",
"chars": 434,
"preview": "/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. *"
},
{
"path": "site/.eleventy.js",
"chars": 2890,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/.firebaserc",
"chars": 51,
"preview": "{\n \"projects\": {\n \"default\": \"afdocsite\"\n }\n}\n"
},
{
"path": "site/.gitignore",
"chars": 18,
"preview": "_site\npublic\n_tmp\n"
},
{
"path": "site/firebase.json",
"chars": 1620,
"preview": "{\n \"hosting\": {\n \"public\": \"public\",\n \"cleanUrls\": true,\n \"redirects\": [\n {\n \"source\": \"/get-start"
},
{
"path": "site/package.json",
"chars": 1259,
"preview": "{\n \"name\": \"angularfire-guide\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"private\": true,\n \"scripts\": {\n \"start"
},
{
"path": "site/postcss.config.js",
"chars": 701,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/scripts/build.js",
"chars": 981,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/_data/nextprev.json",
"chars": 2417,
"preview": "{\n \"Get started\": { \n \"key\": \"Get Started\", \n \"url\": \"/get-started\", \n \"children\": [\n { \"key\": \"Quick sta"
},
{
"path": "site/src/_includes/default.njk",
"chars": 2068,
"preview": "{% import \"side-nav.njk\" as nav %}\n\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>\n {% block title %}Angular"
},
{
"path": "site/src/_includes/guide.njk",
"chars": 208,
"preview": "{% extends \"default.njk\" %}\n{% import \"next-prev.njk\" as nextprev with context %}\n\n{% block content %}\n\n <h1>{{ title }"
},
{
"path": "site/src/_includes/next-prev.njk",
"chars": 1911,
"preview": "\n{% macro item(direction, title, url) %}\n {% set justifyDirection = 'justify-center lg:justify-start xl:justify-start' "
},
{
"path": "site/src/_includes/side-nav.njk",
"chars": 988,
"preview": "{# \nType of sectionEntry\n[{\n \"key\": \"Mammals\",\n \"url\": \"/mammals/\",\n \"title\": \"Mammals\",\n \"children\": [{\n "
},
{
"path": "site/src/analytics/analytics.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/analytics/getting-started.md",
"chars": 5213,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Analytics\n---\n\n## Google Analytics\n\n`Ang"
},
{
"path": "site/src/analytics/index.md",
"chars": 57,
"preview": "---\neleventyNavigation:\n key: Analytics\n order: 5\n---\n\n"
},
{
"path": "site/src/auth/auth.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/auth/getting-started.md",
"chars": 1586,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Auth\n---\n\n## Using AngularFireAuth\n\n`Ang"
},
{
"path": "site/src/auth/index.md",
"chars": 51,
"preview": "---\neleventyNavigation:\n key: Auth\n order: 3\n---\n"
},
{
"path": "site/src/auth/route-guards.md",
"chars": 5037,
"preview": "---\ntitle: Route guards\neleventyNavigation:\n key: Route guards\n parent: Auth\n---\n\n## Route users with AngularFire guar"
},
{
"path": "site/src/firestore/collections.md",
"chars": 12935,
"preview": "---\ntitle: Collections\neleventyNavigation:\n key: Collections\n parent: Firestore\n---\n\n## Documents in AngularFirestore\n"
},
{
"path": "site/src/firestore/documents.md",
"chars": 4852,
"preview": "---\ntitle: Documents\neleventyNavigation:\n key: Documents\n parent: Firestore\n---\n\n## Documents in AngularFirestore\n\nClo"
},
{
"path": "site/src/firestore/firestore.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/firestore/index.md",
"chars": 55,
"preview": "---\neleventyNavigation:\n key: Firestore\n order: 2\n---"
},
{
"path": "site/src/functions/functions.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/functions/getting-started.md",
"chars": 5083,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Functions\n---\n\n## Using AngularFireFunct"
},
{
"path": "site/src/functions/index.md",
"chars": 56,
"preview": "---\neleventyNavigation:\n key: Functions\n order: 7\n---\n"
},
{
"path": "site/src/get-started/deploying.md",
"chars": 6371,
"preview": "---\ntitle: Deploying\neleventyNavigation:\n key: Deploying\n parent: Get started\n---\n\n## Static or Server-side rendered\n\n"
},
{
"path": "site/src/get-started/get-started.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/get-started/index.md",
"chars": 58,
"preview": "---\neleventyNavigation:\n key: Get started\n order: 1\n---\n"
},
{
"path": "site/src/get-started/local-development.md",
"chars": 5302,
"preview": "---\ntitle: Local development\neleventyNavigation:\n key: Local development\n parent: Get started\n---\n\n## Connect to the F"
},
{
"path": "site/src/get-started/quick-start.md",
"chars": 6689,
"preview": "---\ntitle: Quick start\neleventyNavigation:\n key: Quick start\n parent: Get started\n---\n\n## Create a new project\n\n```bas"
},
{
"path": "site/src/index.md",
"chars": 1557,
"preview": "---\nlayout: default.njk\n---\n\n{% headingone %}AngularFire{% endheadingone %}\n\n{% subheading %}The official library for An"
},
{
"path": "site/src/ionic/authentication.md",
"chars": 2991,
"preview": "---\ntitle: Authentication\neleventyNavigation:\n key: Authentication\n parent: Ionic\n---\n\n## Setting up Ionic and Firebas"
},
{
"path": "site/src/ionic/getting-started.md",
"chars": 4848,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Ionic\n---\n\n## Setup with Ionic CLI\n\nBefo"
},
{
"path": "site/src/ionic/index.md",
"chars": 54,
"preview": "---\neleventyNavigation:\n key: Ionic\n order: 12\n---\n\n"
},
{
"path": "site/src/ionic/ionic.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/js/click-card.js",
"chars": 517,
"preview": "customElements.define('eap-click-card', class extends HTMLElement {\n connectedCallback() {\n let down;\n let up;\n "
},
{
"path": "site/src/js/menu-button.js",
"chars": 642,
"preview": "customElements.define('eap-menu-button', class extends HTMLElement {\n connectedCallback() {\n const menuId = this.get"
},
{
"path": "site/src/js/tab-switcher.js",
"chars": 1196,
"preview": "customElements.define('eap-tab-switcher', class extends HTMLElement {});\ncustomElements.define('eap-tab-list', class ext"
},
{
"path": "site/src/messaging/getting-started.md",
"chars": 9549,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Messaging\n---\n\n## Using AngularFireMessa"
},
{
"path": "site/src/messaging/index.md",
"chars": 57,
"preview": "---\neleventyNavigation:\n key: Messaging\n order: 8\n---\n\n"
},
{
"path": "site/src/messaging/messaging.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/performance/getting-started.md",
"chars": 5623,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Performance\n---\n\n## Automatic page load "
},
{
"path": "site/src/performance/index.md",
"chars": 59,
"preview": "---\neleventyNavigation:\n key: Performance\n order: 10\n---\n"
},
{
"path": "site/src/performance/performance.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/remote-config/getting-started.md",
"chars": 5310,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Remote Config\n---\n\n## Getting started wi"
},
{
"path": "site/src/remote-config/index.md",
"chars": 60,
"preview": "---\neleventyNavigation:\n key: Remote Config\n order: 9\n---\n"
},
{
"path": "site/src/remote-config/remote-config.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/rtdb/index.md",
"chars": 51,
"preview": "---\neleventyNavigation:\n key: RTDB\n order: 4\n---\n"
},
{
"path": "site/src/rtdb/lists.md",
"chars": 10046,
"preview": "---\ntitle: Lists\neleventyNavigation:\n key: Lists\n parent: RTDB\n---\n\n## Retrieving data as lists\n\nAngularFire synchroni"
},
{
"path": "site/src/rtdb/objects.md",
"chars": 5693,
"preview": "---\ntitle: Objects\neleventyNavigation:\n key: Objects\n parent: RTDB\n---\n\n## Retrieving data as objects\n\nThe `AngularFir"
},
{
"path": "site/src/rtdb/querying.md",
"chars": 6205,
"preview": "---\ntitle: Querying\neleventyNavigation:\n key: Querying\n parent: RTDB\n---\n\n## Querying lists\n\nLists of data in the Real"
},
{
"path": "site/src/rtdb/rtdb.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/shortcodes/buttons/index.js",
"chars": 1373,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/disclaimerprod/index.js",
"chars": 1332,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/filters/index.js",
"chars": 2857,
"preview": "const console = require('console');\nconst { resolve } = require('path');\n\nconst findByName = {\n name: \"findByName\",\n t"
},
{
"path": "site/src/shortcodes/headings/index.js",
"chars": 1099,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/includecode/fetch.js",
"chars": 1186,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/includecode/from-local.js",
"chars": 599,
"preview": "const { readFile } = require('fs');\nconst { resolve } = require('path');\nconst { promisify } = require('util');\nconst re"
},
{
"path": "site/src/shortcodes/includecode/index.js",
"chars": 3848,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/includecode/snippets.js",
"chars": 2159,
"preview": "// Modified from: https://github.com/firebase/snippets-web/blob/master/scripts/separate-snippets.ts\n\n// Regex for [START"
},
{
"path": "site/src/shortcodes/includecode/transform.js",
"chars": 2123,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/index.js",
"chars": 1281,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/shortcodes/version/index.js",
"chars": 794,
"preview": "/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/storage/getting-started.md",
"chars": 7461,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Storage\n---\n\n\n## Using AngularFireStorag"
},
{
"path": "site/src/storage/index.md",
"chars": 55,
"preview": "---\neleventyNavigation:\n key: Storage\n order: 6\n---\n\n"
},
{
"path": "site/src/storage/storage.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "site/src/styles/prism.css",
"chars": 3626,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/styles/tailwind.config.js",
"chars": 1443,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/styles/tailwind.css",
"chars": 7042,
"preview": "/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "site/src/universal/cloud-functions.md",
"chars": 2756,
"preview": "---\ntitle: Cloud Functions\neleventyNavigation:\n key: Cloud Functions\n parent: Universal\n---\n\n## Deploying on Universal"
},
{
"path": "site/src/universal/getting-started.md",
"chars": 4444,
"preview": "---\ntitle: Getting started\neleventyNavigation:\n key: Getting started\n parent: Universal\n---\n\n## Getting started with A"
},
{
"path": "site/src/universal/index.md",
"chars": 57,
"preview": "---\neleventyNavigation:\n key: Universal\n order: 11\n---\n"
},
{
"path": "site/src/universal/prerendering.md",
"chars": 2640,
"preview": "---\ntitle: Prerendering\neleventyNavigation:\n key: Prerendering\n parent: Universal\n---\n\n## Prerendering Universal sites"
},
{
"path": "site/src/universal/universal.11tydata.json",
"chars": 48,
"preview": "{\n \"layout\": \"guide.njk\",\n \"tags\": \"guides\"\n}\n"
},
{
"path": "src/ai/ai.module.ts",
"chars": 2109,
"preview": "import {\n EnvironmentProviders,\n InjectionToken,\n Injector,\n NgModule,\n NgZone,\n Optional,\n makeEnvironmentProvid"
},
{
"path": "src/ai/ai.spec.ts",
"chars": 1064,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { AI, getAI, provideAI } from '@angular/fire/ai';\nimport { Fireb"
},
{
"path": "src/ai/ai.ts",
"chars": 747,
"preview": "import { ɵgetAllInstancesOf } from '@angular/fire';\nimport { AI as FirebaseAI } from 'firebase/ai';\nimport { from, timer"
},
{
"path": "src/ai/firebase.ts",
"chars": 715,
"preview": "// DO NOT MODIFY, this file is autogenerated by tools/build.ts\nexport * from 'firebase/ai';\nimport { ɵzoneWrap } from '@"
},
{
"path": "src/ai/ng-package.json",
"chars": 121,
"preview": "{\n \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n \"lib\": {\n \"entryFile\": \"public_api.ts\"\n }\n}"
},
{
"path": "src/ai/package.json",
"chars": 69,
"preview": "{\n \"$schema\": \"../../node_modules/ng-packagr/package.schema.json\"\n}\n"
},
{
"path": "src/ai/public_api.ts",
"chars": 132,
"preview": "export { AI, AIInstances, AIInstance$ } from './ai';\nexport { provideAI, AIModule } from './ai.module';\nexport * from '."
},
{
"path": "src/analytics/analytics.module.ts",
"chars": 2803,
"preview": "import { isPlatformBrowser } from '@angular/common';\nimport {\n EnvironmentProviders,\n InjectionToken,\n Injector,\n Ng"
},
{
"path": "src/analytics/analytics.spec.ts",
"chars": 1205,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { Analytics, getAnalytics, provideAnalytics } from '@angular/fir"
},
{
"path": "src/analytics/analytics.ts",
"chars": 879,
"preview": "import { ɵgetAllInstancesOf } from '@angular/fire';\nimport { Analytics as FirebaseAnalytics } from 'firebase/analytics';"
},
{
"path": "src/analytics/firebase.ts",
"chars": 1503,
"preview": "// DO NOT MODIFY, this file is autogenerated by tools/build.ts\nexport * from 'firebase/analytics';\nimport { ɵzoneWrap } "
},
{
"path": "src/analytics/ng-package.json",
"chars": 121,
"preview": "{\n \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n \"lib\": {\n \"entryFile\": \"public_api.ts\"\n }\n}"
},
{
"path": "src/analytics/package.json",
"chars": 68,
"preview": "{\n \"$schema\": \"../../node_modules/ng-packagr/package.schema.json\"\n}"
},
{
"path": "src/analytics/public_api.ts",
"chars": 264,
"preview": "export { Analytics, AnalyticsInstances, analyticInstance$ } from './analytics';\nexport { provideAnalytics, AnalyticsModu"
},
{
"path": "src/analytics/screen-tracking.service.ts",
"chars": 7061,
"preview": "import { ComponentFactoryResolver, Injectable, Injector, NgZone, OnDestroy, Optional } from '@angular/core';\nimport { VE"
},
{
"path": "src/analytics/user-tracking.service.ts",
"chars": 1556,
"preview": "import { Injectable, Injector, NgZone, OnDestroy } from '@angular/core';\nimport { VERSION } from '@angular/fire';\nimport"
},
{
"path": "src/app/app.module.ts",
"chars": 3256,
"preview": "import {\n EnvironmentProviders,\n Inject,\n InjectionToken,\n Injector,\n VERSION as NG_VERSION,\n NgModule,\n NgZone,\n"
},
{
"path": "src/app/app.spec.ts",
"chars": 873,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { FirebaseApp, initializeApp, provideFirebaseApp } from '@angula"
},
{
"path": "src/app/app.ts",
"chars": 1456,
"preview": "import { FirebaseApp as IFirebaseApp, getApps } from 'firebase/app';\nimport { from, timer } from 'rxjs';\nimport { concat"
}
]
// ... and 259 more files (download for full content)
About this extraction
This page contains the full source code of the angular/angularfire GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 459 files (887.3 KB), approximately 225.2k tokens, and a symbol index with 674 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.