├── .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.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 ├── database.md ├── deploy │ └── getting-started.md ├── firebase.json ├── firestore.md ├── functions.md ├── images │ ├── analytics-illo_1x.png │ ├── auth-illo_1x.png │ ├── cloud-messaging-illo_1x.png │ ├── database-illo_1x.png │ ├── firestore-illo_1x.png │ ├── functions-illo_1x.png │ ├── hosting-illo_1x.png │ ├── performance-illo_1x.png │ ├── reCAPTCHA-logo@1x.png │ ├── remote-config-illo_1x.png │ └── storage-illo_1x.png ├── 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 ├── package-lock.json ├── package.json ├── sample ├── .editorconfig ├── .firebaserc ├── .gitignore ├── README.md ├── angular.json ├── database.rules.json ├── firebase.json ├── firestore.indexes.json ├── firestore.rules ├── functions │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── package-lock.json ├── package.json ├── public │ └── favicon.ico ├── 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 │ │ ├── blobs │ │ └── angularfire2-test.appspot.com │ │ │ └── google-g.png │ │ ├── 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 │ ├── assets │ ├── GoogleSans-Bold.woff2 │ ├── GoogleSans-Medium.woff2 │ ├── GoogleSans-Regular.woff2 │ ├── Roboto-900.woff2 │ ├── Roboto-Italic.woff2 │ ├── Roboto-Regular.woff2 │ ├── RobotoMono-Regular.woff2 │ ├── corner.svg │ └── firebase-logo.svg │ ├── auth │ ├── auth.11tydata.json │ ├── getting-started.md │ ├── index.md │ └── route-guards.md │ ├── favicon.ico │ ├── 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-check │ ├── app-check.module.ts │ ├── app-check.spec.ts │ ├── app-check.ts │ ├── firebase.ts │ ├── ng-package.json │ ├── package.json │ └── public_api.ts ├── app │ ├── app.module.ts │ ├── app.spec.ts │ ├── app.ts │ ├── firebase.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 ├── auth │ ├── auth.module.ts │ ├── auth.spec.ts │ ├── auth.ts │ ├── firebase.ts │ ├── ng-package.json │ ├── package.json │ ├── public_api.ts │ └── rxfire.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-guard │ │ ├── auth-guard.module.ts │ │ ├── auth-guard.spec.ts │ │ ├── auth-guard.ts │ │ ├── ng-package.json │ │ ├── package.json │ │ └── public_api.ts │ ├── auth │ │ ├── auth.module.ts │ │ ├── auth.spec.ts │ │ ├── auth.ts │ │ ├── base.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-group │ │ │ ├── collection-group.spec.ts │ │ │ └── collection-group.ts │ │ ├── collection │ │ │ ├── changes.ts │ │ │ ├── collection.spec.ts │ │ │ └── collection.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 ├── vertexai │ ├── firebase.ts │ ├── ng-package.json │ ├── package.json │ ├── public_api.ts │ ├── vertexai.module.ts │ ├── vertexai.spec.ts │ └── vertexai.ts └── zones.ts ├── test ├── database.rules.json ├── firestore.indexes.json ├── firestore.rules ├── functions │ ├── .gitignore │ ├── package-lock.json │ ├── 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 /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "angularfire2-test" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/**/firebase.ts linguist-generated=true 2 | src/**/rxfire.ts linguist-generated=true 3 | src/compat/**/base.ts linguist-generated=true 4 | samples/**/* linguist-generated=true 5 | yarn.lock linguist-generated=true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | dist-test/ 4 | docs/api/ 5 | typings/ 6 | npm-debug.log 7 | .idea/ 8 | .vscode/settings.json 9 | angular-fire-*.tgz 10 | angularfire2-*.tgz 11 | *.ngfactory.ts 12 | *.ngsummary.json 13 | .DS_Store 14 | yarn-error.log 15 | *.bak 16 | yarn.lock 17 | test/ng-build/**/yarn.lock 18 | tools/build.js 19 | coverage 20 | *.log 21 | api-*.json 22 | angularfire.tgz 23 | unpack.sh 24 | publish.sh 25 | .firebase 26 | .angular 27 | .vscode -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.spec.* 2 | test-config.* 3 | publish.sh 4 | __ivy_ngcc__/ 5 | *.min.js 6 | *.min.js.map 7 | *.__ivy_ngcc_bak -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. http://angular.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 22 | 23 | ### Checklist 24 | 25 | - Issue number for this PR: #nnn (required) 26 | - Docs included?: (yes/no; required for all API/functional changes) 27 | - Test units included?: (yes/no; required) 28 | - In a clean directory, `yarn install`, `yarn test` run successfully? (yes/no; required) 29 | 30 | ### Description 31 | 32 | 34 | 35 | ### Code sample 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 6.0+ | :white_check_mark: | 8 | | < 6.0 | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | 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. 13 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": ".", 5 | "projects": { 6 | "angularfire": { 7 | "projectType": "library", 8 | "root": "src", 9 | "sourceRoot": "src", 10 | "prefix": "angularfire", 11 | "architect": { 12 | "build": { 13 | "builder": "@angular-devkit/build-angular:ng-packagr", 14 | "options": { 15 | "tsConfig": "tsconfig.json", 16 | "project": "src/ng-package.json" 17 | } 18 | }, 19 | "test": { 20 | "builder": "@angular-devkit/build-angular:karma", 21 | "options": { 22 | "polyfills": [ 23 | "zone.js", 24 | "zone.js/testing" 25 | ], 26 | "tsConfig": "tsconfig.spec.json", 27 | "karmaConfig": "karma.conf.js" 28 | } 29 | }, 30 | "lint": { 31 | "builder": "@angular-eslint/builder:lint", 32 | "options": { 33 | "lintFilePatterns": [ 34 | "src/**/*.ts", 35 | "src/**/*.html" 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | }, 42 | "cli": { 43 | "packageManager": "npm", 44 | "analytics": "86795b8f-9036-4a53-929c-a7303453d677" 45 | } 46 | } -------------------------------------------------------------------------------- /docs/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "firebase": "angular-fire-2", 3 | "public": ".", 4 | "redirects": [ 5 | { 6 | "source": "/", 7 | "destination": "/api", 8 | "type": 302 9 | } 10 | ], 11 | "ignore": [ 12 | "firebase.json", 13 | "**/.*", 14 | "**/node_modules/**" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /docs/images/analytics-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/analytics-illo_1x.png -------------------------------------------------------------------------------- /docs/images/auth-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/auth-illo_1x.png -------------------------------------------------------------------------------- /docs/images/cloud-messaging-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/cloud-messaging-illo_1x.png -------------------------------------------------------------------------------- /docs/images/database-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/database-illo_1x.png -------------------------------------------------------------------------------- /docs/images/firestore-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/firestore-illo_1x.png -------------------------------------------------------------------------------- /docs/images/functions-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/functions-illo_1x.png -------------------------------------------------------------------------------- /docs/images/hosting-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/hosting-illo_1x.png -------------------------------------------------------------------------------- /docs/images/performance-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/performance-illo_1x.png -------------------------------------------------------------------------------- /docs/images/reCAPTCHA-logo@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/reCAPTCHA-logo@1x.png -------------------------------------------------------------------------------- /docs/images/remote-config-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/remote-config-illo_1x.png -------------------------------------------------------------------------------- /docs/images/storage-illo_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/docs/images/storage-illo_1x.png -------------------------------------------------------------------------------- /docs/universal/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started with AngularFire and Universal 2 | 3 | Server-side rendering (SSR) is the process of converting a JavaScript app to plain HTML at request-time, allowing search engine crawlers and linkbots to understand page content reliably. 4 | 5 | ## 0. Prerequisites 6 | 7 | - @angular/cli >= v6.0 8 | - @angular/fire >= v5.0.0 9 | 10 | ## 1. Add Angular Universal to your project 11 | 12 | Follow the steps from the [Angular Universal Tutorial](https://angular.io/guide/universal) to add Universal to your 13 | project. 14 | 15 | ``` 16 | ng add @nguniversal/express-engine 17 | ``` 18 | 19 | This will create all the files you need and setup all the configurations for Universal rendering for your application. 20 | 21 | ## 2. Next Steps 22 | 23 | Test your app locally by running `npm run dev:ssr`. 24 | 25 | _Note: `dev:ssr` is a command that was added to your `package.json` by the `ng add` command that will run the dev server 26 | for your Angular with Universal._ 27 | 28 | ### [Next Step: Deploying your Universal application on Cloud Functions for Firebase](cloud-functions.md) 29 | -------------------------------------------------------------------------------- /docs/version-6-upgrade.md: -------------------------------------------------------------------------------- 1 | # Upgrading to AngularFire 6.0 2 | 3 | Intended to be run with Angular 9; version 6 of AngularFire drops support for Angular version 8 and below, older versions of typescript, Firebase, drops `firebase-node`, `database-deprecated`, and more. 4 | 5 | ## Breaking changes: 6 | 7 | * Support for Angular versions less than 9 has been dropped 8 | * Support for Firebase JS SDK versions less than 7.13.1 has been dropped 9 | * Support for `firebase-tools` less than 8.0 has been dropped 10 | * The `angularfire2` NPM library will no longer be updated 11 | * Dropped `@angular/fire/firebase-node` and `@angular/fire/database-depreciated` 12 | * We make use of Proxy in more modules, you'll need to polyfill if you want to support IE 11 13 | * We've standardized our DI Token naming conventions across all modules 14 | * `AngularFireAuth` has dropped the `auth` property and instead Promise Proxies the underlying Firebase `auth.Auth` instance; allowing your development experience to more closely mirror the JS SDK. Similar changes have been made to `AngularFireFunctions`, `AngularFireMessaging`, and `AngularFirePerformance`. 15 | * `AngularFireAuthGuard` and `canActivate` have dropped support for raw pipes, this was never working correctly in AOT 16 | * `AngularFirePerformance` has been simplified, the RXJS pipes are now exported as pure-functions outside the class. Automatic tracking of `isStable` timing has now been moved into `PerformanceMonitoringService` and we've dropped the `AUTOMATICALLY_TRACE_CORE_NG_METRICS` DI token. -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "rules": "test/database.rules.json" 4 | }, 5 | "firestore": { 6 | "rules": "test/firestore.rules", 7 | "indexes": "test/firestore.indexes.json" 8 | }, 9 | "storage": { 10 | "rules": "test/storage.rules" 11 | }, 12 | "emulators": { 13 | "auth": { 14 | "port": 9098 15 | }, 16 | "functions": { 17 | "port": 5001 18 | }, 19 | "firestore": { 20 | "port": 8089 21 | }, 22 | "database": { 23 | "port": 9002 24 | }, 25 | "storage": { 26 | "port": 9199 27 | }, 28 | "ui": { 29 | "enabled": false 30 | } 31 | }, 32 | "functions": [ 33 | { 34 | "source": "test/functions", 35 | "codebase": "default", 36 | "ignore": [ 37 | "node_modules", 38 | ".git", 39 | "firebase-debug.log", 40 | "firebase-debug.*.log", 41 | "*.local" 42 | ], 43 | "predeploy": [ 44 | "npm --prefix \"$RESOURCE_DIR\" run build" 45 | ] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /sample/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | ij_typescript_use_double_quotes = false 14 | 15 | [*.md] 16 | max_line_length = off 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /sample/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "angularfire2-test" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | 44 | # Firebase 45 | .firebase 46 | *-debug.log 47 | .runtimeconfig.json 48 | -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # Ng19Test 2 | 3 | This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.0.0. 4 | 5 | ## Development server 6 | 7 | To start a local development server, run: 8 | 9 | ```bash 10 | ng serve 11 | ``` 12 | 13 | Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files. 14 | 15 | ## Code scaffolding 16 | 17 | Angular CLI includes powerful code scaffolding tools. To generate a new component, run: 18 | 19 | ```bash 20 | ng generate component component-name 21 | ``` 22 | 23 | For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run: 24 | 25 | ```bash 26 | ng generate --help 27 | ``` 28 | 29 | ## Building 30 | 31 | To build the project run: 32 | 33 | ```bash 34 | ng build 35 | ``` 36 | 37 | This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed. 38 | 39 | ## Running unit tests 40 | 41 | To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command: 42 | 43 | ```bash 44 | ng test 45 | ``` 46 | 47 | ## Running end-to-end tests 48 | 49 | For end-to-end (e2e) testing, run: 50 | 51 | ```bash 52 | ng e2e 53 | ``` 54 | 55 | Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs. 56 | 57 | ## Additional Resources 58 | 59 | For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. 60 | -------------------------------------------------------------------------------- /sample/database.rules.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */ 3 | "rules": { 4 | ".read": true, 5 | ".write": false 6 | } 7 | } -------------------------------------------------------------------------------- /sample/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "rules": "database.rules.json" 4 | }, 5 | "firestore": { 6 | "rules": "firestore.rules", 7 | "indexes": "firestore.indexes.json" 8 | }, 9 | "storage": { 10 | "rules": "storage.rules" 11 | }, 12 | "functions": [ 13 | { 14 | "source": "functions", 15 | "codebase": "default", 16 | "ignore": [ 17 | "node_modules", 18 | ".git", 19 | "firebase-debug.log", 20 | "firebase-debug.*.log" 21 | ], 22 | "predeploy": [ 23 | "npm --prefix \"$RESOURCE_DIR\" run build" 24 | ] 25 | } 26 | ], 27 | "emulators": { 28 | "auth": { 29 | "port": 9099 30 | }, 31 | "functions": { 32 | "port": 5001 33 | }, 34 | "firestore": { 35 | "port": 8080 36 | }, 37 | "database": { 38 | "port": 9000 39 | }, 40 | "storage": { 41 | "port": 9199 42 | }, 43 | "ui": { 44 | "enabled": true 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sample/firestore.indexes.json: -------------------------------------------------------------------------------- 1 | { 2 | "indexes": [ 3 | { 4 | "collectionGroup": "animals", 5 | "queryScope": "COLLECTION", 6 | "fields": [ 7 | { 8 | "fieldPath": "upboats", 9 | "order": "DESCENDING" 10 | }, 11 | { 12 | "fieldPath": "updatedAt", 13 | "order": "DESCENDING" 14 | } 15 | ] 16 | } 17 | ], 18 | "fieldOverrides": [] 19 | } 20 | -------------------------------------------------------------------------------- /sample/firestore.rules: -------------------------------------------------------------------------------- 1 | service cloud.firestore { 2 | match /databases/{database}/documents { 3 | match /{document=**} { 4 | allow read; 5 | allow write: if false; 6 | } 7 | match /animals/{document=**} { 8 | allow read; 9 | allow write: if request.auth != null; 10 | } 11 | match /dreams/{document=**} { 12 | allow read; 13 | allow write; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /sample/functions/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled JavaScript files 2 | **/*.js 3 | **/*.js.map 4 | 5 | # Except the ESLint config file 6 | !.eslintrc.js 7 | 8 | # TypeScript v1 declaration files 9 | typings/ 10 | 11 | # Node.js dependency directory 12 | node_modules/ 13 | lib/ 14 | -------------------------------------------------------------------------------- /sample/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "scripts": { 4 | "build": "tsc", 5 | "serve": "npm run build && firebase emulators:start --only functions", 6 | "shell": "npm run build && firebase functions:shell", 7 | "start": "npm run shell", 8 | "deploy": "firebase deploy --only functions", 9 | "logs": "firebase functions:log" 10 | }, 11 | "engines": { 12 | "node": "20" 13 | }, 14 | "main": "lib/index.js", 15 | "dependencies": { 16 | "firebase-admin": "^13.0.1", 17 | "firebase-functions": "^6.1.2" 18 | }, 19 | "devDependencies": { 20 | "typescript": "^5.7.2" 21 | }, 22 | "private": true 23 | } 24 | -------------------------------------------------------------------------------- /sample/functions/src/index.ts: -------------------------------------------------------------------------------- 1 | import { onCall } from "firebase-functions/https"; 2 | 3 | export const yada = onCall(() => { 4 | return { time: new Date().getTime() }; 5 | }); 6 | -------------------------------------------------------------------------------- /sample/functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitReturns": true, 5 | "noUnusedLocals": true, 6 | "outDir": "lib", 7 | "sourceMap": true, 8 | "strict": true, 9 | "target": "es2020" 10 | }, 11 | "compileOnSave": true, 12 | "include": [ 13 | "src" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng19-test", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "firebase emulators:exec --import seed \"ng serve\"", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test", 10 | "serve:ssr:ng19-test": "node dist/ng19-test/server/server.mjs" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^19.0.0", 15 | "@angular/common": "^19.0.0", 16 | "@angular/compiler": "^19.0.0", 17 | "@angular/core": "^19.0.0", 18 | "@angular/fire": "file:../angular-fire-19.0.0.tgz", 19 | "@angular/forms": "^19.0.0", 20 | "@angular/platform-browser": "^19.0.0", 21 | "@angular/platform-browser-dynamic": "^19.0.0", 22 | "@angular/platform-server": "^19.0.0", 23 | "@angular/router": "^19.0.0", 24 | "@angular/ssr": "^19.0.0", 25 | "cookie-parser": "^1.4.7", 26 | "cookie-store": "^4.0.0-next.4", 27 | "express": "^4.18.2", 28 | "firebase-admin": "^13.0.1", 29 | "js-cookie": "^3.0.5", 30 | "rxjs": "~7.8.0", 31 | "tslib": "^2.3.0", 32 | "zone.js": "~0.15.0" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "^19.0.0", 36 | "@angular/cli": "^19.0.0", 37 | "@angular/compiler-cli": "^19.0.0", 38 | "@types/cookie-parser": "^1.4.8", 39 | "@types/express": "^4.17.17", 40 | "@types/jasmine": "~5.1.0", 41 | "@types/js-cookie": "^3.0.6", 42 | "@types/node": "^18.18.0", 43 | "jasmine-core": "~5.4.0", 44 | "karma": "~6.4.0", 45 | "karma-chrome-launcher": "~3.2.0", 46 | "karma-coverage": "~2.2.0", 47 | "karma-jasmine": "~5.1.0", 48 | "karma-jasmine-html-reporter": "~2.1.0", 49 | "typescript": "~5.6.2" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sample/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/sample/public/favicon.ico -------------------------------------------------------------------------------- /sample/seed/auth_export/accounts.json: -------------------------------------------------------------------------------- 1 | {"kind":"identitytoolkit#DownloadAccountResponse","users":[]} -------------------------------------------------------------------------------- /sample/seed/auth_export/config.json: -------------------------------------------------------------------------------- 1 | {"signIn":{"allowDuplicateEmails":false}} -------------------------------------------------------------------------------- /sample/seed/database_export/angularfire2-test.json: -------------------------------------------------------------------------------- 1 | {"test":{"foo":"bar"}} -------------------------------------------------------------------------------- /sample/seed/firebase-export-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "9.18.0", 3 | "firestore": { 4 | "version": "1.13.1", 5 | "path": "firestore_export", 6 | "metadata_file": "firestore_export/firestore_export.overall_export_metadata" 7 | }, 8 | "database": { 9 | "version": "4.7.2", 10 | "path": "database_export" 11 | }, 12 | "auth": { 13 | "version": "9.18.0", 14 | "path": "auth_export" 15 | }, 16 | "storage": { 17 | "version": "9.18.0", 18 | "path": "storage_export" 19 | } 20 | } -------------------------------------------------------------------------------- /sample/seed/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/sample/seed/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata -------------------------------------------------------------------------------- /sample/seed/firestore_export/all_namespaces/all_kinds/output-0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/sample/seed/firestore_export/all_namespaces/all_kinds/output-0 -------------------------------------------------------------------------------- /sample/seed/firestore_export/firestore_export.overall_export_metadata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/sample/seed/firestore_export/firestore_export.overall_export_metadata -------------------------------------------------------------------------------- /sample/seed/storage_export/blobs/angularfire2-test.appspot.com/google-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/sample/seed/storage_export/blobs/angularfire2-test.appspot.com/google-g.png -------------------------------------------------------------------------------- /sample/seed/storage_export/buckets.json: -------------------------------------------------------------------------------- 1 | { 2 | "buckets": [ 3 | { 4 | "id": "default-bucket" 5 | }, 6 | { 7 | "id": "angularfire2-test.appspot.com" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /sample/seed/storage_export/metadata/angularfire2-test.appspot.com/google-g.png.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-g.png", 3 | "bucket": "angularfire2-test.appspot.com", 4 | "contentType": "image/png", 5 | "metageneration": 1, 6 | "generation": 1631220526565, 7 | "storageClass": "STANDARD", 8 | "etag": "someETag", 9 | "contentDisposition": "inline", 10 | "contentEncoding": "identity", 11 | "downloadTokens": [ 12 | "7553ce27-5bd0-409d-843b-25ff4d792740" 13 | ], 14 | "timeCreated": "2021-09-09T20:48:46.564Z", 15 | "updated": "2021-09-09T20:48:46.567Z", 16 | "size": 9916, 17 | "md5Hash": "3NH+6XyxOMx2hUhq9d4hxQ==", 18 | "crc32c": "2188947963" 19 | } 20 | -------------------------------------------------------------------------------- /sample/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | imports: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have the 'ng19-test' title`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('ng19-test'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain('Hello, ng19-test'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /sample/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { RouterOutlet } from '@angular/router'; 3 | import { AuthComponent } from './auth/auth.component'; 4 | import { DatabaseComponent } from './database/database.component'; 5 | import { FirestoreComponent } from './firestore/firestore.component'; 6 | import { FunctionsComponent } from './functions/functions.component'; 7 | import { MessagingComponent } from './messaging/messaging.component'; 8 | import { RemoteConfigComponent } from './remote-config/remote-config.component'; 9 | import { StorageComponent } from './storage/storage.component'; 10 | import { UpboatsComponent } from './upboats/upboats.component'; 11 | 12 | @Component({ 13 | selector: 'app-root', 14 | imports: [ 15 | RouterOutlet, 16 | AuthComponent, 17 | DatabaseComponent, 18 | FirestoreComponent, 19 | FunctionsComponent, 20 | MessagingComponent, 21 | RemoteConfigComponent, 22 | StorageComponent, 23 | UpboatsComponent 24 | ], 25 | template: ` 26 | Hello World! 27 | 28 | @defer (hydrate on idle) { } @placeholder { Database! … } 29 | @defer (hydrate on idle) { } @placeholder { Firestore! … } 30 | @defer (hydrate on idle) { } @placeholder { Functions! … } 31 | @defer (hydrate on idle) { } @placeholder { Messaging! … } 32 | @defer (hydrate on idle) { } @placeholder { Remote Config! … } 33 | @defer (hydrate never) { } @placeholder { Storage! … } 34 | @defer (hydrate on idle) { } @placeholder { … } 35 | 36 | `, 37 | }) 38 | export class AppComponent { 39 | title = 'ng19-test'; 40 | } 41 | -------------------------------------------------------------------------------- /sample/src/app/app.config.client.ts: -------------------------------------------------------------------------------- 1 | import { mergeApplicationConfig, ApplicationConfig } from '@angular/core'; 2 | import { initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { getAnalytics, provideAnalytics, ScreenTrackingService, UserTrackingService } from '@angular/fire/analytics'; 4 | import { getMessaging, provideMessaging } from '@angular/fire/messaging'; 5 | import { getPerformance, providePerformance } from '@angular/fire/performance'; 6 | 7 | import { appConfig } from './app.config'; 8 | 9 | import { environment } from '../environments/environment'; 10 | 11 | const clientConfig: ApplicationConfig = { 12 | providers: [ 13 | provideFirebaseApp(() => initializeApp(environment.firebase)), 14 | provideAnalytics(() => getAnalytics()), 15 | ScreenTrackingService, 16 | UserTrackingService, 17 | provideMessaging(() => getMessaging()), 18 | providePerformance(() => getPerformance()), 19 | ] 20 | }; 21 | 22 | export const config = mergeApplicationConfig(appConfig, clientConfig); 23 | -------------------------------------------------------------------------------- /sample/src/app/app.config.server.ts: -------------------------------------------------------------------------------- 1 | import { mergeApplicationConfig, ApplicationConfig, inject, REQUEST_CONTEXT } from '@angular/core'; 2 | import { initializeServerApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { provideServerRendering } from '@angular/platform-server'; 4 | import { provideServerRoutesConfig } from '@angular/ssr'; 5 | 6 | import { appConfig } from './app.config'; 7 | import { serverRoutes } from './app.routes.server'; 8 | import { environment } from '../environments/environment'; 9 | 10 | const serverConfig: ApplicationConfig = { 11 | providers: [ 12 | provideServerRendering(), 13 | provideServerRoutesConfig(serverRoutes), 14 | provideFirebaseApp(() => { 15 | // TODO migrate to REQUEST once that's working 16 | const requestContext = inject(REQUEST_CONTEXT, { optional: true }) as { 17 | authIdToken: string, 18 | } | undefined; 19 | const authIdToken = requestContext?.authIdToken; 20 | return initializeServerApp(environment.firebase, { authIdToken }); 21 | }), 22 | ] 23 | }; 24 | 25 | export const config = mergeApplicationConfig(appConfig, serverConfig); 26 | -------------------------------------------------------------------------------- /sample/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, inject, provideExperimentalZonelessChangeDetection } from '@angular/core'; 2 | import { connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth'; 3 | import { provideClientHydration, withIncrementalHydration } from '@angular/platform-browser'; 4 | import { provideRouter } from '@angular/router'; 5 | 6 | import { routes } from './app.routes'; 7 | import { FirebaseApp } from '@angular/fire/app'; 8 | import { environment } from '../environments/environment'; 9 | 10 | export const appConfig: ApplicationConfig = { 11 | providers: [ 12 | provideExperimentalZonelessChangeDetection(), 13 | provideRouter(routes), 14 | provideClientHydration(withIncrementalHydration()), 15 | provideAuth(() => { 16 | const auth = getAuth(inject(FirebaseApp)); 17 | if ((auth as any)._canInitEmulator && environment.emulatorPorts?.auth) { 18 | connectAuthEmulator(auth, `http://localhost:${environment.emulatorPorts.auth}`, { disableWarnings: true }); 19 | } 20 | return auth; 21 | }), 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /sample/src/app/app.routes.server.ts: -------------------------------------------------------------------------------- 1 | import { RenderMode, ServerRoute } from '@angular/ssr'; 2 | 3 | export const serverRoutes: ServerRoute[] = [ 4 | { 5 | path: '**', 6 | renderMode: RenderMode.Server 7 | } 8 | ]; 9 | -------------------------------------------------------------------------------- /sample/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | export const routes: Routes = []; 4 | -------------------------------------------------------------------------------- /sample/src/app/database/database.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject, makeStateKey, PLATFORM_ID, TransferState } from '@angular/core'; 2 | import { startWith, tap } from 'rxjs'; 3 | import { connectDatabaseEmulator, getDatabase, objectVal, ref } from '@angular/fire/database'; 4 | import { AsyncPipe, isPlatformServer, JsonPipe } from '@angular/common'; 5 | import { FirebaseApp } from '@angular/fire/app'; 6 | import { environment } from '../../environments/environment'; 7 | 8 | @Component({ 9 | selector: 'app-database', 10 | template: ` 11 |

12 | Database! 13 | {{ testObjectValue$ | async | json }} 14 |

15 | `, 16 | imports: [AsyncPipe, JsonPipe] 17 | }) 18 | export class DatabaseComponent { 19 | 20 | private readonly database; 21 | 22 | private readonly transferState = inject(TransferState); 23 | private readonly transferStateKey = makeStateKey("database:test"); 24 | protected readonly testObjectValue$; 25 | 26 | constructor() { 27 | this.database = getDatabase(inject(FirebaseApp)); 28 | if (!(this.database as any)._instanceStarted && environment.emulatorPorts?.database) { 29 | connectDatabaseEmulator(this.database, "localhost", environment.emulatorPorts.database); 30 | } 31 | 32 | this.testObjectValue$ = objectVal(ref(this.database, "test")).pipe( 33 | isPlatformServer(inject(PLATFORM_ID)) ? 34 | tap(it => this.transferState.set(this.transferStateKey, it)) : 35 | this.transferState.hasKey(this.transferStateKey) ? 36 | startWith(this.transferState.get(this.transferStateKey, undefined)) : 37 | tap() 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sample/src/app/firestore/firestore.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject, makeStateKey, PLATFORM_ID, signal, TransferState } from '@angular/core'; 2 | import { traceUntilFirst } from '@angular/fire/performance'; 3 | import { doc, docData, getFirestore, connectFirestoreEmulator } from '@angular/fire/firestore'; 4 | import { startWith, tap } from 'rxjs'; 5 | import { AsyncPipe, isPlatformServer, JsonPipe } from '@angular/common'; 6 | import { FirebaseApp } from '@angular/fire/app'; 7 | import { environment } from '../../environments/environment'; 8 | 9 | @Component({ 10 | selector: 'app-firestore', 11 | template: `

12 | Firestore! 13 | {{ testDocValue | async | json }} 14 |

`, 15 | imports: [ AsyncPipe, JsonPipe ] 16 | }) 17 | export class FirestoreComponent { 18 | 19 | private readonly firestore; 20 | 21 | private readonly transferState = inject(TransferState); 22 | private readonly transferStateKey = makeStateKey("firestore:test/1"); 23 | public readonly testDocValue; 24 | 25 | protected readonly className = signal("is-deferred"); 26 | 27 | constructor() { 28 | this.firestore = getFirestore(inject(FirebaseApp)); 29 | if (!(this.firestore as any)._settingsFrozen && environment.emulatorPorts?.firestore) { 30 | connectFirestoreEmulator(this.firestore, "localhost", environment.emulatorPorts.firestore); 31 | } 32 | 33 | this.testDocValue = docData(doc(this.firestore, 'test/1')).pipe( 34 | traceUntilFirst('firestore'), 35 | isPlatformServer(inject(PLATFORM_ID)) ? 36 | tap(it => this.transferState.set(this.transferStateKey, it)) : 37 | this.transferState.hasKey(this.transferStateKey) ? 38 | startWith(this.transferState.get(this.transferStateKey, undefined)) : 39 | tap() 40 | ); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sample/src/app/functions/functions.component.ts: -------------------------------------------------------------------------------- 1 | import { JsonPipe } from '@angular/common'; 2 | import { afterNextRender, Component, inject, signal } from '@angular/core'; 3 | import { FirebaseApp } from '@angular/fire/app'; 4 | import { connectFunctionsEmulator, getFunctions, httpsCallableData } from '@angular/fire/functions'; 5 | import { environment } from '../../environments/environment'; 6 | 7 | @Component({ 8 | selector: 'app-functions', 9 | template: ` 10 |

11 | Functions! 12 | {{ response() | json }} 13 | 14 |

15 | `, 16 | imports: [JsonPipe] 17 | }) 18 | export class FunctionsComponent { 19 | 20 | private readonly functions = getFunctions(inject(FirebaseApp)); 21 | 22 | protected readonly response = signal(undefined); 23 | private readonly yadaFunction = httpsCallableData(this.functions, 'yada', { timeout: 3_000 }); 24 | 25 | async request() { 26 | this.yadaFunction({}).subscribe({ 27 | next: (next) => this.response.set(next), 28 | error: (error) => this.response.set(error), 29 | }); 30 | } 31 | 32 | protected readonly className = signal("is-deferred"); 33 | 34 | constructor() { 35 | if (environment.emulatorPorts?.functions) { 36 | connectFunctionsEmulator(this.functions, "localhost", environment.emulatorPorts.functions); 37 | } 38 | 39 | afterNextRender(() => { 40 | if (this.className) this.className.set(""); 41 | }); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sample/src/app/messaging/messaging.component.ts: -------------------------------------------------------------------------------- 1 | import { AsyncPipe, JsonPipe, SlicePipe } from '@angular/common'; 2 | import { Component, inject, signal } from '@angular/core'; 3 | import { Messaging } from '@angular/fire/messaging'; 4 | import { EMPTY } from 'rxjs'; 5 | 6 | @Component({ 7 | selector: 'app-messaging', 8 | template: ` 9 |

10 | Messaging! 11 | {{ token$ | async | slice:0:12 }} @if (token$ | async) { … } 12 |  {{ message$ | async | json }} 13 | @if (showRequest()) { 14 | 15 | } 16 |

17 | `, 18 | imports: [AsyncPipe, SlicePipe, JsonPipe] 19 | }) 20 | export class MessagingComponent { 21 | 22 | private readonly messaging = inject(Messaging, { optional: true }); 23 | protected readonly token$ = EMPTY; 24 | protected readonly message$ = EMPTY; 25 | 26 | protected readonly showRequest = signal(false); 27 | 28 | async request() { 29 | await Notification.requestPermission(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /sample/src/app/remote-config/remote-config.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject, PLATFORM_ID } from '@angular/core'; 2 | import { getAllChanges, getRemoteConfig } from '@angular/fire/remote-config'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { EMPTY } from 'rxjs'; 5 | import { AsyncPipe, isPlatformServer, JsonPipe } from '@angular/common'; 6 | import { FirebaseApp } from '@angular/fire/app'; 7 | 8 | @Component({ 9 | selector: 'app-remote-config', 10 | template: `

Remote Config! {{ config$ | async | json }}

`, 11 | imports: [AsyncPipe, JsonPipe], 12 | }) 13 | export class RemoteConfigComponent { 14 | 15 | private readonly remoteConfig = isPlatformServer(inject(PLATFORM_ID)) ? undefined : getRemoteConfig(inject(FirebaseApp)); 16 | protected readonly config$ = this.remoteConfig ? 17 | getAllChanges(this.remoteConfig).pipe( 18 | traceUntilFirst('remote-config'), 19 | ) : 20 | EMPTY; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sample/src/app/storage/storage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject, makeStateKey, PLATFORM_ID, TransferState } from '@angular/core'; 2 | import { from, startWith, tap } from 'rxjs'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { connectStorageEmulator, getDownloadURL, getStorage, ref } from '@angular/fire/storage'; 5 | import { AsyncPipe, isPlatformServer } from '@angular/common'; 6 | import { FirebaseApp } from '@angular/fire/app'; 7 | import { environment } from '../../environments/environment'; 8 | 9 | const TRANSPARENT_PNG 10 | = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; 11 | 12 | @Component({ 13 | selector: 'app-storage', 14 | template: ` 15 |

16 | Storage! 17 | 18 |

19 | `, 20 | imports: [AsyncPipe] 21 | }) 22 | export class StorageComponent { 23 | 24 | private readonly storage = getStorage(inject(FirebaseApp)); 25 | 26 | private readonly transferState = inject(TransferState); 27 | private readonly transferStateKey = makeStateKey("storage:google-g.png"); 28 | 29 | private readonly icon = ref(this.storage, 'google-g.png'); 30 | 31 | protected readonly downloadUrl$ = from(getDownloadURL(this.icon)).pipe( 32 | traceUntilFirst('storage'), 33 | isPlatformServer(inject(PLATFORM_ID)) ? 34 | tap(it => this.transferState.set(this.transferStateKey, it)) : 35 | startWith(this.transferState.get(this.transferStateKey, TRANSPARENT_PNG)) 36 | ); 37 | 38 | constructor() { 39 | if (environment.emulatorPorts?.storage) { 40 | connectStorageEmulator(this.storage, "localhost", environment.emulatorPorts.storage); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sample/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | firebase: { 3 | apiKey: "AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA", 4 | authDomain: "angularfire2-test.firebaseapp.com", 5 | databaseURL: "https://angularfire2-test.firebaseio.com", 6 | projectId: "angularfire2-test", 7 | storageBucket: "angularfire2-test.appspot.com", 8 | messagingSenderId: "920323787688", 9 | appId: "1:920323787688:web:2253a0e5eb5b9a8b", 10 | measurementId: "G-W20QDV5CZP" 11 | }, 12 | emulatorPorts: { 13 | auth: 9099, 14 | functions: 5001, 15 | firestore: 8080, 16 | database: 9000, 17 | storage: 9199, 18 | }, 19 | vapidKey: 'BObYLml9CWDGcaj2xQTv6MwjS-R5mRyTlCbfTpflWy3iGHEMTyIhhd0FN6VIFszPoVzwEL_gm7o9ISxpotwKHfE', 20 | recaptcha3SiteKey: '6LchwAoqAAAAAMfT_hY2nwI1WXJcBE20DGA_k-A3', 21 | }; 22 | -------------------------------------------------------------------------------- /sample/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ng19Test 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /sample/src/main.server.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { AppComponent } from './app/app.component'; 3 | import { config } from './app/app.config.server'; 4 | 5 | const bootstrap = () => bootstrapApplication(AppComponent, config); 6 | 7 | export default bootstrap; 8 | -------------------------------------------------------------------------------- /sample/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { config } from './app/app.config.client'; 3 | import { AppComponent } from './app/app.component'; 4 | 5 | bootstrapApplication(AppComponent, config) 6 | .catch((err) => console.error(err)); 7 | -------------------------------------------------------------------------------- /sample/src/server.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AngularNodeAppEngine, 3 | createNodeRequestHandler, 4 | isMainModule, 5 | writeResponseToNodeResponse, 6 | } from '@angular/ssr/node'; 7 | import express from 'express'; 8 | import { dirname, resolve } from 'node:path'; 9 | import { fileURLToPath } from 'node:url'; 10 | import cookieParser from "cookie-parser"; 11 | 12 | const serverDistFolder = dirname(fileURLToPath(import.meta.url)); 13 | const browserDistFolder = resolve(serverDistFolder, '../browser'); 14 | 15 | const app = express(); 16 | const angularApp = new AngularNodeAppEngine(); 17 | 18 | app.use( 19 | express.static(browserDistFolder, { 20 | maxAge: '1y', 21 | index: false, 22 | redirect: false, 23 | }), 24 | ); 25 | 26 | app.use(cookieParser()); 27 | 28 | app.use('/**', (req, res, next) => { 29 | angularApp 30 | .handle(req, { authIdToken: req.cookies?.__session }) 31 | .then((response) => 32 | response ? writeResponseToNodeResponse(response, res) : next(), 33 | ) 34 | .catch(next); 35 | }); 36 | 37 | if (isMainModule(import.meta.url)) { 38 | const port = process.env['PORT'] || 4000; 39 | app.listen(port, () => { 40 | console.log(`Node Express server listening on http://localhost:${port}`); 41 | }); 42 | } 43 | 44 | export const reqHandler = createNodeRequestHandler(app); 45 | -------------------------------------------------------------------------------- /sample/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /sample/storage.rules: -------------------------------------------------------------------------------- 1 | rules_version = '2'; 2 | service firebase.storage { 3 | match /b/{bucket}/o { 4 | match /{allPaths=**} { 5 | allow read; 6 | allow write: if request.auth!=null; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /sample/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/app", 7 | "types": [ 8 | "node" 9 | ] 10 | }, 11 | "files": [ 12 | "src/main.ts", 13 | "src/main.server.ts", 14 | "src/server.ts" 15 | ], 16 | "include": [ 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /sample/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "compileOnSave": false, 5 | "compilerOptions": { 6 | "outDir": "./dist/out-tsc", 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "skipLibCheck": true, 13 | "isolatedModules": true, 14 | "esModuleInterop": true, 15 | "experimentalDecorators": true, 16 | "moduleResolution": "bundler", 17 | "importHelpers": true, 18 | "target": "ES2022", 19 | "module": "ES2022" 20 | }, 21 | "angularCompilerOptions": { 22 | "enableI18nLegacyMessageIdFormat": false, 23 | "strictInjectionParameters": true, 24 | "strictInputAccessModifiers": true, 25 | "strictTemplates": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sample/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/spec", 7 | "types": [ 8 | "jasmine" 9 | ] 10 | }, 11 | "include": [ 12 | "src/**/*.spec.ts", 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /site/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "afdocsite" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /site/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | public 3 | _tmp 4 | -------------------------------------------------------------------------------- /site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularfire-guide", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "scripts": { 7 | "start": "eleventy --serve & postcss ./src/styles/tailwind.css --o _tmp/style.css --watch", 8 | "quiet": "eleventy --quiet --serve & postcss ./src/styles/tailwind.css --o _tmp/style.css --watch", 9 | "just_a_comment_explaining_below": "The build scripts are read by scripts/build.js and executed in their number order (_0_, _1_, etc...), hence the weird naming system.", 10 | "build:_0_clean": "rm -rf _site", 11 | "build:_1_css": "NODE_ENV=production postcss ./src/styles/tailwind.css --o _site/style.css", 12 | "build:_2_eleventy": "ELEVENTY_PRODUCTION=true eleventy", 13 | "build": "node scripts/build.js" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "@11ty/eleventy": "^0.11.1", 20 | "@11ty/eleventy-navigation": "^0.1.6", 21 | "firebase-tools": "^9.3.0", 22 | "markdown-it": "^12.0.4", 23 | "markdown-it-attrs": "^3.0.3", 24 | "markdown-it-container": "^3.0.0", 25 | "markdown-it-prism": "^2.1.3", 26 | "markdown-it-replace-link": "^1.1.0", 27 | "nunjucks": "^3.2.2", 28 | "postcss-cli": "^8.3.1", 29 | "postcss-import": "^14.0.0", 30 | "shelljs": "^0.8.4", 31 | "tailwindcss": "^2.0.2" 32 | }, 33 | "dependencies": {} 34 | } 35 | -------------------------------------------------------------------------------- /site/postcss.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module.exports = { 18 | plugins: [ 19 | require(`tailwindcss`)(`./src/styles/tailwind.config.js`), 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /site/scripts/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const { exec, echo } = require('shelljs'); 18 | const pkg = require('../package.json'); 19 | 20 | function runExec(command) { 21 | if (exec(command).code !== 0) { 22 | echo(`${command} failed`); 23 | } 24 | } 25 | 26 | const buildScripts = Object.keys(pkg.scripts) 27 | .filter(k => k.startsWith('build:')); 28 | 29 | for(let script of buildScripts) { 30 | console.log(`Running npm run ${script}`); 31 | runExec(`npm run ${script}`); 32 | } 33 | -------------------------------------------------------------------------------- /site/src/_includes/guide.njk: -------------------------------------------------------------------------------- 1 | {% extends "default.njk" %} 2 | {% import "next-prev.njk" as nextprev with context %} 3 | 4 | {% block content %} 5 | 6 |

{{ title }}

7 | 8 | {{ content | safe }} 9 | {{ nextprev.contextgrid("guides") }} 10 | 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /site/src/_includes/side-nav.njk: -------------------------------------------------------------------------------- 1 | {# 2 | Type of sectionEntry 3 | [{ 4 | "key": "Mammals", 5 | "url": "/mammals/", 6 | "title": "Mammals", 7 | "children": [{ 8 | "key": "Humans", 9 | "parentKey": "Mammals", 10 | "url": "/humans/", 11 | "title": "Humans" 12 | }, 13 | { 14 | "key": "Dogs", 15 | "parentKey": "Mammals", 16 | "url": "/dogs/", 17 | "title": "Dogs" 18 | }] 19 | }] 20 | #} 21 | 22 | {% macro navsection(sectionEntry, page) %} 23 | 45 | {% endmacro %} 46 | -------------------------------------------------------------------------------- /site/src/analytics/analytics.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/analytics/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Analytics 4 | order: 5 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /site/src/assets/GoogleSans-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/GoogleSans-Bold.woff2 -------------------------------------------------------------------------------- /site/src/assets/GoogleSans-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/GoogleSans-Medium.woff2 -------------------------------------------------------------------------------- /site/src/assets/GoogleSans-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/GoogleSans-Regular.woff2 -------------------------------------------------------------------------------- /site/src/assets/Roboto-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/Roboto-900.woff2 -------------------------------------------------------------------------------- /site/src/assets/Roboto-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/Roboto-Italic.woff2 -------------------------------------------------------------------------------- /site/src/assets/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /site/src/assets/RobotoMono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/assets/RobotoMono-Regular.woff2 -------------------------------------------------------------------------------- /site/src/assets/corner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/src/auth/auth.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/auth/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting started 3 | eleventyNavigation: 4 | key: Getting started 5 | parent: Auth 6 | --- 7 | 8 | ## Using AngularFireAuth 9 | 10 | `AngularFireAuth.user` provides you an `Observable` to monitor your application's authentication State. 11 | 12 | `AngularFireAuth` promise proxies an initialized 13 | `firebase.auth.Auth` instance, allowing you to log users in, out, etc. [See 14 | the Firebase docs for more information on what methods are available.](https://firebase.google.com/docs/reference/js/firebase.auth.Auth) 15 | 16 | **Example app:** 17 | 18 | ```ts 19 | import { Component } from '@angular/core'; 20 | import { AngularFireAuth } from '@angular/fire/auth'; 21 | import firebase from 'firebase/app'; 22 | 23 | @Component({ 24 | selector: 'app-root', 25 | template: `{%raw%} 26 |
27 |

Hello {{ user.displayName }}!

28 | 29 |
30 | 31 |

Please login.

32 | 33 |
34 | {%endraw%}`, 35 | }) 36 | export class AppComponent { 37 | constructor(public auth: AngularFireAuth) { 38 | } 39 | login() { 40 | this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()); 41 | } 42 | logout() { 43 | this.auth.signOut(); 44 | } 45 | } 46 | ``` 47 | 48 | ## UI Libraries 49 | 50 | - Material Design : [ngx-auth-firebaseui](https://github.com/AnthonyNahas/ngx-auth-firebaseui) 51 | - Bootstrap : [@firebaseui/ng-bootstrap](https://github.com/firebaseui/ng-bootstrap) 52 | 53 | ## Cordova 54 | 55 | Learn how to [setup Firebase Authentication with Cordova](https://firebase.google.com/docs/auth/web/cordova) in the Firebase Guides. 56 | -------------------------------------------------------------------------------- /site/src/auth/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Auth 4 | order: 3 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular/angularfire/c1c6af9779154caff6bc0d9b837f6c3e2d913456/site/src/favicon.ico -------------------------------------------------------------------------------- /site/src/firestore/firestore.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/firestore/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Firestore 4 | order: 2 5 | --- -------------------------------------------------------------------------------- /site/src/functions/functions.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/functions/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Functions 4 | order: 7 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/get-started/get-started.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/get-started/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Get started 4 | order: 1 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default.njk 3 | --- 4 | 5 | {% headingone %}AngularFire{% endheadingone %} 6 | 7 | {% subheading %}The official library for Angular and Firebase{% endsubheading %} 8 | 9 |
10 |
11 | {%- linkbutton "/get-started/quick-start" %} 12 | Get started 13 | {%- endlinkbutton %} 14 |
15 |
16 | {%- linkbutton "https://github.com/angular/fire", "secondary", true %} 17 | GitHub 18 | {%- endlinkbutton %} 19 |
20 |
21 | 22 | {% disclaimerprod %} 23 | 24 | ## What is AngularFire? 25 | 26 | AngularFire smooths over the rough edges an Angular developer might encounter when implementing the framework-agnostic Firebase JS SDK & aims to provide a more natural developer experience by conforming to Angular conventions. 27 | 28 | ### Dependency injection 29 | Provide and Inject Firebase services in your components 30 | 31 | ### Zone.js wrappers 32 | Stable zones allow proper functionality of service workers, forms, SSR, and pre-rendering 33 | 34 | ### Observable based 35 | Utilize RxJS rather than callbacks for realtime streams 36 | 37 | ### NgRx friendly API 38 | Integrate with NgRx using AngularFire's action based APIs. 39 | 40 | ### Lazy-loading 41 | AngularFire dynamically imports much of Firebase, reducing time to load your app 42 | 43 | ### Deploy schematics 44 | Get your Angular application deployed on Firebase Hosting with a single command 45 | 46 | ### Google Analytics 47 | Zero-effort Angular Router awareness in Google Analytics 48 | 49 | ### Router Guards 50 | Guard your Angular routes with built-in Firebase Authentication checks 51 | -------------------------------------------------------------------------------- /site/src/ionic/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Ionic 4 | order: 12 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /site/src/ionic/ionic.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/js/click-card.js: -------------------------------------------------------------------------------- 1 | customElements.define('eap-click-card', class extends HTMLElement { 2 | connectedCallback() { 3 | let down; 4 | let up; 5 | // Enhance to a pointer only if the JavaScript applies 6 | this.style.cursor = 'pointer'; 7 | // Note: This only works for a single link or the first one. 8 | const firstOrOnlyLink = this.querySelector('a'); 9 | this.onmousedown = () => down = +new Date(); 10 | this.onmouseup = () => { 11 | up = +new Date(); 12 | if ((up - down) < 200) { 13 | firstOrOnlyLink.click(); 14 | } 15 | } 16 | } 17 | }); -------------------------------------------------------------------------------- /site/src/js/menu-button.js: -------------------------------------------------------------------------------- 1 | customElements.define('eap-menu-button', class extends HTMLElement { 2 | connectedCallback() { 3 | const menuId = this.getAttribute('data-menu-id'); 4 | const menuEl = document.getElementById(menuId); 5 | const button = document.createElement('button'); 6 | button.classList.add('fixed', 'w-16', 'h-16', 'text-white', 'rounded-full', 'shadow-lg', 'bottom-6', 'right-6', 'bg-grey-700', 'focus:ring-grey-600' , 'z-50', 'focus:ring-4', 'md:hidden', 'lg:hidden', 'xl:hidden'); 7 | button.textContent = '🔥'; 8 | this.appendChild(button); 9 | button.addEventListener('click', clickEvent => { 10 | menuEl.classList.toggle('slideIn'); 11 | }); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /site/src/js/tab-switcher.js: -------------------------------------------------------------------------------- 1 | customElements.define('eap-tab-switcher', class extends HTMLElement {}); 2 | customElements.define('eap-tab-list', class extends HTMLElement { 3 | connectedCallback() { 4 | this.buttonTabs = this.querySelectorAll('button'); 5 | for(let button of this.buttonTabs) { 6 | button.addEventListener('click', clickEvent => { 7 | const activeButton = this.querySelector('button[aria-selected="true"]'); 8 | const activePanelId = activeButton.dataset.panel; 9 | const panelToDisplayId = button.dataset.panel; 10 | const panelToDisplay = document.querySelector(`#${panelToDisplayId}`); 11 | const activePanel = document.querySelector(`#${activePanelId}`); 12 | if(activeButton.id !== button.id) { 13 | button.setAttribute('aria-selected', true); 14 | activeButton.setAttribute('aria-selected', false); 15 | panelToDisplay.classList.add('block'); 16 | panelToDisplay.classList.remove('hidden'); 17 | activePanel.classList.remove('block'); 18 | activePanel.classList.add('hidden'); 19 | } 20 | }); 21 | } 22 | } 23 | }); 24 | customElements.define('eap-tab-panel-list', class extends HTMLElement {}); 25 | customElements.define('eap-tab-panel', class extends HTMLElement { }); -------------------------------------------------------------------------------- /site/src/messaging/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Messaging 4 | order: 8 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /site/src/messaging/messaging.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/performance/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Performance 4 | order: 10 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/performance/performance.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/remote-config/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Remote Config 4 | order: 9 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/remote-config/remote-config.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/rtdb/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: RTDB 4 | order: 4 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/rtdb/rtdb.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/shortcodes/buttons/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const linkButton = { 18 | name: "linkbutton", 19 | type: "addPairedShortcode", 20 | create (content, href, type='primary', external=false) { 21 | const primaryClass = `link-button inline-block shadow-lg bg-blue text-white text-lg uppercase font-bold font-display tracking-wide rounded-lg px-8 py-3 text-center`; 22 | const secondaryClass = `link-button inline-block shadow-lg bg-blue-200 text-black text-lg uppercase font-bold font-display tracking-wide rounded-lg px-8 py-3 text-center`; 23 | const cssClass = type === 'primary' ? primaryClass : secondaryClass; 24 | const externalAttrs = external ? 'rel="noopener" target="blank"' : ''; 25 | return `${content}`; 26 | } 27 | } 28 | 29 | module.exports = { 30 | shortcodes: [ 31 | linkButton, 32 | ] 33 | }; 34 | -------------------------------------------------------------------------------- /site/src/shortcodes/disclaimerprod/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Usage: {% disclaimerprod %} 18 | const disclaimerprod = { 19 | name: "disclaimerprod", 20 | type: "addShortcode", 21 | create() { 22 | return `
23 |

Beta Site!

24 |

This is a brand new guide site that is in beta. During this time period we'd love to hear your feedback on our GitHub Discussion board. Please let us know what you think of the usability, content, and any ideas for improvement. All contributors are welcome!

25 |
`; 26 | } 27 | } 28 | 29 | module.exports = { 30 | shortcodes: [ 31 | disclaimerprod 32 | ] 33 | }; 34 | -------------------------------------------------------------------------------- /site/src/shortcodes/headings/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Usage: {% headingone %} My title! {% endheadingone %} 18 | const headingOne = { 19 | name: "headingone", 20 | type: "addPairedShortcode", 21 | create (content) { 22 | return `

${ content }

` 23 | } 24 | }; 25 | 26 | const subHeading = { 27 | name: "subheading", 28 | type: "addPairedShortcode", 29 | create (content) { 30 | return `
${content}
`; 31 | } 32 | }; 33 | 34 | module.exports = { 35 | shortcodes: [ 36 | headingOne, 37 | subHeading, 38 | ] 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /site/src/shortcodes/includecode/fetch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const fetch = require("node-fetch"); 18 | 19 | function convertToGitHubApiUrl(githubPath) { 20 | const urlPieces = githubPath.split('/'); 21 | const [user, repo] = urlPieces.slice(0, 2); 22 | // TODO(davideast): Don't hardcode main branch 23 | const githubApiUrl = [user, repo, 'master', ...urlPieces.slice(2, urlPieces.length)].join('/'); 24 | return `https://raw.githubusercontent.com/${githubApiUrl}`; 25 | } 26 | 27 | async function fetchCode(githubPath) { 28 | const githubApiUrl = convertToGitHubApiUrl(githubPath); 29 | const response = await fetch(githubApiUrl); 30 | return response.text(); 31 | } 32 | 33 | module.exports = { fetchCode }; 34 | -------------------------------------------------------------------------------- /site/src/shortcodes/includecode/from-local.js: -------------------------------------------------------------------------------- 1 | const { readFile } = require('fs'); 2 | const { resolve } = require('path'); 3 | const { promisify } = require('util'); 4 | const readFileAsync = promisify(readFile); 5 | 6 | function convertGitHubPathToLocal(githubPath) { 7 | return resolve(__dirname, '../../../repo_clones', githubPath); 8 | } 9 | 10 | async function fetchCode(githubPath = '') { 11 | let content = ''; 12 | try { 13 | const localPath = convertGitHubPathToLocal(githubPath); 14 | content = await readFileAsync(localPath, 'utf-8'); 15 | } catch(error) { 16 | console.error(error); 17 | content = 'File not found 😭'; 18 | } 19 | return content; 20 | } 21 | 22 | module.exports = { 23 | fetchCode, 24 | }; 25 | -------------------------------------------------------------------------------- /site/src/shortcodes/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const { readdirSync, lstatSync } = require('fs'); 18 | const { resolve } = require('path'); 19 | 20 | /** 21 | * This sets up the shortcodes plugin to dynamically register 22 | * any shortcode in this directory, as long as it is is in 23 | * its own directory, exported in an index.js with an exports 24 | * of an array of shortcodes. 25 | * 26 | * Example: 27 | * / shortcodes 28 | * / includecode 29 | * + index.js 30 | * module.exports = { shortcodes: [...] } 31 | */ 32 | 33 | const shortcodes = readdirSync(__dirname) 34 | .map(relativePath => resolve(__dirname, relativePath)) 35 | .filter(absolutePath => lstatSync(absolutePath).isDirectory()) 36 | .map(path => require(path).shortcodes) 37 | .flat(); 38 | 39 | module.exports = { 40 | shortcodes 41 | }; 42 | -------------------------------------------------------------------------------- /site/src/shortcodes/version/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Usage: {% version %} 18 | const version = { 19 | name: "version", 20 | type: "addShortcode", 21 | create () { 22 | return Date.now().toString(); 23 | } 24 | }; 25 | 26 | module.exports = { 27 | shortcodes: [ 28 | version, 29 | ] 30 | }; 31 | -------------------------------------------------------------------------------- /site/src/storage/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Storage 4 | order: 6 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /site/src/storage/storage.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /site/src/styles/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | purge: [ 18 | "src/**/*.njk", 19 | "src/**/*.md", 20 | "src/**/*.js", 21 | ], 22 | darkMode: false, // or 'media' or 'class' 23 | theme: { 24 | fontFamily: { 25 | body: ['Roboto', 'Arial', 'sans-serif'], 26 | display: ['Google Sans', 'Arial', 'sans-serif'], 27 | mono: ['Roboto Mono', 'monospace'], 28 | }, 29 | extend: { 30 | colors: { 31 | 'black': 'hsl(0 0% 0% / 87%)', 32 | 'blue-200': 'hsl(214 82% 50% / 7%)', 33 | 'blue': 'hsl(214 82% 50%)', 34 | 'navy': '#283142', 35 | 'grey': '#DADCE0', 36 | 'grey-200': '#ECEFF1', 37 | 'grey-300': 'hsl(0 0% 0% / 54%)', 38 | 'grey-600': 'hsl(213 5% 39% / 1)', 39 | 'grey-700': 'hsl(213 5% 19% / 1)', 40 | 'yellow': 'hsl(37 100% 94%)', 41 | 'orange': "#FF8F00", 42 | 'green': '#6CFF38', 43 | } 44 | }, 45 | }, 46 | variants: { 47 | extend: {}, 48 | }, 49 | plugins: [], 50 | } -------------------------------------------------------------------------------- /site/src/universal/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyNavigation: 3 | key: Universal 4 | order: 11 5 | --- 6 | -------------------------------------------------------------------------------- /site/src/universal/universal.11tydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "guide.njk", 3 | "tags": "guides" 4 | } 5 | -------------------------------------------------------------------------------- /src/ai/ai.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AI, getAI, provideAI } from '@angular/fire/ai'; 3 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('AI', () => { 8 | let app: FirebaseApp; 9 | let ai: AI; 10 | let providedAI: AI; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideAI(() => { 21 | providedAI = getAI(getApp(appName)); 22 | return providedAI; 23 | }), 24 | ], 25 | }); 26 | app = TestBed.inject(FirebaseApp); 27 | ai = TestBed.inject(AI); 28 | }); 29 | 30 | it('should be injectable', () => { 31 | expect(providedAI).toBeTruthy(); 32 | expect(ai).toEqual(providedAI); 33 | expect(ai.app).toEqual(app); 34 | }); 35 | 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /src/ai/ai.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { AI as FirebaseAI } from 'firebase/ai'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface AI extends FirebaseAI {} 9 | 10 | export class AI { 11 | constructor(ai: FirebaseAI) { 12 | return ai; 13 | } 14 | } 15 | 16 | export const AI_PROVIDER_NAME = 'AI'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface AIInstances extends Array {} 20 | 21 | export class AIInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(AI_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const AIInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(AI_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/ai/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/ai'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | getAI as _getAI, 6 | getGenerativeModel as _getGenerativeModel, 7 | getImagenModel as _getImagenModel, 8 | getVertexAI as _getVertexAI 9 | } from 'firebase/ai'; 10 | 11 | export const getAI = ɵzoneWrap(_getAI, true); 12 | export const getGenerativeModel = ɵzoneWrap(_getGenerativeModel, true); 13 | export const getImagenModel = ɵzoneWrap(_getImagenModel, true); 14 | export const getVertexAI = ɵzoneWrap(_getVertexAI, true); 15 | -------------------------------------------------------------------------------- /src/ai/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/ai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/ai/public_api.ts: -------------------------------------------------------------------------------- 1 | export { AI, AIInstances, AIInstance$ } from './ai'; 2 | export { provideAI, AIModule } from './ai.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/analytics/analytics.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { Analytics, getAnalytics, provideAnalytics } from '@angular/fire/analytics'; 3 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 4 | import { COMMON_CONFIG_TOO } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Analytics', () => { 8 | let app: FirebaseApp; 9 | let analytics: Analytics; 10 | let providedAnalytics: Analytics; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG_TOO, appName)), 20 | provideAnalytics(() => { 21 | providedAnalytics = getAnalytics(getApp(appName)); 22 | return providedAnalytics; 23 | }), 24 | ], 25 | }); 26 | app = TestBed.inject(FirebaseApp); 27 | analytics = TestBed.inject(Analytics); 28 | }); 29 | 30 | it('should be injectable', () => { 31 | expect(providedAnalytics).toBeTruthy(); 32 | expect(analytics).toEqual(providedAnalytics); 33 | expect(analytics.app).toEqual(app); 34 | }); 35 | 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /src/analytics/analytics.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Analytics as FirebaseAnalytics } from 'firebase/analytics'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Analytics extends FirebaseAnalytics {} 9 | 10 | export class Analytics { 11 | constructor(analytics: FirebaseAnalytics) { 12 | return analytics; 13 | } 14 | } 15 | 16 | export const ANALYTICS_PROVIDER_NAME = 'analytics'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface AnalyticsInstances extends Array {} 20 | 21 | export class AnalyticsInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(ANALYTICS_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const analyticInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(ANALYTICS_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/analytics/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/analytics'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | getAnalytics as _getAnalytics, 6 | getGoogleAnalyticsClientId as _getGoogleAnalyticsClientId, 7 | initializeAnalytics as _initializeAnalytics, 8 | isSupported as _isSupported, 9 | logEvent as _logEvent, 10 | setAnalyticsCollectionEnabled as _setAnalyticsCollectionEnabled, 11 | setConsent as _setConsent, 12 | setCurrentScreen as _setCurrentScreen, 13 | setDefaultEventParameters as _setDefaultEventParameters, 14 | setUserId as _setUserId, 15 | setUserProperties as _setUserProperties, 16 | settings as _settings 17 | } from 'firebase/analytics'; 18 | 19 | export const getAnalytics = ɵzoneWrap(_getAnalytics, true); 20 | export const getGoogleAnalyticsClientId = ɵzoneWrap(_getGoogleAnalyticsClientId, true); 21 | export const initializeAnalytics = ɵzoneWrap(_initializeAnalytics, true); 22 | export const isSupported = ɵzoneWrap(_isSupported, false); 23 | export const logEvent = ɵzoneWrap(_logEvent, false, 2); 24 | export const setAnalyticsCollectionEnabled = ɵzoneWrap(_setAnalyticsCollectionEnabled, true, 2); 25 | export const setConsent = ɵzoneWrap(_setConsent, true, 2); 26 | export const setCurrentScreen = ɵzoneWrap(_setCurrentScreen, true, 2); 27 | export const setDefaultEventParameters = ɵzoneWrap(_setDefaultEventParameters, true, 2); 28 | export const setUserId = ɵzoneWrap(_setUserId, true, 2); 29 | export const setUserProperties = ɵzoneWrap(_setUserProperties, true, 2); 30 | export const settings = ɵzoneWrap(_settings, true); 31 | -------------------------------------------------------------------------------- /src/analytics/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } -------------------------------------------------------------------------------- /src/analytics/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Analytics, AnalyticsInstances, analyticInstance$ } from './analytics'; 2 | export { provideAnalytics, AnalyticsModule } from './analytics.module'; 3 | export * from './firebase'; 4 | export * from './screen-tracking.service'; 5 | export * from './user-tracking.service'; 6 | -------------------------------------------------------------------------------- /src/analytics/user-tracking.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Injector, NgZone, OnDestroy } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import { Auth, authState } from '@angular/fire/auth'; 4 | import { registerVersion } from 'firebase/app'; 5 | import { Subscription } from 'rxjs'; 6 | import { Analytics } from './analytics'; 7 | import { isSupported, setUserId } from './firebase'; 8 | 9 | @Injectable() 10 | export class UserTrackingService implements OnDestroy { 11 | 12 | public readonly initialized: Promise; 13 | private disposables: Subscription[] = []; 14 | 15 | constructor( 16 | auth: Auth, 17 | zone: NgZone, 18 | injector: Injector, 19 | ) { 20 | registerVersion('angularfire', VERSION.full, 'user-tracking'); 21 | let resolveInitialized: () => void; 22 | this.initialized = zone.runOutsideAngular(() => new Promise(resolve => { resolveInitialized = resolve; })); 23 | // The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI 24 | // may not be done when services are initialized. Guard the functionality by first ensuring 25 | // that the (global) promise has resolved, then get Analytics from the injector. 26 | isSupported().then(() => { 27 | const analytics = injector.get(Analytics); 28 | if (analytics) { 29 | this.disposables = [ 30 | // TODO add credential tracking back in 31 | authState(auth).subscribe(user => { 32 | setUserId(analytics, user?.uid); 33 | resolveInitialized(); 34 | }), 35 | ]; 36 | } else { 37 | resolveInitialized(); 38 | } 39 | }); 40 | } 41 | 42 | ngOnDestroy() { 43 | this.disposables.forEach(it => it.unsubscribe()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/app-check/app-check.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Auth, connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Auth', () => { 8 | let app: FirebaseApp; 9 | let auth: Auth; 10 | let providedAuth: Auth; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideAuth(() => { 21 | providedAuth = getAuth(getApp(appName)); 22 | connectAuthEmulator(providedAuth, 'http://localhost:9098'); 23 | return providedAuth; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | auth = TestBed.inject(Auth); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(auth).toBeTruthy(); 33 | expect(auth).toEqual(providedAuth); 34 | expect(auth.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/app-check/app-check.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { AppCheck as FirebaseAppCheck } from 'firebase/app-check'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | export const APP_CHECK_PROVIDER_NAME = 'app-check'; 7 | 8 | // see notes in core/firebase.app.module.ts for why we're building the class like this 9 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 10 | export interface AppCheck extends FirebaseAppCheck {} 11 | 12 | export class AppCheck { 13 | constructor(appCheck: FirebaseAppCheck) { 14 | return appCheck; 15 | } 16 | } 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface AppCheckInstances extends Array {} 20 | 21 | export class AppCheckInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(APP_CHECK_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const appCheckInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(APP_CHECK_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/app-check/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/app-check'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | getLimitedUseToken as _getLimitedUseToken, 6 | getToken as _getToken, 7 | initializeAppCheck as _initializeAppCheck, 8 | onTokenChanged as _onTokenChanged, 9 | setTokenAutoRefreshEnabled as _setTokenAutoRefreshEnabled 10 | } from 'firebase/app-check'; 11 | 12 | export const getLimitedUseToken = ɵzoneWrap(_getLimitedUseToken, true, 2); 13 | export const getToken = ɵzoneWrap(_getToken, true); 14 | export const initializeAppCheck = ɵzoneWrap(_initializeAppCheck, true); 15 | export const onTokenChanged = ɵzoneWrap(_onTokenChanged, true); 16 | export const setTokenAutoRefreshEnabled = ɵzoneWrap(_setTokenAutoRefreshEnabled, true); 17 | -------------------------------------------------------------------------------- /src/app-check/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app-check/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } -------------------------------------------------------------------------------- /src/app-check/public_api.ts: -------------------------------------------------------------------------------- 1 | export { AppCheck, appCheckInstance$, AppCheckInstances } from './app-check'; 2 | export { provideAppCheck, AppCheckModule } from './app-check.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/app/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { COMMON_CONFIG } from '../test-config'; 4 | import { rando } from '../utils'; 5 | 6 | describe('FirebaseApp', () => { 7 | let app: FirebaseApp; 8 | let providedApp: FirebaseApp; 9 | let appName: string; 10 | 11 | describe('single injection', () => { 12 | 13 | beforeEach(() => { 14 | appName = rando(); 15 | TestBed.configureTestingModule({ 16 | providers: [ 17 | provideFirebaseApp(() => { 18 | providedApp = initializeApp(COMMON_CONFIG, appName); 19 | return providedApp; 20 | }) 21 | ], 22 | }); 23 | app = TestBed.inject(FirebaseApp); 24 | }); 25 | 26 | it('should be injectable', () => { 27 | expect(app).toBeTruthy(); 28 | expect(app).toEqual(providedApp); 29 | }); 30 | 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /src/app/app.ts: -------------------------------------------------------------------------------- 1 | import { FirebaseApp as IFirebaseApp, getApps } from 'firebase/app'; 2 | import { from, timer } from 'rxjs'; 3 | import { concatMap, distinct } from 'rxjs/operators'; 4 | 5 | // Need to turn the FirebaseApp interface exported by firebase/app into a class 6 | // as types don't work in Angular DI. We want developers to be able to inject FirebaseApp like so 7 | // constructor(app: FirebaseApp) 8 | // the cleanest way to achieve this that I found is to export a new interface and class 9 | // the interface just extends the interface you want to turn into the class. This informs tyepscript 10 | // that the class has all the same methods/properties as the interface you want to extend without 11 | // breaking if Firebase adds/removes APIs in future releases. This was a big problem for @angular/fire 12 | // back when we constructed our own class. Then in the "new class" we just return the FirebaseApp in the 13 | // constructor, this also has the added benefit of Firebase methods taking our DI class without 14 | // casting. E.g, 15 | // constructor(private app: FirebaseApp) { } 16 | // ngOnDestroy() { deleteApp(this.app); } 17 | // 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface FirebaseApp extends IFirebaseApp {} 20 | 21 | export class FirebaseApp { 22 | constructor(app: IFirebaseApp) { 23 | return app; 24 | } 25 | } 26 | 27 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 28 | export interface FirebaseApps extends Array {} 29 | 30 | export class FirebaseApps { 31 | constructor() { 32 | return getApps(); 33 | } 34 | } 35 | 36 | export const firebaseApp$ = timer(0, 300).pipe( 37 | concatMap(() => from(getApps())), 38 | distinct(), 39 | ); 40 | -------------------------------------------------------------------------------- /src/app/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/app'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | deleteApp as _deleteApp, 6 | getApp as _getApp, 7 | getApps as _getApps, 8 | initializeApp as _initializeApp, 9 | initializeServerApp as _initializeServerApp, 10 | onLog as _onLog, 11 | registerVersion as _registerVersion, 12 | setLogLevel as _setLogLevel 13 | } from 'firebase/app'; 14 | 15 | export const deleteApp = ɵzoneWrap(_deleteApp, true); 16 | export const getApp = ɵzoneWrap(_getApp, true); 17 | export const getApps = ɵzoneWrap(_getApps, true); 18 | export const initializeApp = ɵzoneWrap(_initializeApp, true); 19 | export const initializeServerApp = ɵzoneWrap(_initializeServerApp, true); 20 | export const onLog = ɵzoneWrap(_onLog, true); 21 | export const registerVersion = ɵzoneWrap(_registerVersion, true); 22 | export const setLogLevel = ɵzoneWrap(_setLogLevel, true); 23 | -------------------------------------------------------------------------------- /src/app/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } -------------------------------------------------------------------------------- /src/app/public_api.ts: -------------------------------------------------------------------------------- 1 | export { FirebaseApp, FirebaseApps, firebaseApp$ } from './app'; 2 | export { provideFirebaseApp, FirebaseAppModule } from './app.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/auth-guard/auth-guard.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import { registerVersion } from 'firebase/app'; 4 | import { AuthGuard } from './auth-guard'; 5 | 6 | @NgModule({ 7 | providers: [ AuthGuard ] 8 | }) 9 | export class AuthGuardModule { 10 | constructor() { 11 | registerVersion('angularfire', VERSION.full, 'auth-guard'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/auth-guard/auth-guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { APP_BASE_HREF } from '@angular/common'; 2 | import { TestBed } from '@angular/core/testing'; 3 | import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 4 | import { connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth'; 5 | import { AuthGuard, AuthGuardModule } from '@angular/fire/auth-guard'; 6 | import { Router, RouterModule } from '@angular/router'; 7 | import { COMMON_CONFIG } from '../test-config'; 8 | import { rando } from '../utils'; 9 | 10 | class TestComponent { } 11 | 12 | describe('AuthGuard', () => { 13 | let router: Router; 14 | let appName: string; 15 | 16 | beforeEach(() => { 17 | appName = rando(); 18 | TestBed.configureTestingModule({ 19 | imports: [ 20 | AuthGuardModule, 21 | RouterModule.forRoot([ 22 | { path: 'a', component: TestComponent, canActivate: [AuthGuard] } 23 | ]) 24 | ], 25 | providers: [ 26 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 27 | provideAuth(() => { 28 | const auth = getAuth(getApp(appName)); 29 | connectAuthEmulator(auth, 'http://localhost:9098'); 30 | return auth; 31 | }), 32 | { provide: APP_BASE_HREF, useValue: 'http://localhost:4200/' } 33 | ] 34 | }); 35 | 36 | router = TestBed.inject(Router); 37 | }); 38 | 39 | it('should be injectable', () => { 40 | expect(AuthGuard).toBeTruthy(); 41 | }); 42 | 43 | it('router should be valid', () => { 44 | expect(router).toBeTruthy(); 45 | }); 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /src/auth-guard/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/auth-guard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/auth-guard/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './auth-guard'; 2 | export * from './auth-guard.module'; 3 | -------------------------------------------------------------------------------- /src/auth/auth.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Auth, connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth'; 4 | import { COMMON_CONFIG, authEmulatorPort } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Auth', () => { 8 | let app: FirebaseApp; 9 | let auth: Auth; 10 | let providedAuth: Auth; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideAuth(() => { 21 | providedAuth = getAuth(getApp(appName)); 22 | connectAuthEmulator(providedAuth, `http://localhost:${authEmulatorPort}`, { disableWarnings: true }); 23 | return providedAuth; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | auth = TestBed.inject(Auth); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedAuth).toBeTruthy(); 33 | expect(auth).toEqual(providedAuth); 34 | expect(auth.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/auth/auth.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Auth as FirebaseAuth } from 'firebase/auth'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | export const AUTH_PROVIDER_NAME = 'auth'; 7 | 8 | // see notes in core/firebase.app.module.ts for why we're building the class like this 9 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 10 | export interface Auth extends FirebaseAuth {} 11 | 12 | export class Auth { 13 | constructor(auth: FirebaseAuth) { 14 | return auth; 15 | } 16 | } 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface AuthInstances extends Array {} 20 | 21 | export class AuthInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(AUTH_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const authInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(AUTH_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/auth/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } -------------------------------------------------------------------------------- /src/auth/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Auth, AuthInstances, authInstance$ } from './auth'; 2 | export { provideAuth, AuthModule } from './auth.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/auth/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | authState as _authState, 5 | idToken as _idToken, 6 | user as _user 7 | } from 'rxfire/auth'; 8 | 9 | export const authState = ɵzoneWrap(_authState, true); 10 | export const idToken = ɵzoneWrap(_idToken, true); 11 | export const user = ɵzoneWrap(_user, true); 12 | -------------------------------------------------------------------------------- /src/compat/analytics/analytics.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, Optional } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireAnalytics } from './analytics'; 5 | import { ScreenTrackingService } from './screen-tracking.service'; 6 | import { UserTrackingService } from './user-tracking.service'; 7 | 8 | @NgModule({ 9 | providers: [ AngularFireAnalytics ] 10 | }) 11 | export class AngularFireAnalyticsModule { 12 | constructor( 13 | analytics: AngularFireAnalytics, 14 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 15 | @Optional() screenTracking: ScreenTrackingService, 16 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 17 | @Optional() userTracking: UserTrackingService, 18 | ) { 19 | firebase.registerVersion('angularfire', VERSION.full, 'analytics-compat'); 20 | // calling anything on analytics will eagerly load the SDK 21 | analytics.app.then(() => undefined); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/compat/analytics/analytics.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AngularFireModule } from '@angular/fire/compat'; 3 | import { AngularFireAnalytics, AngularFireAnalyticsModule } from '@angular/fire/compat/analytics'; 4 | import { COMMON_CONFIG } from '../../test-config'; 5 | import { rando } from '../../utils'; 6 | 7 | 8 | describe('AngularFireAnalytics', () => { 9 | let analytics: AngularFireAnalytics; 10 | 11 | beforeEach(() => { 12 | TestBed.configureTestingModule({ 13 | imports: [ 14 | AngularFireModule.initializeApp(COMMON_CONFIG, rando()), 15 | AngularFireAnalyticsModule 16 | ] 17 | }); 18 | 19 | analytics = TestBed.inject(AngularFireAnalytics); 20 | }); 21 | 22 | it('should be exist', () => { 23 | expect(analytics instanceof AngularFireAnalytics).toBe(true); 24 | }); 25 | 26 | it('should have the Firebase Functions instance', () => { 27 | expect(analytics.app).toBeDefined(); 28 | }); 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /src/compat/analytics/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/analytics, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | app: null, 5 | logEvent: null, 6 | setCurrentScreen: null, 7 | setUserId: null, 8 | setUserProperties: null, 9 | setAnalyticsCollectionEnabled: null, 10 | }; 11 | -------------------------------------------------------------------------------- /src/compat/analytics/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/compat/analytics/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/analytics/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './analytics'; 2 | export * from './analytics.module'; 3 | export * from './screen-tracking.service'; 4 | export * from './user-tracking.service'; 5 | -------------------------------------------------------------------------------- /src/compat/analytics/screen-tracking.service.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactoryResolver, Injectable, NgZone, OnDestroy, Optional } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import { ɵscreenViewEvent } from '@angular/fire/analytics'; 4 | import { Title } from '@angular/platform-browser'; 5 | import { Router } from '@angular/router'; 6 | import firebase from 'firebase/compat/app'; 7 | import { Subscription } from 'rxjs'; 8 | import { switchMap } from 'rxjs/operators'; 9 | import { AngularFireAnalytics } from './analytics'; 10 | import { UserTrackingService } from './user-tracking.service'; 11 | 12 | const SCREEN_VIEW_EVENT = 'screen_view'; 13 | 14 | @Injectable() 15 | export class ScreenTrackingService implements OnDestroy { 16 | 17 | private disposable: Subscription | undefined; 18 | 19 | constructor( 20 | analytics: AngularFireAnalytics, 21 | @Optional() router: Router, 22 | @Optional() title: Title, 23 | componentFactoryResolver: ComponentFactoryResolver, 24 | zone: NgZone, 25 | @Optional() userTrackingService: UserTrackingService, 26 | ) { 27 | firebase.registerVersion('angularfire', VERSION.full, 'compat-screen-tracking'); 28 | if (!router || !analytics) { return this; } 29 | zone.runOutsideAngular(() => { 30 | this.disposable = ɵscreenViewEvent(router, title, componentFactoryResolver).pipe( 31 | switchMap(async params => { 32 | if (userTrackingService) { 33 | await userTrackingService.initialized; 34 | } 35 | return await analytics.logEvent(SCREEN_VIEW_EVENT, params); 36 | }) 37 | ).subscribe(); 38 | }); 39 | } 40 | 41 | ngOnDestroy() { 42 | if (this.disposable) { 43 | this.disposable.unsubscribe(); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/compat/auth-guard/auth-guard.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireAuthGuard } from './auth-guard'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireAuthGuard ] 8 | }) 9 | export class AngularFireAuthGuardModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'auth-guard-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/auth-guard/auth-guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { APP_BASE_HREF } from '@angular/common'; 2 | import { TestBed } from '@angular/core/testing'; 3 | import { AngularFireModule } from '@angular/fire/compat'; 4 | import { AngularFireAuthGuard, AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard'; 5 | import { Router, RouterModule } from '@angular/router'; 6 | import { COMMON_CONFIG } from '../../../src/test-config'; 7 | import { rando } from '../../../src/utils'; 8 | 9 | class TestComponent { } 10 | 11 | describe('AngularFireAuthGuard', () => { 12 | let router: Router; 13 | 14 | beforeEach(() => { 15 | TestBed.configureTestingModule({ 16 | imports: [ 17 | AngularFireModule.initializeApp(COMMON_CONFIG, rando()), 18 | AngularFireAuthGuardModule, 19 | RouterModule.forRoot([ 20 | { path: 'a', component: TestComponent, canActivate: [AngularFireAuthGuard] } 21 | ]) 22 | ], 23 | providers: [ 24 | { provide: APP_BASE_HREF, useValue: 'http://localhost:4200/' } 25 | ] 26 | }); 27 | 28 | router = TestBed.inject(Router); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(router).toBeTruthy(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/compat/auth-guard/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/auth-guard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/auth-guard/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './auth-guard'; 2 | export * from './auth-guard.module'; 3 | -------------------------------------------------------------------------------- /src/compat/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireAuth } from './auth'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireAuth ] 8 | }) 9 | export class AngularFireAuthModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'auth-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/auth/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/auth, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | name: null, 5 | config: null, 6 | emulatorConfig: null, 7 | app: null, 8 | applyActionCode: null, 9 | checkActionCode: null, 10 | confirmPasswordReset: null, 11 | createUserWithEmailAndPassword: null, 12 | currentUser: null, 13 | fetchSignInMethodsForEmail: null, 14 | isSignInWithEmailLink: null, 15 | getRedirectResult: null, 16 | languageCode: null, 17 | settings: null, 18 | onAuthStateChanged: null, 19 | onIdTokenChanged: null, 20 | sendSignInLinkToEmail: null, 21 | sendPasswordResetEmail: null, 22 | setPersistence: null, 23 | signInAndRetrieveDataWithCredential: null, 24 | signInAnonymously: null, 25 | signInWithCredential: null, 26 | signInWithCustomToken: null, 27 | signInWithEmailAndPassword: null, 28 | signInWithPhoneNumber: null, 29 | signInWithEmailLink: null, 30 | signInWithPopup: null, 31 | signInWithRedirect: null, 32 | signOut: null, 33 | tenantId: null, 34 | updateCurrentUser: null, 35 | useDeviceLanguage: null, 36 | useEmulator: null, 37 | verifyPasswordResetCode: null, 38 | }; 39 | -------------------------------------------------------------------------------- /src/compat/auth/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/auth/public_api.ts: -------------------------------------------------------------------------------- 1 | 2 | import 'firebase/compat/auth'; // removed in build process when not UMD 3 | 4 | export * from './auth'; 5 | export * from './auth.module'; 6 | -------------------------------------------------------------------------------- /src/compat/cache.ts: -------------------------------------------------------------------------------- 1 | import { isDevMode } from '@angular/core'; 2 | 3 | export function ɵcacheInstance(cacheKey: any, moduleName: string, appName: string, fn: () => T, deps: any): T { 4 | const [, instance, cachedDeps] = globalThis.ɵAngularfireInstanceCache.find((it: any) => it[0] === cacheKey) || []; 5 | if (instance) { 6 | if (!matchDep(deps, cachedDeps)) { 7 | log('error', `${moduleName} was already initialized on the ${appName} Firebase App with different settings.${IS_HMR ? ' You may need to reload as Firebase is not HMR aware.' : ''}`); 8 | log('warn', {is: deps, was: cachedDeps}); 9 | } 10 | return instance; 11 | } else { 12 | const newInstance = fn(); 13 | globalThis.ɵAngularfireInstanceCache.push([cacheKey, newInstance, deps]); 14 | return newInstance; 15 | } 16 | } 17 | 18 | function matchDep(a: any, b: any) { 19 | try { 20 | return a.toString() === b.toString(); 21 | } catch (_) { 22 | return a === b; 23 | } 24 | } 25 | 26 | const IS_HMR = typeof module !== 'undefined' && !!(module as any).hot; 27 | 28 | const log = (level: 'log'|'error'|'info'|'warn', ...args: any) => { 29 | if (isDevMode() && typeof console !== 'undefined') { 30 | // eslint-disable-next-line no-console 31 | console[level](...args); 32 | } 33 | }; 34 | 35 | globalThis.ɵAngularfireInstanceCache ||= []; 36 | -------------------------------------------------------------------------------- /src/compat/database/database.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireDatabase } from './database'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireDatabase ] 8 | }) 9 | export class AngularFireDatabaseModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'rtdb-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/database/list/data-operation.ts: -------------------------------------------------------------------------------- 1 | import { DatabaseReference, DatabaseSnapshot, FirebaseOperation } from '../interfaces'; 2 | import { checkOperationCases } from '../utils'; 3 | 4 | export function createDataOperationMethod(ref: DatabaseReference, operation: string) { 5 | return function dataOperation(item: FirebaseOperation, value: T) { 6 | return checkOperationCases(item, { 7 | stringCase: () => ref.child(item as string)[operation](value), 8 | firebaseCase: () => (item as DatabaseReference)[operation](value), 9 | snapshotCase: () => (item as DatabaseSnapshot).ref[operation](value) 10 | }); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /src/compat/database/list/remove.ts: -------------------------------------------------------------------------------- 1 | import { DatabaseReference, DatabaseSnapshot, FirebaseOperation } from '../interfaces'; 2 | import { checkOperationCases } from '../utils'; 3 | 4 | // TODO(davideast): Find out why TS thinks this returns firebase.Primise 5 | // instead of Promise. 6 | export function createRemoveMethod(ref: DatabaseReference) { 7 | return function remove(item?: FirebaseOperation): any { 8 | if (!item) { return ref.remove(); } 9 | return checkOperationCases(item, { 10 | stringCase: () => ref.child(item as string).remove(), 11 | firebaseCase: () => (item as DatabaseReference).remove(), 12 | snapshotCase: () => (item as DatabaseSnapshot).ref.remove() 13 | }); 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/compat/database/list/snapshot-changes.ts: -------------------------------------------------------------------------------- 1 | import { Observable, SchedulerLike } from 'rxjs'; 2 | import { ChildEvent, DatabaseQuery, SnapshotAction } from '../interfaces'; 3 | import { listChanges } from './changes'; 4 | import { validateEventsArray } from './utils'; 5 | 6 | export function snapshotChanges( 7 | query: DatabaseQuery, 8 | events?: ChildEvent[], 9 | scheduler?: SchedulerLike 10 | ): Observable[]> { 11 | events = validateEventsArray(events); 12 | return listChanges(query, events, scheduler); 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/database/list/state-changes.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerLike, merge } from 'rxjs'; 2 | import { ChildEvent, DatabaseQuery } from '../interfaces'; 3 | import { fromRef } from '../observable/fromRef'; 4 | import { validateEventsArray } from './utils'; 5 | 6 | export function stateChanges(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike) { 7 | events = validateEventsArray(events); 8 | const childEvent$ = events.map(event => fromRef(query, event, 'on', scheduler)); 9 | return merge(...childEvent$); 10 | } 11 | -------------------------------------------------------------------------------- /src/compat/database/list/utils.ts: -------------------------------------------------------------------------------- 1 | import { isNil } from '../utils'; 2 | 3 | export function validateEventsArray(events?: any[]) { 4 | if (isNil(events) || events.length === 0) { 5 | events = ['child_added', 'child_removed', 'child_changed', 'child_moved']; 6 | } 7 | return events; 8 | } 9 | -------------------------------------------------------------------------------- /src/compat/database/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/database/object/create-reference.ts: -------------------------------------------------------------------------------- 1 | import { Injector } from '@angular/core'; 2 | import { pendingUntilEvent } from '@angular/core/rxjs-interop'; 3 | import { map } from 'rxjs/operators'; 4 | import { AngularFireDatabase } from '../database'; 5 | import { AngularFireObject, DatabaseQuery } from '../interfaces'; 6 | import { createObjectSnapshotChanges } from './snapshot-changes'; 7 | 8 | export function createObjectReference(query: DatabaseQuery, afDatabase: AngularFireDatabase, injector?: Injector): AngularFireObject { 9 | return { 10 | query, 11 | snapshotChanges() { 12 | return createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)().pipe( 13 | pendingUntilEvent(injector) 14 | ); 15 | }, 16 | update(data: Partial) { return query.ref.update(data as any) as Promise; }, 17 | set(data: T) { return query.ref.set(data) as Promise; }, 18 | remove() { return query.ref.remove() as Promise; }, 19 | valueChanges() { 20 | const snapshotChanges$ = createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)(); 21 | return snapshotChanges$.pipe( 22 | pendingUntilEvent(injector), 23 | map(action => action.payload.exists() ? action.payload.val() as T : null) 24 | ); 25 | }, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/compat/database/object/snapshot-changes.ts: -------------------------------------------------------------------------------- 1 | import { Observable, SchedulerLike } from 'rxjs'; 2 | import { DatabaseQuery, SnapshotAction } from '../interfaces'; 3 | import { fromRef } from '../observable/fromRef'; 4 | 5 | export function createObjectSnapshotChanges(query: DatabaseQuery, scheduler?: SchedulerLike) { 6 | return function snapshotChanges(): Observable> { 7 | return fromRef(query, 'value', 'on', scheduler); 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /src/compat/database/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/database/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './database'; 2 | export * from './list/changes'; 3 | export * from './list/create-reference'; 4 | export * from './list/snapshot-changes'; 5 | export * from './list/state-changes'; 6 | export * from './list/audit-trail'; 7 | export * from './observable/fromRef'; 8 | export * from './database.module'; 9 | -------------------------------------------------------------------------------- /src/compat/database/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import * as utils from './utils'; 2 | 3 | describe('utils', () => { 4 | 5 | describe('isString', () => { 6 | 7 | it('should be able to properly detect a string', () => { 8 | const str = 'oh hai'; 9 | const notStr = 101; 10 | const bool = true; 11 | const nul = null; 12 | const obj = {}; 13 | const fn = () => undefined; 14 | const undef = undefined; 15 | expect(utils.isString(str)).toBe(true); 16 | expect(utils.isString(notStr)).toBe(false); 17 | expect(utils.isString(bool)).toBe(false); 18 | expect(utils.isString(nul)).toBe(false); 19 | expect(utils.isString(obj)).toBe(false); 20 | expect(utils.isString(fn)).toBe(false); 21 | expect(utils.isString(undef)).toBe(false); 22 | }); 23 | 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /src/compat/database/utils.ts: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/compat/app'; 2 | import { DatabaseReference, FirebaseOperation, FirebaseOperationCases, PathReference } from './interfaces'; 3 | 4 | export function isString(value: any): boolean { 5 | return typeof value === 'string'; 6 | } 7 | 8 | export function isFirebaseDataSnapshot(value: any): boolean { 9 | return typeof value.exportVal === 'function'; 10 | } 11 | 12 | export function isNil(obj: any): boolean { 13 | return obj === undefined || obj === null; 14 | } 15 | 16 | export function isFirebaseRef(value: any): boolean { 17 | return typeof value.set === 'function'; 18 | } 19 | 20 | /** 21 | * Returns a database reference given a Firebase App and an 22 | * absolute or relative path. 23 | * @param database - Firebase Database 24 | * @param pathRef - Database path, relative or absolute 25 | */ 26 | export function getRef(database: firebase.database.Database, pathRef: PathReference): DatabaseReference { 27 | // if a db ref was passed in, just return it 28 | return isFirebaseRef(pathRef) ? pathRef as DatabaseReference 29 | : database.ref(pathRef as string); 30 | } 31 | 32 | export function checkOperationCases(item: FirebaseOperation, cases: FirebaseOperationCases): Promise { 33 | if (isString(item)) { 34 | return cases.stringCase(); 35 | } else if (isFirebaseRef(item)) { 36 | return cases.firebaseCase(); 37 | } else if (isFirebaseDataSnapshot(item)) { 38 | return cases.snapshotCase(); 39 | } 40 | throw new Error(`Expects a string, snapshot, or reference. Got: ${typeof item}`); 41 | } 42 | -------------------------------------------------------------------------------- /src/compat/firebase.app.ts: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/compat/app'; 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 4 | export interface FirebaseApp extends firebase.app.App {} 5 | 6 | export class FirebaseApp { 7 | constructor(app: firebase.app.App) { 8 | return app; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/compat/firestore/firestore.module.ts: -------------------------------------------------------------------------------- 1 | import { ModuleWithProviders, NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFirestore, ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS } from './firestore'; 5 | import { PersistenceSettings } from './interfaces'; 6 | 7 | @NgModule({ 8 | providers: [ AngularFirestore ] 9 | }) 10 | export class AngularFirestoreModule { 11 | constructor() { 12 | firebase.registerVersion('angularfire', VERSION.full, 'fst-compat'); 13 | } 14 | /** 15 | * Attempt to enable persistent storage, if possible 16 | */ 17 | static enablePersistence(persistenceSettings?: PersistenceSettings): ModuleWithProviders { 18 | return { 19 | ngModule: AngularFirestoreModule, 20 | providers: [ 21 | { provide: ENABLE_PERSISTENCE, useValue: true }, 22 | { provide: PERSISTENCE_SETTINGS, useValue: persistenceSettings }, 23 | ] 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/compat/firestore/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/firestore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/firestore/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './firestore'; 2 | export * from './firestore.module'; 3 | export * from './collection/collection'; 4 | export * from './collection-group/collection-group'; 5 | export * from './document/document'; 6 | export * from './collection/changes'; 7 | export * from './observable/fromRef'; 8 | export * from './interfaces'; 9 | -------------------------------------------------------------------------------- /src/compat/functions/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/functions, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | useEmulator: null, 5 | useFunctionsEmulator: null, 6 | httpsCallable: null, 7 | }; 8 | -------------------------------------------------------------------------------- /src/compat/functions/functions.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireFunctions } from './functions'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireFunctions ] 8 | }) 9 | export class AngularFireFunctionsModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'fn-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/functions/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/functions/public_api.ts: -------------------------------------------------------------------------------- 1 | 2 | import 'firebase/compat/functions'; // removed in build process when not UMD 3 | 4 | export * from './functions'; 5 | export * from './functions.module'; 6 | -------------------------------------------------------------------------------- /src/compat/messaging/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/messaging, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | deleteToken: null, 5 | getToken: null, 6 | onMessage: null, 7 | onBackgroundMessage: null, 8 | }; 9 | -------------------------------------------------------------------------------- /src/compat/messaging/messaging.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireMessaging } from './messaging'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireMessaging ] 8 | }) 9 | export class AngularFireMessagingModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'fcm-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/messaging/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/messaging/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/messaging/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './messaging'; 2 | export * from './messaging.module'; 3 | -------------------------------------------------------------------------------- /src/compat/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/performance/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/performance, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | app: null, 5 | trace: null, 6 | instrumentationEnabled: null, 7 | dataCollectionEnabled: null, 8 | }; 9 | -------------------------------------------------------------------------------- /src/compat/performance/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/performance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/performance/performance.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, Optional } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFirePerformance } from './performance'; 5 | import { PerformanceMonitoringService } from './performance.service'; 6 | 7 | @NgModule({ 8 | providers: [ AngularFirePerformance ] 9 | }) 10 | export class AngularFirePerformanceModule { 11 | constructor( 12 | perf: AngularFirePerformance, 13 | @Optional() _: PerformanceMonitoringService 14 | ) { 15 | firebase.registerVersion('angularfire', VERSION.full, 'perf-compat'); 16 | // call anything here to get perf loading 17 | perf.dataCollectionEnabled.then(() => undefined); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/compat/performance/performance.service.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationRef, Injectable, OnDestroy } from '@angular/core'; 2 | import { Subscription } from 'rxjs'; 3 | import { first, tap } from 'rxjs/operators'; 4 | 5 | const IS_STABLE_START_MARK = 'Zone'; 6 | const IS_STABLE_END_MARK = '_isStableEnd'; 7 | 8 | @Injectable() 9 | export class PerformanceMonitoringService implements OnDestroy { 10 | 11 | private disposable: Subscription|undefined; 12 | 13 | constructor(appRef: ApplicationRef) { 14 | // eslint-disable-next-line @typescript-eslint/prefer-optional-chain 15 | if (typeof window !== 'undefined' && window.performance?.mark) { 16 | this.disposable = appRef.isStable.pipe( 17 | first(it => it), 18 | tap(() => { 19 | window.performance.mark(IS_STABLE_END_MARK); 20 | window.performance.measure('isStable', IS_STABLE_START_MARK, IS_STABLE_END_MARK); 21 | }) 22 | ).subscribe(); 23 | } 24 | } 25 | 26 | ngOnDestroy() { 27 | if (this.disposable) { this.disposable.unsubscribe(); } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/compat/performance/performance.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AngularFireModule } from '@angular/fire/compat'; 3 | import { AngularFirePerformance, AngularFirePerformanceModule } from '@angular/fire/compat/performance'; 4 | import { COMMON_CONFIG } from '../../../src/test-config'; 5 | 6 | describe('AngularFirePerformance', () => { 7 | let afp: AngularFirePerformance; 8 | 9 | beforeEach(() => { 10 | TestBed.configureTestingModule({ 11 | imports: [ 12 | // NOTE: You must use the [DEFAULT] app instance 13 | // for these tests to work. 14 | AngularFireModule.initializeApp(COMMON_CONFIG), 15 | AngularFirePerformanceModule 16 | ] 17 | }); 18 | afp = TestBed.inject(AngularFirePerformance); 19 | }); 20 | 21 | it('should exist', () => { 22 | expect(afp instanceof AngularFirePerformance).toBe(true); 23 | }); 24 | 25 | it('should have the Performance instance', () => { 26 | expect(afp.dataCollectionEnabled).toBeDefined(); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /src/compat/performance/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './performance'; 2 | export * from './performance.module'; 3 | export * from './performance.service'; 4 | -------------------------------------------------------------------------------- /src/compat/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './proxy'; 2 | export * from './firebase.app'; 3 | export * from './firebase.app.module'; 4 | export * from './cache'; 5 | -------------------------------------------------------------------------------- /src/compat/remote-config/base.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | // Export a null object with the same keys as firebase/compat/remote-config, so Proxy can work with proxy-polyfill in Internet Explorer 3 | export const proxyPolyfillCompat = { 4 | app: null, 5 | settings: null, 6 | defaultConfig: null, 7 | fetchTimeMillis: null, 8 | lastFetchStatus: null, 9 | activate: null, 10 | ensureInitialized: null, 11 | fetch: null, 12 | fetchAndActivate: null, 13 | getAll: null, 14 | getBoolean: null, 15 | getNumber: null, 16 | getString: null, 17 | getValue: null, 18 | setLogLevel: null, 19 | }; 20 | -------------------------------------------------------------------------------- /src/compat/remote-config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/compat/remote-config/interfaces.ts: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/compat/app'; 2 | 3 | export type Settings = firebase.remoteConfig.Settings; 4 | -------------------------------------------------------------------------------- /src/compat/remote-config/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/remote-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/remote-config/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './remote-config'; 2 | export * from './remote-config.module'; 3 | -------------------------------------------------------------------------------- /src/compat/remote-config/remote-config.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { AngularFireRemoteConfig } from './remote-config'; 5 | 6 | @NgModule({ 7 | providers: [ AngularFireRemoteConfig ] 8 | }) 9 | export class AngularFireRemoteConfigModule { 10 | constructor() { 11 | firebase.registerVersion('angularfire', VERSION.full, 'rc-compat'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/storage/interfaces.ts: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/compat/app'; 2 | 3 | export type UploadTask = firebase.storage.UploadTask; 4 | export type UploadTaskSnapshot = firebase.storage.UploadTaskSnapshot; 5 | export type UploadMetadata = firebase.storage.UploadMetadata; 6 | 7 | export type SettableMetadata = firebase.storage.SettableMetadata; 8 | export type Reference = firebase.storage.Reference; 9 | export type StringFormat = firebase.storage.StringFormat; 10 | export type ListResult = firebase.storage.ListResult; 11 | export type ListOptions = firebase.storage.ListOptions; 12 | -------------------------------------------------------------------------------- /src/compat/storage/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/compat/storage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/compat/storage/pipes/storageUrl.pipe.ts: -------------------------------------------------------------------------------- 1 | import { AsyncPipe } from '@angular/common'; 2 | import { ChangeDetectorRef, NgModule, OnDestroy, Optional, Pipe, PipeTransform, TransferState, makeStateKey } from '@angular/core'; 3 | import { Observable, of } from 'rxjs'; 4 | import { tap } from 'rxjs/operators'; 5 | import { AngularFireStorage } from '../storage'; 6 | 7 | /** to be used with in combination with | async */ 8 | @Pipe({ 9 | name: 'getDownloadURL', 10 | pure: false, 11 | }) 12 | export class GetDownloadURLPipe implements PipeTransform, OnDestroy { 13 | 14 | private asyncPipe: AsyncPipe; 15 | private path: string; 16 | private downloadUrl$: Observable; 17 | 18 | constructor( 19 | private storage: AngularFireStorage, 20 | cdr: ChangeDetectorRef, 21 | @Optional() private state: TransferState 22 | ) { 23 | this.asyncPipe = new AsyncPipe(cdr); 24 | } 25 | 26 | transform(path: string) { 27 | if (path !== this.path) { 28 | this.path = path; 29 | const key = makeStateKey(`|getDownloadURL|${path}`); 30 | const existing = this.state?.get(key, undefined); 31 | this.downloadUrl$ = existing ? of(existing) : this.storage.ref(path).getDownloadURL().pipe( 32 | tap(it => this.state?.set(key, it)) 33 | ); 34 | } 35 | return this.asyncPipe.transform(this.downloadUrl$); 36 | } 37 | 38 | ngOnDestroy() { 39 | this.asyncPipe.ngOnDestroy(); 40 | } 41 | 42 | } 43 | 44 | @NgModule({ 45 | imports: [ GetDownloadURLPipe ], 46 | exports: [ GetDownloadURLPipe ], 47 | }) 48 | export class GetDownloadURLPipeModule {} 49 | -------------------------------------------------------------------------------- /src/compat/storage/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './ref'; 2 | export * from './storage'; 3 | export * from './task'; 4 | export * from './observable/fromTask'; 5 | export * from './storage.module'; 6 | export * from './pipes/storageUrl.pipe'; 7 | -------------------------------------------------------------------------------- /src/compat/storage/storage.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { VERSION } from '@angular/fire'; 3 | import firebase from 'firebase/compat/app'; 4 | import { GetDownloadURLPipeModule } from './pipes/storageUrl.pipe'; 5 | import { AngularFireStorage } from './storage'; 6 | 7 | @NgModule({ 8 | imports: [ GetDownloadURLPipeModule ], 9 | exports: [ GetDownloadURLPipeModule ], 10 | providers: [ AngularFireStorage ] 11 | }) 12 | export class AngularFireStorageModule { 13 | constructor() { 14 | firebase.registerVersion('angularfire', VERSION.full, 'gcs-compat'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/compat/storage/task.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { map } from 'rxjs/operators'; 3 | import { UploadTask, UploadTaskSnapshot } from './interfaces'; 4 | import { fromTask } from './observable/fromTask'; 5 | 6 | export interface AngularFireUploadTask { 7 | task: UploadTask; 8 | snapshotChanges(): Observable; 9 | percentageChanges(): Observable; 10 | pause(): boolean; 11 | cancel(): boolean; 12 | resume(): boolean; 13 | then( 14 | onFulfilled?: ((a: UploadTaskSnapshot) => any) | null, 15 | onRejected?: ((a: Error) => any) | null 16 | ): Promise; 17 | catch(onRejected: (a: Error) => any): Promise; 18 | } 19 | 20 | /** 21 | * Create an AngularFireUploadTask from a regular UploadTask from the Storage SDK. 22 | * This method creates an observable of the upload and returns on object that provides 23 | * multiple methods for controlling and monitoring the file upload. 24 | */ 25 | export function createUploadTask(task: UploadTask): AngularFireUploadTask { 26 | const inner$ = fromTask(task); 27 | return { 28 | task, 29 | then: task.then.bind(task), 30 | catch: task.catch.bind(task), 31 | pause: task.pause.bind(task), 32 | cancel: task.cancel.bind(task), 33 | resume: task.resume.bind(task), 34 | snapshotChanges: () => inner$, 35 | percentageChanges: () => inner$.pipe( 36 | map(s => s.bytesTransferred / s.totalBytes * 100) 37 | ) 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/data-connect/data-connect.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | import { TestBed } from '@angular/core/testing'; 3 | import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 4 | import { DataConnect, getDataConnect, provideDataConnect } from '@angular/fire/data-connect'; 5 | import { COMMON_CONFIG } from '../test-config'; 6 | import { rando } from '../utils'; 7 | 8 | 9 | describe('DataConnect', () => { 10 | let dataConnect: DataConnect; 11 | let providedDataConnect: DataConnect; 12 | let appName: string; 13 | 14 | describe('single injection', () => { 15 | 16 | beforeEach(() => { 17 | appName = rando(); 18 | TestBed.configureTestingModule({ 19 | providers: [ 20 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 21 | provideDataConnect(() => { 22 | providedDataConnect = getDataConnect(getApp(appName)); 23 | return providedDataConnect; 24 | }), 25 | ], 26 | }); 27 | dataConnect = TestBed.inject(DataConnect); 28 | }); 29 | 30 | it('should be injectable', () => { 31 | expect(providedDataConnect).toBeTruthy(); 32 | expect(dataConnect).toEqual(providedDataConnect); 33 | }); 34 | 35 | }); 36 | 37 | }); 38 | */ -------------------------------------------------------------------------------- /src/data-connect/data-connect.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { DataConnect } from 'firebase/data-connect'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | export { DataConnect }; 7 | 8 | export const DATA_CONNECT_PROVIDER_NAME = 'data-connect'; 9 | 10 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 11 | export interface DataConnectInstances extends Array {} 12 | 13 | export class DataConnectInstances { 14 | constructor() { 15 | return ɵgetAllInstancesOf(DATA_CONNECT_PROVIDER_NAME); 16 | } 17 | } 18 | 19 | export const dataConnectInstance$ = timer(0, 300).pipe( 20 | concatMap(() => from(ɵgetAllInstancesOf(DATA_CONNECT_PROVIDER_NAME))), 21 | distinct(), 22 | ); 23 | -------------------------------------------------------------------------------- /src/data-connect/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/data-connect'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | connectDataConnectEmulator as _connectDataConnectEmulator, 6 | executeMutation as _executeMutation, 7 | executeQuery as _executeQuery, 8 | getDataConnect as _getDataConnect, 9 | mutationRef as _mutationRef, 10 | queryRef as _queryRef, 11 | setLogLevel as _setLogLevel, 12 | subscribe as _subscribe, 13 | terminate as _terminate, 14 | toQueryRef as _toQueryRef 15 | } from 'firebase/data-connect'; 16 | 17 | export const connectDataConnectEmulator = ɵzoneWrap(_connectDataConnectEmulator, true); 18 | export const executeMutation = ɵzoneWrap(_executeMutation, true); 19 | export const executeQuery = ɵzoneWrap(_executeQuery, true); 20 | export const getDataConnect = ɵzoneWrap(_getDataConnect, true); 21 | export const mutationRef = ɵzoneWrap(_mutationRef, true, 2); 22 | export const queryRef = ɵzoneWrap(_queryRef, true, 2); 23 | export const setLogLevel = ɵzoneWrap(_setLogLevel, true); 24 | export const subscribe = ɵzoneWrap(_subscribe, true); 25 | export const terminate = ɵzoneWrap(_terminate, true); 26 | export const toQueryRef = ɵzoneWrap(_toQueryRef, true, 2); 27 | -------------------------------------------------------------------------------- /src/data-connect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/data-connect/overrides.ts: -------------------------------------------------------------------------------- 1 | import { isMessagingSupportedFactory } from './is-messaging-supported-factory'; 2 | 3 | export const isSupported = isMessagingSupportedFactory.async; 4 | -------------------------------------------------------------------------------- /src/data-connect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/data-connect/public_api.ts: -------------------------------------------------------------------------------- 1 | export { DataConnectInstances, DataConnect, dataConnectInstance$ } from './data-connect'; 2 | export { provideDataConnect, DataConnectModule } from './data-connect.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/database/database.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Database, connectDatabaseEmulator, getDatabase, provideDatabase } from '@angular/fire/database'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Database', () => { 8 | let app: FirebaseApp; 9 | let database: Database; 10 | let providedDatabase: Database; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideDatabase(() => { 21 | providedDatabase = getDatabase(getApp(appName)); 22 | connectDatabaseEmulator(providedDatabase, 'localhost', 9002); 23 | return providedDatabase; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | database = TestBed.inject(Database); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedDatabase).toBeTruthy(); 33 | expect(database).toEqual(providedDatabase); 34 | expect(database.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/database/database.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Database as FirebaseDatabase } from 'firebase/database'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Database extends FirebaseDatabase {} 9 | 10 | export class Database { 11 | constructor(database: FirebaseDatabase) { 12 | return database; 13 | } 14 | } 15 | 16 | export const DATABASE_PROVIDER_NAME = 'database'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface DatabaseInstances extends Array {} 20 | 21 | export class DatabaseInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(DATABASE_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const databaseInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(DATABASE_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/database/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/database/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/database/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Database, DatabaseInstances, databaseInstance$ } from './database'; 2 | export { provideDatabase, DatabaseModule } from './database.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/database/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | auditTrail as _auditTrail, 5 | changeToData as _changeToData, 6 | fromRef as _fromRef, 7 | list as _list, 8 | listVal as _listVal, 9 | object as _object, 10 | objectVal as _objectVal, 11 | stateChanges as _stateChanges 12 | } from 'rxfire/database'; 13 | 14 | export { 15 | ListenEvent, 16 | ListenerMethods 17 | } from 'rxfire/database'; 18 | 19 | export const auditTrail = ɵzoneWrap(_auditTrail, true); 20 | export const changeToData = ɵzoneWrap(_changeToData, true); 21 | export const fromRef = ɵzoneWrap(_fromRef, true); 22 | export const list = ɵzoneWrap(_list, true); 23 | export const listVal = ɵzoneWrap(_listVal, true); 24 | export const object = ɵzoneWrap(_object, true); 25 | export const objectVal = ɵzoneWrap(_objectVal, true); 26 | export const stateChanges = ɵzoneWrap(_stateChanges, true); 27 | -------------------------------------------------------------------------------- /src/firestore/firestore.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Firestore, connectFirestoreEmulator, getFirestore, provideFirestore } from '@angular/fire/firestore'; 4 | import { COMMON_CONFIG, firestoreEmulatorPort } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Firestore', () => { 8 | let app: FirebaseApp; 9 | let firestore: Firestore; 10 | let providedFirestore: Firestore; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideFirestore(() => { 21 | providedFirestore = getFirestore(getApp(appName)); 22 | connectFirestoreEmulator(providedFirestore, 'localhost', firestoreEmulatorPort); 23 | return providedFirestore; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | firestore = TestBed.inject(Firestore); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedFirestore).toBeTruthy(); 33 | expect(firestore).toEqual(providedFirestore); 34 | expect(firestore.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/firestore/firestore.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Firestore as FirebaseFirestore } from 'firebase/firestore'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Firestore extends FirebaseFirestore {} 9 | 10 | export class Firestore { 11 | constructor(firestore: FirebaseFirestore) { 12 | return firestore; 13 | } 14 | } 15 | 16 | export const FIRESTORE_PROVIDER_NAME = 'firestore'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface FirestoreInstances extends Array {} 20 | 21 | export class FirestoreInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(FIRESTORE_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const firestoreInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(FIRESTORE_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/firestore/lite/lite.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Firestore, connectFirestoreEmulator, getFirestore, provideFirestore } from '@angular/fire/firestore/lite'; 4 | import { COMMON_CONFIG, firestoreEmulatorPort } from '../../test-config'; 5 | import { rando } from '../../utils'; 6 | 7 | describe('Firestore-lite', () => { 8 | let app: FirebaseApp; 9 | let firestore: Firestore; 10 | let providedFirestore: Firestore; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideFirestore(() => { 21 | providedFirestore = getFirestore(getApp(appName)); 22 | connectFirestoreEmulator(providedFirestore, 'localhost', firestoreEmulatorPort); 23 | return providedFirestore; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | firestore = TestBed.inject(Firestore); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedFirestore).toBeTruthy(); 33 | expect(firestore).toEqual(providedFirestore); 34 | expect(firestore.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/firestore/lite/lite.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Firestore as FirebaseFirestore } from 'firebase/firestore/lite'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Firestore extends FirebaseFirestore {} 9 | 10 | export class Firestore { 11 | constructor(firestore: FirebaseFirestore) { 12 | return firestore; 13 | } 14 | } 15 | 16 | export const FIRESTORE_PROVIDER_NAME = 'firestore/lite'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface FirestoreInstances extends Array {} 20 | 21 | export class FirestoreInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(FIRESTORE_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const firestoreInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(FIRESTORE_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/firestore/lite/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/firestore/lite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/firestore/lite/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Firestore, FirestoreInstances, firestoreInstance$ } from './lite'; 2 | export { FirestoreModule, provideFirestore } from './lite.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/firestore/lite/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | collection as _collection, 5 | collectionCount as _collectionCount, 6 | collectionCountSnap as _collectionCountSnap, 7 | collectionData as _collectionData, 8 | doc as _doc, 9 | docData as _docData, 10 | fromRef as _fromRef, 11 | snapToData as _snapToData 12 | } from 'rxfire/firestore/lite'; 13 | 14 | export const collectionSnapshots = ɵzoneWrap(_collection, true); 15 | export const collectionCount = ɵzoneWrap(_collectionCount, true); 16 | export const collectionCountSnap = ɵzoneWrap(_collectionCountSnap, true); 17 | export const collectionData = ɵzoneWrap(_collectionData, true); 18 | export const docSnapshots = ɵzoneWrap(_doc, true); 19 | export const docData = ɵzoneWrap(_docData, true); 20 | export const fromRef = ɵzoneWrap(_fromRef, true); 21 | export const snapToData = ɵzoneWrap(_snapToData, true); 22 | -------------------------------------------------------------------------------- /src/firestore/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/firestore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/firestore/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Firestore, FirestoreInstances, firestoreInstance$ } from './firestore'; 2 | export { provideFirestore, FirestoreModule } from './firestore.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/firestore/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | auditTrail as _auditTrail, 5 | collection as _collection, 6 | collectionChanges as _collectionChanges, 7 | collectionCount as _collectionCount, 8 | collectionCountSnap as _collectionCountSnap, 9 | collectionData as _collectionData, 10 | doc as _doc, 11 | docData as _docData, 12 | fromRef as _fromRef, 13 | snapToData as _snapToData, 14 | sortedChanges as _sortedChanges 15 | } from 'rxfire/firestore'; 16 | 17 | export const auditTrail = ɵzoneWrap(_auditTrail, true); 18 | export const collectionSnapshots = ɵzoneWrap(_collection, true); 19 | export const collectionChanges = ɵzoneWrap(_collectionChanges, true); 20 | export const collectionCount = ɵzoneWrap(_collectionCount, true); 21 | export const collectionCountSnap = ɵzoneWrap(_collectionCountSnap, true); 22 | export const collectionData = ɵzoneWrap(_collectionData, true); 23 | export const docSnapshots = ɵzoneWrap(_doc, true); 24 | export const docData = ɵzoneWrap(_docData, true); 25 | export const fromRef = ɵzoneWrap(_fromRef, true); 26 | export const snapToData = ɵzoneWrap(_snapToData, true); 27 | export const sortedChanges = ɵzoneWrap(_sortedChanges, true); 28 | -------------------------------------------------------------------------------- /src/functions/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/functions'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | connectFunctionsEmulator as _connectFunctionsEmulator, 6 | getFunctions as _getFunctions, 7 | httpsCallable as _httpsCallable, 8 | httpsCallableFromURL as _httpsCallableFromURL 9 | } from 'firebase/functions'; 10 | 11 | export const connectFunctionsEmulator = ɵzoneWrap(_connectFunctionsEmulator, true); 12 | export const getFunctions = ɵzoneWrap(_getFunctions, true); 13 | export const httpsCallable = ɵzoneWrap(_httpsCallable, true); 14 | export const httpsCallableFromURL = ɵzoneWrap(_httpsCallableFromURL, true); 15 | -------------------------------------------------------------------------------- /src/functions/functions.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Functions, connectFunctionsEmulator, getFunctions, provideFunctions } from '@angular/fire/functions'; 4 | import { COMMON_CONFIG, functionsEmulatorPort } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Functions', () => { 8 | let app: FirebaseApp; 9 | let functions: Functions; 10 | let providedFunctions: Functions; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideFunctions(() => { 21 | providedFunctions = getFunctions(getApp(appName)); 22 | connectFunctionsEmulator(providedFunctions, 'localhost', functionsEmulatorPort); 23 | return providedFunctions; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | functions = TestBed.inject(Functions); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedFunctions).toBeTruthy(); 33 | expect(functions).toEqual(providedFunctions); 34 | expect(functions.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/functions/functions.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Functions as FirebaseFunctions } from 'firebase/functions'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Functions extends FirebaseFunctions {} 9 | 10 | export class Functions { 11 | constructor(functions: FirebaseFunctions) { 12 | return functions; 13 | } 14 | } 15 | 16 | export const FUNCTIONS_PROVIDER_NAME = 'functions'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface FunctionsInstances extends Array {} 20 | 21 | export class FunctionsInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(FUNCTIONS_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const functionInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(FUNCTIONS_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/functions/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/functions/public_api.ts: -------------------------------------------------------------------------------- 1 | export { provideFunctions, FunctionsModule } from './functions.module'; 2 | export { Functions, FunctionsInstances, functionInstance$ } from './functions'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/functions/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | httpsCallable as _httpsCallable 5 | } from 'rxfire/functions'; 6 | 7 | export const httpsCallableData = ɵzoneWrap(_httpsCallable, true); 8 | -------------------------------------------------------------------------------- /src/messaging/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/messaging'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | deleteToken as _deleteToken, 6 | getMessaging as _getMessaging, 7 | getToken as _getToken, 8 | isSupported as _isSupported, 9 | onMessage as _onMessage 10 | } from 'firebase/messaging'; 11 | 12 | export const deleteToken = ɵzoneWrap(_deleteToken, true, 2); 13 | export const getMessaging = ɵzoneWrap(_getMessaging, true); 14 | export const getToken = ɵzoneWrap(_getToken, true); 15 | export const isSupported = ɵzoneWrap(_isSupported, false); 16 | export const onMessage = ɵzoneWrap(_onMessage, false); 17 | -------------------------------------------------------------------------------- /src/messaging/messaging.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Messaging, getMessaging, isSupported, provideMessaging } from '@angular/fire/messaging'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Messaging', () => { 8 | let messaging: Messaging; 9 | let providedMessaging: Messaging; 10 | let appName: string; 11 | 12 | describe('single injection', () => { 13 | 14 | beforeEach(() => { 15 | appName = rando(); 16 | TestBed.configureTestingModule({ 17 | providers: [ 18 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 19 | provideMessaging(() => { 20 | providedMessaging = getMessaging(getApp(appName)); 21 | return providedMessaging; 22 | }), 23 | ], 24 | }); 25 | messaging = TestBed.inject(Messaging); 26 | }); 27 | 28 | it('should be injectable', async () => { 29 | const supported = await TestBed.runInInjectionContext(isSupported); 30 | if (supported) { 31 | expect(providedMessaging).toBeTruthy(); 32 | expect(messaging).toEqual(providedMessaging); 33 | } else { 34 | expect(providedMessaging).toBeUndefined(); 35 | expect(messaging).toBeNull(); 36 | } 37 | }); 38 | 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /src/messaging/messaging.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { Messaging as FirebaseMessaging } from 'firebase/messaging'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Messaging extends FirebaseMessaging {} 9 | 10 | export class Messaging { 11 | constructor(messaging: FirebaseMessaging) { 12 | return messaging; 13 | } 14 | } 15 | 16 | export const MESSAGING_PROVIDER_NAME = 'messaging'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface MessagingInstances extends Array {} 20 | 21 | export class MessagingInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(MESSAGING_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const messagingInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(MESSAGING_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/messaging/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/messaging/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/messaging/public_api.ts: -------------------------------------------------------------------------------- 1 | export { MessagingInstances, Messaging, messagingInstance$ } from './messaging'; 2 | export { provideMessaging, MessagingModule } from './messaging.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | }, 6 | "dest": "../dist/packages-dist", 7 | "allowedNonPeerDependencies": [ 8 | "@angular-devkit/schematics", "@schematics/angular", 9 | "fuzzy", "inquirer-autocomplete-prompt", 10 | "open", "jsonc-parser", "ora", "winston", 11 | "triple-beam", "@schematics/angular", "node-fetch", 12 | "semver", "inquirer", "fs-extra", 13 | "firebase", "rxfire" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../node_modules/ng-packagr/package.schema.json", 3 | "name": "@angular/fire", 4 | "version": "ANGULARFIRE2_VERSION", 5 | "description": "Angular + Firebase = ❤️", 6 | "schematics": "./schematics/collection.json", 7 | "builders": "./schematics/builders.json", 8 | "keywords": [ 9 | "angular", 10 | "firebase", 11 | "rxjs", 12 | "angularfire", 13 | "angularfire2" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/angular/angularfire.git" 18 | }, 19 | "bugs": { 20 | "url": "https://github.com/angular/angularfire/issues" 21 | }, 22 | "homepage": "https://github.com/angular/angularfire#readme", 23 | "author": "angular,firebase", 24 | "license": "MIT", 25 | "peerDependencies": { 26 | "@angular/common": "^20.0.0", 27 | "@angular/core": "^20.0.0", 28 | "@angular/platform-browser": "^20.0.0", 29 | "@angular/platform-browser-dynamic": "^20.0.0", 30 | "@angular/platform-server": "^20.0.0", 31 | "rxjs": "~7.8.0", 32 | "firebase-tools": "^14.0.0" 33 | }, 34 | "peerDependenciesMeta": { 35 | "firebase-tools": { "optional": true }, 36 | "@angular/platform-server": { "optional": true } 37 | }, 38 | "dependencies": { 39 | "firebase": "^11.8.0", 40 | "rxfire": "^6.1.0", 41 | "@angular-devkit/schematics": "^20.0.0", 42 | "@schematics/angular": "^20.0.0", 43 | "tslib": "^2.3.0" 44 | }, 45 | "ng-update": { 46 | "migrations": "./schematics/migration.json" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/performance/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/performance'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | getPerformance as _getPerformance, 6 | initializePerformance as _initializePerformance, 7 | trace as _trace 8 | } from 'firebase/performance'; 9 | 10 | export const getPerformance = ɵzoneWrap(_getPerformance, true); 11 | export const initializePerformance = ɵzoneWrap(_initializePerformance, true); 12 | export const trace = ɵzoneWrap(_trace, true, 2); 13 | -------------------------------------------------------------------------------- /src/performance/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/performance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/performance/performance.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Performance, getPerformance, providePerformance } from '@angular/fire/performance'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | 6 | describe('Performance', () => { 7 | let app: FirebaseApp; 8 | let performance: Performance; 9 | let providedPerformance: Performance; 10 | 11 | describe('single injection', () => { 12 | 13 | beforeEach(() => { 14 | TestBed.configureTestingModule({ 15 | providers: [ 16 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG)), 17 | providePerformance(() => { 18 | providedPerformance = getPerformance(); 19 | return providedPerformance; 20 | }), 21 | ], 22 | }); 23 | app = TestBed.inject(FirebaseApp); 24 | performance = TestBed.inject(Performance); 25 | }); 26 | 27 | it('should be injectable', () => { 28 | expect(providedPerformance).toBeTruthy(); 29 | expect(performance).toEqual(providedPerformance); 30 | expect(performance.app).toEqual(app); 31 | }); 32 | 33 | }); 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /src/performance/performance.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { FirebasePerformance } from 'firebase/performance'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Performance extends FirebasePerformance {} 9 | 10 | export class Performance { 11 | constructor(performance: FirebasePerformance) { 12 | return performance; 13 | } 14 | } 15 | 16 | export const PERFORMANCE_PROVIDER_NAME = 'performance'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface PerformanceInstances extends Array {} 20 | 21 | export class PerformanceInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(PERFORMANCE_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const performanceInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(PERFORMANCE_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/performance/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Performance, PerformanceInstances, performanceInstance$ } from './performance'; 2 | export { providePerformance, PerformanceModule } from './performance.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/performance/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | traceUntil as _traceUntil, 5 | traceUntilComplete as _traceUntilComplete, 6 | traceUntilFirst as _traceUntilFirst, 7 | traceWhile as _traceWhile 8 | } from 'rxfire/performance'; 9 | 10 | export const traceUntil = ɵzoneWrap(_traceUntil, true); 11 | export const traceUntilComplete = ɵzoneWrap(_traceUntilComplete, true); 12 | export const traceUntilFirst = ɵzoneWrap(_traceUntilFirst, true); 13 | export const traceWhile = ɵzoneWrap(_traceWhile, true); 14 | -------------------------------------------------------------------------------- /src/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './core'; 2 | export * from './zones'; 3 | -------------------------------------------------------------------------------- /src/remote-config/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/remote-config'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | activate as _activate, 6 | ensureInitialized as _ensureInitialized, 7 | fetchAndActivate as _fetchAndActivate, 8 | fetchConfig as _fetchConfig, 9 | getAll as _getAll, 10 | getBoolean as _getBoolean, 11 | getNumber as _getNumber, 12 | getRemoteConfig as _getRemoteConfig, 13 | getString as _getString, 14 | getValue as _getValue, 15 | isSupported as _isSupported, 16 | setCustomSignals as _setCustomSignals, 17 | setLogLevel as _setLogLevel 18 | } from 'firebase/remote-config'; 19 | 20 | export const activate = ɵzoneWrap(_activate, true); 21 | export const ensureInitialized = ɵzoneWrap(_ensureInitialized, true); 22 | export const fetchAndActivate = ɵzoneWrap(_fetchAndActivate, true); 23 | export const fetchConfig = ɵzoneWrap(_fetchConfig, true); 24 | export const getAll = ɵzoneWrap(_getAll, true); 25 | export const getBoolean = ɵzoneWrap(_getBoolean, true); 26 | export const getNumber = ɵzoneWrap(_getNumber, true); 27 | export const getRemoteConfig = ɵzoneWrap(_getRemoteConfig, true); 28 | export const getString = ɵzoneWrap(_getString, true); 29 | export const getValue = ɵzoneWrap(_getValue, true); 30 | export const isSupported = ɵzoneWrap(_isSupported, true); 31 | export const setCustomSignals = ɵzoneWrap(_setCustomSignals, true); 32 | export const setLogLevel = ɵzoneWrap(_setLogLevel, true); 33 | -------------------------------------------------------------------------------- /src/remote-config/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/remote-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/remote-config/public_api.ts: -------------------------------------------------------------------------------- 1 | export { RemoteConfigInstances, RemoteConfig, remoteConfigInstance$ } from './remote-config'; 2 | export { provideRemoteConfig, RemoteConfigModule } from './remote-config.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/remote-config/remote-config.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { RemoteConfig, getRemoteConfig, provideRemoteConfig } from '@angular/fire/remote-config'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('RemoteConfig', () => { 8 | let app: FirebaseApp; 9 | let remoteConfig: RemoteConfig; 10 | let providedRemoteConfig: RemoteConfig; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideRemoteConfig(() => { 21 | providedRemoteConfig = getRemoteConfig(getApp(appName)); 22 | return providedRemoteConfig; 23 | }), 24 | ], 25 | }); 26 | app = TestBed.inject(FirebaseApp); 27 | remoteConfig = TestBed.inject(RemoteConfig); 28 | }); 29 | 30 | it('should be injectable', () => { 31 | expect(providedRemoteConfig).toBeTruthy(); 32 | expect(remoteConfig).toEqual(providedRemoteConfig); 33 | expect(remoteConfig.app).toEqual(app); 34 | }); 35 | 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /src/remote-config/remote-config.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { RemoteConfig as FirebaseRemoteConfig } from 'firebase/remote-config'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface RemoteConfig extends FirebaseRemoteConfig {} 9 | 10 | export class RemoteConfig { 11 | constructor(remoteConfig: FirebaseRemoteConfig) { 12 | return remoteConfig; 13 | } 14 | } 15 | 16 | export const REMOTE_CONFIG_PROVIDER_NAME = 'remote-config'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface RemoteConfigInstances extends Array {} 20 | 21 | export class RemoteConfigInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(REMOTE_CONFIG_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const remoteConfigInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(REMOTE_CONFIG_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/remote-config/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | getAll as _getAll, 5 | getBoolean as _getBoolean, 6 | getNumber as _getNumber, 7 | getString as _getString, 8 | getValue as _getValue 9 | } from 'rxfire/remote-config'; 10 | 11 | export const getAllChanges = ɵzoneWrap(_getAll, true); 12 | export const getBooleanChanges = ɵzoneWrap(_getBoolean, true); 13 | export const getNumberChanges = ɵzoneWrap(_getNumber, true); 14 | export const getStringChanges = ɵzoneWrap(_getString, true); 15 | export const getValueChanges = ɵzoneWrap(_getValue, true); 16 | -------------------------------------------------------------------------------- /src/schematics/add/index.ts: -------------------------------------------------------------------------------- 1 | import { SchematicContext, Tree } from '@angular-devkit/schematics'; 2 | import { NodePackageInstallTask, RunSchematicTask } from '@angular-devkit/schematics/tasks'; 3 | import { addDependencies } from '../common'; 4 | import { DeployOptions } from '../interfaces'; 5 | import { peerDependencies } from '../versions.json'; 6 | 7 | export const ngAdd = (options: DeployOptions) => (tree: Tree, context: SchematicContext) => { 8 | addDependencies( 9 | tree, 10 | peerDependencies, 11 | context 12 | ); 13 | const npmInstallTaskId = context.addTask(new NodePackageInstallTask()); 14 | context.addTask(new RunSchematicTask('ng-add-setup-project', options), [npmInstallTaskId]); 15 | return tree; 16 | }; 17 | -------------------------------------------------------------------------------- /src/schematics/add/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "$id": "angular-fire-ng-add", 4 | "title": "AngularFire ng-add", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "description": "The name of the project.", 10 | "$default": { 11 | "$source": "projectName" 12 | } 13 | } 14 | }, 15 | "required": [] 16 | } 17 | -------------------------------------------------------------------------------- /src/schematics/builders.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "builders": { 4 | "deploy": { 5 | "implementation": "./deploy/builder", 6 | "schema": "./deploy/schema.json", 7 | "description": "Deploy builder" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/schematics/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "ng-add": { 5 | "description": "Add firebase deploy schematic", 6 | "factory": "./add#ngAdd", 7 | "schema": "./add/schema.json" 8 | }, 9 | "ng-add-setup-project": { 10 | "description": "Setup ng deploy", 11 | "factory": "./setup#ngAddSetupProject", 12 | "schema": "./setup/schema.json" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/schematics/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "migration-v7": { 5 | "version": "7.0.0", 6 | "description": "Update @angular/fire to v7", 7 | "factory": "./update/v7#ngUpdate" 8 | }, 9 | "ng-post-upgate": { 10 | "description": "Print out results after ng-update", 11 | "factory": "./update#ngPostUpdate", 12 | "private": true 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/schematics/setup/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "$id": "angular-fire-ng-add", 4 | "title": "AngularFire ng-add", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "description": "The name of the project.", 10 | "$default": { 11 | "$source": "projectName" 12 | } 13 | } 14 | }, 15 | "required": [] 16 | } 17 | -------------------------------------------------------------------------------- /src/schematics/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "sourceMap": false, 5 | "inlineSources": false, 6 | "declaration": false, 7 | "removeComments": true, 8 | "strictNullChecks": true, 9 | "resolveJsonModule": true, 10 | "esModuleInterop": true, 11 | "lib": [ 12 | "es2015", 13 | "dom", 14 | "es2015.promise", 15 | "es2015.collection", 16 | "es2015.iterable" 17 | ], 18 | "skipLibCheck": true, 19 | "moduleResolution": "node", 20 | "target": "es2018", 21 | "module": "commonjs", 22 | "outDir": "../../dist/packages-dist/schematics" 23 | }, 24 | "files": [ 25 | "update/index.ts", 26 | "deploy/actions.ts", 27 | "deploy/builder.ts", 28 | "add/index.ts", 29 | "setup/index.ts", 30 | "update/v7/index.ts", 31 | ] 32 | } -------------------------------------------------------------------------------- /src/schematics/update/index.ts: -------------------------------------------------------------------------------- 1 | import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; 2 | 3 | export const ngPostUpdate = (): Rule => ( 4 | host: Tree, 5 | _context: SchematicContext 6 | ) => { 7 | return host; 8 | }; 9 | -------------------------------------------------------------------------------- /src/schematics/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "peerDependencies": { 3 | }, 4 | "firebaseFunctionsDependencies": { 5 | "firebase-admin": { "dev": false, "version": "0.0.0" }, 6 | "firebase-functions": { "dev": false, "version": "0.0.0" } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/storage/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/storage'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | connectStorageEmulator as _connectStorageEmulator, 6 | deleteObject as _deleteObject, 7 | getBlob as _getBlob, 8 | getBytes as _getBytes, 9 | getDownloadURL as _getDownloadURL, 10 | getMetadata as _getMetadata, 11 | getStorage as _getStorage, 12 | getStream as _getStream, 13 | list as _list, 14 | listAll as _listAll, 15 | ref as _ref, 16 | updateMetadata as _updateMetadata, 17 | uploadBytes as _uploadBytes, 18 | uploadBytesResumable as _uploadBytesResumable, 19 | uploadString as _uploadString 20 | } from 'firebase/storage'; 21 | 22 | export const connectStorageEmulator = ɵzoneWrap(_connectStorageEmulator, true); 23 | export const deleteObject = ɵzoneWrap(_deleteObject, true, 2); 24 | export const getBlob = ɵzoneWrap(_getBlob, true); 25 | export const getBytes = ɵzoneWrap(_getBytes, true); 26 | export const getDownloadURL = ɵzoneWrap(_getDownloadURL, true); 27 | export const getMetadata = ɵzoneWrap(_getMetadata, true); 28 | export const getStorage = ɵzoneWrap(_getStorage, true); 29 | export const getStream = ɵzoneWrap(_getStream, true); 30 | export const list = ɵzoneWrap(_list, true); 31 | export const listAll = ɵzoneWrap(_listAll, true); 32 | export const ref = ɵzoneWrap(_ref, true, 2); 33 | export const updateMetadata = ɵzoneWrap(_updateMetadata, true, 2); 34 | export const uploadBytes = ɵzoneWrap(_uploadBytes, true); 35 | export const uploadBytesResumable = ɵzoneWrap(_uploadBytesResumable, true); 36 | export const uploadString = ɵzoneWrap(_uploadString, true); 37 | -------------------------------------------------------------------------------- /src/storage/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/storage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/storage/public_api.ts: -------------------------------------------------------------------------------- 1 | export { Storage, StorageInstances, storageInstance$ } from './storage'; 2 | export { provideStorage, StorageModule } from './storage.module'; 3 | export * from './rxfire'; 4 | export * from './firebase'; 5 | -------------------------------------------------------------------------------- /src/storage/rxfire.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | import { ɵzoneWrap } from '@angular/fire'; 3 | import { 4 | fromTask as _fromTask, 5 | percentage as _percentage 6 | } from 'rxfire/storage'; 7 | 8 | export const fromTask = ɵzoneWrap(_fromTask, true); 9 | export const percentage = ɵzoneWrap(_percentage, true); 10 | -------------------------------------------------------------------------------- /src/storage/storage.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { Storage, connectStorageEmulator, getStorage, provideStorage } from '@angular/fire/storage'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('Storage', () => { 8 | let app: FirebaseApp; 9 | let storage: Storage; 10 | let providedStorage: Storage; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideStorage(() => { 21 | providedStorage = getStorage(getApp(appName)); 22 | connectStorageEmulator(providedStorage, 'localhost', 9199); 23 | return providedStorage; 24 | }), 25 | ], 26 | }); 27 | app = TestBed.inject(FirebaseApp); 28 | storage = TestBed.inject(Storage); 29 | }); 30 | 31 | it('should be injectable', () => { 32 | expect(providedStorage).toBeTruthy(); 33 | expect(storage).toEqual(providedStorage); 34 | expect(storage.app).toEqual(app); 35 | }); 36 | 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /src/storage/storage.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { FirebaseStorage } from 'firebase/storage'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface Storage extends FirebaseStorage {} 9 | 10 | export class Storage { 11 | constructor(auth: FirebaseStorage) { 12 | return auth; 13 | } 14 | } 15 | 16 | export const STORAGE_PROVIDER_NAME = 'storage'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface StorageInstances extends Array {} 20 | 21 | export class StorageInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(STORAGE_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const storageInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(STORAGE_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /src/test-config.ts: -------------------------------------------------------------------------------- 1 | export const COMMON_CONFIG = { 2 | apiKey: 'AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA', 3 | authDomain: 'angularfire2-test.firebaseapp.com', 4 | databaseURL: 'https://angularfire2-test.firebaseio.com', 5 | projectId: 'angularfire2-test', 6 | storageBucket: 'angularfire2-test.appspot.com', 7 | messagingSenderId: '920323787688', 8 | appId: '1:920323787688:web:2253a0e5eb5b9a8b', 9 | databaseName: 'angularfire2-test', 10 | measurementId: 'G-W20QDV5CZP' 11 | }; 12 | 13 | export const COMMON_CONFIG_TOO = { 14 | apiKey: 'AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA', 15 | authDomain: 'angularfire2-test.firebaseapp.com', 16 | databaseURL: 'https://angularfire2-test.firebaseio.com', 17 | projectId: 'angularfire2-test', 18 | storageBucket: 'angularfire2-test.appspot.com', 19 | messagingSenderId: '920323787688', 20 | appId: '1:920323787688:web:2253a0e5eb5b9a8d', 21 | databaseName: 'angularfire2-test', 22 | measurementId: 'G-W20QDV5CZZ' 23 | }; 24 | 25 | declare global { 26 | interface Window { 27 | __karma__ : { 28 | config: { 29 | args: any[] 30 | } 31 | }; 32 | } 33 | } 34 | 35 | export const firestoreEmulatorPort: number = window.__karma__.config.args.find((it) => it[0] === "FIRESTORE_EMULATOR_PORT")[1]; 36 | export const storageEmulatorPort: number = window.__karma__.config.args.find((it) => it[0] === "STORAGE_EMULATOR_PORT")[1]; 37 | export const authEmulatorPort: number = window.__karma__.config.args.find((it) => it[0] === "AUTH_EMULATOR_PORT")[1]; 38 | export const databaseEmulatorPort: number = window.__karma__.config.args.find((it) => it[0] === "DATABASE_EMULATOR_PORT")[1]; 39 | export const functionsEmulatorPort: number = window.__karma__.config.args.find((it) => it[0] === "FUNCTIONS_EMULATOR_PORT")[1]; 40 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone'; 4 | import 'zone.js/dist/zone-testing'; 5 | import 'zone.js/dist/task-tracking'; 6 | 7 | import { getTestBed } from '@angular/core/testing'; 8 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /^\.\/.+\.spec\.ts$/); 19 | 20 | // And load the modules. 21 | context.keys().map(context); 22 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | const randomString = () => (Math.random() + 1).toString(36).split('.')[1]; 2 | 3 | export const rando = () => [randomString(), randomString(), randomString()].join(''); 4 | -------------------------------------------------------------------------------- /src/vertexai/firebase.ts: -------------------------------------------------------------------------------- 1 | // DO NOT MODIFY, this file is autogenerated by tools/build.ts 2 | export * from 'firebase/vertexai'; 3 | import { ɵzoneWrap } from '@angular/fire'; 4 | import { 5 | getAI as _getAI, 6 | getGenerativeModel as _getGenerativeModel, 7 | getImagenModel as _getImagenModel, 8 | getVertexAI as _getVertexAI 9 | } from 'firebase/vertexai'; 10 | 11 | export const getAI = ɵzoneWrap(_getAI, true); 12 | export const getGenerativeModel = ɵzoneWrap(_getGenerativeModel, true); 13 | export const getImagenModel = ɵzoneWrap(_getImagenModel, true); 14 | export const getVertexAI = ɵzoneWrap(_getVertexAI, true); 15 | -------------------------------------------------------------------------------- /src/vertexai/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "public_api.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/vertexai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/package.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/vertexai/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VertexAI, VertexAIInstances, vertexAIInstance$ } from './vertexai'; 2 | export { provideVertexAI, VertexAIModule } from './vertexai.module'; 3 | export * from './firebase'; 4 | -------------------------------------------------------------------------------- /src/vertexai/vertexai.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { FirebaseApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app'; 3 | import { VertexAI, getVertexAI, provideVertexAI } from '@angular/fire/vertexai'; 4 | import { COMMON_CONFIG } from '../test-config'; 5 | import { rando } from '../utils'; 6 | 7 | describe('VertexAI', () => { 8 | let app: FirebaseApp; 9 | let vertexAI: VertexAI; 10 | let providedVertexAI: VertexAI; 11 | let appName: string; 12 | 13 | describe('single injection', () => { 14 | 15 | beforeEach(() => { 16 | appName = rando(); 17 | TestBed.configureTestingModule({ 18 | providers: [ 19 | provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)), 20 | provideVertexAI(() => { 21 | providedVertexAI = getVertexAI(getApp(appName)); 22 | return providedVertexAI; 23 | }), 24 | ], 25 | }); 26 | app = TestBed.inject(FirebaseApp); 27 | vertexAI = TestBed.inject(VertexAI); 28 | }); 29 | 30 | it('should be injectable', () => { 31 | expect(providedVertexAI).toBeTruthy(); 32 | expect(vertexAI).toEqual(providedVertexAI); 33 | expect(vertexAI.app).toEqual(app); 34 | }); 35 | 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /src/vertexai/vertexai.ts: -------------------------------------------------------------------------------- 1 | import { ɵgetAllInstancesOf } from '@angular/fire'; 2 | import { VertexAI as FirebaseVertexAI } from 'firebase/vertexai'; 3 | import { from, timer } from 'rxjs'; 4 | import { concatMap, distinct } from 'rxjs/operators'; 5 | 6 | // see notes in core/firebase.app.module.ts for why we're building the class like this 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface VertexAI extends FirebaseVertexAI {} 9 | 10 | export class VertexAI { 11 | constructor(vertexai: FirebaseVertexAI) { 12 | return vertexai; 13 | } 14 | } 15 | 16 | export const VERTEX_AI_PROVIDER_NAME = 'vertexai'; 17 | 18 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 19 | export interface VertexAIInstances extends Array {} 20 | 21 | export class VertexAIInstances { 22 | constructor() { 23 | return ɵgetAllInstancesOf(VERTEX_AI_PROVIDER_NAME); 24 | } 25 | } 26 | 27 | export const vertexAIInstance$ = timer(0, 300).pipe( 28 | concatMap(() => from(ɵgetAllInstancesOf(VERTEX_AI_PROVIDER_NAME))), 29 | distinct(), 30 | ); 31 | -------------------------------------------------------------------------------- /test/database.rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | ".read": true, 4 | ".write": true, 5 | ".indexOn": [ 6 | "height", 7 | ".value" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/firestore.indexes.json: -------------------------------------------------------------------------------- 1 | { 2 | "indexes": [], 3 | "fieldOverrides": [] 4 | } 5 | -------------------------------------------------------------------------------- /test/firestore.rules: -------------------------------------------------------------------------------- 1 | service cloud.firestore { 2 | match /databases/{database}/documents { 3 | match /{document=**} { 4 | allow read, write: if true; 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /test/functions/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled JavaScript files 2 | lib/**/*.js 3 | lib/**/*.js.map 4 | 5 | # TypeScript v1 declaration files 6 | typings/ 7 | 8 | # Node.js dependency directory 9 | node_modules/ 10 | *.local -------------------------------------------------------------------------------- /test/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "scripts": { 4 | "build": "tsc", 5 | "build:watch": "tsc --watch", 6 | "serve": "npm run build && firebase emulators:start --only functions", 7 | "shell": "npm run build && firebase functions:shell", 8 | "start": "npm run shell", 9 | "deploy": "firebase deploy --only functions", 10 | "logs": "firebase functions:log" 11 | }, 12 | "engines": { 13 | "node": "18" 14 | }, 15 | "main": "lib/index.js", 16 | "dependencies": { 17 | "firebase-admin": "^12.6.0", 18 | "firebase-functions": "^6.0.1" 19 | }, 20 | "devDependencies": { 21 | "typescript": "^4.9.0", 22 | "firebase-functions-test": "^3.1.0" 23 | }, 24 | "private": true 25 | } -------------------------------------------------------------------------------- /test/functions/src/index.ts: -------------------------------------------------------------------------------- 1 | import { onCall } from "firebase-functions/v2/https"; 2 | 3 | export const foo = onCall(() => { 4 | return { bar: "baz" }; 5 | }); 6 | -------------------------------------------------------------------------------- /test/functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitReturns": true, 5 | "noUnusedLocals": true, 6 | "outDir": "lib", 7 | "sourceMap": true, 8 | "strict": true, 9 | "target": "es2017" 10 | }, 11 | "compileOnSave": true, 12 | "include": [ 13 | "src" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /test/storage.rules: -------------------------------------------------------------------------------- 1 | rules_version = '2'; 2 | service firebase.storage { 3 | match /b/{bucket}/o { 4 | match /{allPaths=**} { 5 | allow read, write: if true; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tools/build.sh: -------------------------------------------------------------------------------- 1 | SHORT_SHA=$(git rev-parse --short $GITHUB_SHA) 2 | TAG_TEST="^refs/tags/.+$" 3 | LATEST_TEST="^[^-]*$" 4 | 5 | if [[ $GITHUB_REF =~ $TAG_TEST ]]; then 6 | OVERRIDE_VERSION=${GITHUB_REF/refs\/tags\//} 7 | if [[ $OVERRIDE_VERSION =~ $LATEST_TEST ]]; then 8 | NPM_TAG=latest 9 | else 10 | NPM_TAG=next 11 | fi; 12 | else 13 | OVERRIDE_VERSION=$(node -e "console.log(require('./package.json').version)")-canary.$SHORT_SHA 14 | NPM_TAG=canary 15 | fi; 16 | 17 | npm --no-git-tag-version --allow-same-version -f version $OVERRIDE_VERSION 18 | 19 | npm run build && 20 | echo "npm publish . --tag $NPM_TAG" > ./dist/packages-dist/publish.sh && 21 | chmod +x ./dist/packages-dist/publish.sh 22 | -------------------------------------------------------------------------------- /tools/jasmine.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import Jasmine from 'jasmine'; 3 | 4 | import 'reflect-metadata'; 5 | import 'zone.js'; 6 | 7 | import { getTestBed } from '@angular/core/testing'; 8 | import { platformServerTesting, ServerTestingModule } from '@angular/platform-server/testing'; 9 | 10 | // First, initialize the Angular testing environment. 11 | getTestBed().initTestEnvironment( 12 | ServerTestingModule, 13 | platformServerTesting() 14 | ); 15 | 16 | const tests = new Jasmine({}); 17 | tests.loadConfig({ 18 | spec_dir: '.', 19 | spec_files: [ 20 | 'dist/out-tsc/jasmine/**/*.jasmine.js', 21 | 'dist/out-tsc/jasmine/**/*.spec.js', 22 | ] 23 | }); 24 | 25 | tests.execute(); 26 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "baseUrl": "./", 6 | "outDir": "./dist", 7 | "sourceMap": true, 8 | "declaration": false, 9 | "downlevelIteration": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "importHelpers": true, 15 | "target": "es2020", 16 | "skipLibCheck": true, 17 | "typeRoots": [ 18 | "node_modules/@types" 19 | ], 20 | "lib": [ 21 | "es2018", 22 | "dom" 23 | ], 24 | "paths": { 25 | "@angular/fire": ["dist/packages-dist"], 26 | "@angular/fire/*": ["dist/packages-dist/*"] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "tools/build.ts" 4 | ], 5 | "compilerOptions": { 6 | "outDir": "tools", 7 | "skipLibCheck": true, 8 | "lib": ["es2019", "dom"], 9 | "module": "commonjs", 10 | "target": "ES2020", 11 | "plugins": [ 12 | { "transform": "ts-transformer-keys/transformer" } 13 | ], 14 | "baseUrl": "./" 15 | } 16 | } -------------------------------------------------------------------------------- /tsconfig.jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "dist/out-tsc/jasmine", 5 | "module": "commonjs", 6 | "target": "es2015", 7 | "allowJs": true, 8 | "resolveJsonModule": true, 9 | "esModuleInterop": true, 10 | "types": [ 11 | "jasmine", 12 | "node" 13 | ] 14 | }, 15 | "include": [ 16 | "tools/jasmine.ts", 17 | "src/**/*.jasmine.ts", 18 | // Not sure what is wrong here, but since upgrading karma it's fallen apart 19 | // "src/**/*.spec.ts", 20 | "src/**/*.d.ts", 21 | "node_modules/zone.js/zone.d.ts" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "dist/out-tsc/lib", 5 | "target": "es2015", 6 | "declaration": true, 7 | "inlineSources": true, 8 | "declarationMap": false, 9 | "types": [ 10 | "node" 11 | ], 12 | "lib": [ 13 | "dom", 14 | "es2018" 15 | ] 16 | }, 17 | "angularCompilerOptions": { 18 | "compilationMode": "partial" 19 | }, 20 | "exclude": [ 21 | "src/test.ts", 22 | "src/**/*.spec.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "dist/out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "src/**/*.spec.ts", 15 | "src/**/*.d.ts", 16 | "node_modules/zone.js/zone.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tsconfig": "./tsconfig.json", 3 | "ignoreCompilerErrors": true, 4 | "mode": "modules", 5 | "excludeExternals": true, 6 | "excludeNotExported": true, 7 | "excludePrivate": true, 8 | "excludeProtected": true, 9 | "includeDeclarations": true, 10 | "disableOutputCheck": true 11 | } --------------------------------------------------------------------------------