├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ └── feature_request.md ├── .gitignore ├── .opensource ├── README.md └── project.json ├── .prettierrc.json ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── package-lock.json ├── package.json └── packages ├── demo ├── .eslintrc.js ├── .firebaserc ├── .prettierrc.js ├── Procfile ├── README.md ├── components │ ├── Btn.vue │ ├── Codeblock.vue │ ├── Form.vue │ ├── Logo │ │ ├── FirebaseLogo.vue │ │ ├── NuxtLogo.vue │ │ └── index.vue │ ├── ServiceTitle.vue │ ├── SubTitle.vue │ └── examples │ │ ├── Analytics.vue │ │ ├── AppCheck.vue │ │ ├── Auth.vue │ │ ├── Firestore.vue │ │ ├── Functions.vue │ │ ├── Messaging.vue │ │ ├── Performance.vue │ │ ├── RealTimeDatabase.vue │ │ ├── RemoteConfig.vue │ │ ├── Storage.vue │ │ └── VuexStore.vue ├── firebase.json ├── functions │ ├── .gitignore │ ├── index.js │ ├── package-lock.json │ └── package.json ├── layouts │ └── default.vue ├── middleware │ └── testMiddleware.ts ├── nuxt.config.ts ├── package.json ├── pages │ └── index.vue ├── plugins │ └── lazyMode.js ├── static │ ├── favicon.ico │ ├── icon.png │ ├── logo_350.png │ ├── logo_500.png │ └── logo_text.png ├── storage.rules ├── store │ ├── actions.js │ ├── getters.js │ ├── mutations.js │ └── state.js ├── tsconfig.json └── vue-shim.d.ts ├── docs ├── README.md ├── docs │ ├── .vitepress │ │ ├── config.ts │ │ ├── meta.ts │ │ ├── navigation │ │ │ └── sidebar.ts │ │ ├── style │ │ │ └── vars.css │ │ └── theme │ │ │ └── index.ts │ ├── community │ │ ├── demo.md │ │ ├── faq.md │ │ └── links.md │ ├── guide │ │ ├── getting-started.md │ │ ├── index.md │ │ ├── options.md │ │ └── usage.md │ ├── index.md │ ├── public │ │ ├── favicon.ico │ │ ├── icon.png │ │ ├── logo-dark.svg │ │ ├── logo-light.svg │ │ ├── preview-dark.png │ │ ├── preview.png │ │ └── service-worker.js │ ├── service-options │ │ ├── all-services.md │ │ ├── analytics.md │ │ ├── app-check.md │ │ ├── auth.md │ │ ├── database.md │ │ ├── firestore.md │ │ ├── functions.md │ │ ├── messaging.md │ │ ├── performance.md │ │ ├── remote-config.md │ │ └── storage.md │ └── tutorials │ │ ├── ssr.md │ │ ├── typescript.md │ │ └── vuexfire.md └── package.json └── firebase-module ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── CHANGELOG.md ├── babel.config.js ├── commitlint.config.js ├── husky.config.js ├── jest.config.js ├── lib ├── module.js ├── plugins │ ├── README.md │ ├── main.js │ └── services │ │ ├── analytics.js │ │ ├── app.js │ │ ├── appCheck.js │ │ ├── auth.initialize.js │ │ ├── auth.js │ │ ├── auth.serverLogin.js │ │ ├── auth.ssr.js │ │ ├── database.js │ │ ├── firestore.js │ │ ├── functions.js │ │ ├── messaging.js │ │ ├── performance.js │ │ ├── remoteConfig.js │ │ └── storage.js ├── sw-templates │ ├── README.md │ ├── firebase-auth-sw.js │ └── firebase-messaging-sw.js └── utils │ ├── auth-ssr │ └── ssr-auth-session-manager.js │ ├── logger.js │ └── template-utils.js ├── package.json ├── renovate.json ├── test ├── __snapshots__ │ ├── default.test.js.snap │ ├── lazy-init-auth.test.js.snap │ ├── lazy.test.js.snap │ └── with-module.test.js.snap ├── default.test.js ├── fixture │ ├── nuxt.config.js │ └── pages │ │ └── index.vue ├── lazy-init-auth.test.js ├── lazy.test.js └── with-module.test.js └── types └── index.d.ts /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # Enables "Sponsor" button on project 2 | 3 | github: lupas 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug report to help us improve the module. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 12 | 13 | ### Version 14 | @nuxtjs/firebase: 15 | firebase: 16 | nuxt: 17 | 18 | ### Reproduction Link 19 | 20 | 21 | ### Steps to reproduce 22 | 23 | 24 | ### What is Expected? 25 | 26 | 27 | ### What is actually happening? 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: StackOverflow 4 | url: https://stackoverflow.com/questions/tagged/firebase+nuxt.js 5 | about: Ask general Nuxt & Firebase questions not specifically related to this module on StackOverflow. 6 | - name: Nuxt Community Discord 7 | url: https://discord.nuxtjs.org/ 8 | about: Asking more specific questions about the module on Discord. 9 | - name: nuxt-firebase Documentation 10 | url: https://firebase.nuxtjs.org/ 11 | about: Check our documentation before reporting issues or questions. 12 | - name: Firebase Documentation 13 | url: https://firebase.google.com/docs/web/setup 14 | about: Make sure to study the Firebase documentation before asking questions, too. 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or enhancement for this project. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Is your feature request related to a problem? Please describe. 11 | 12 | 13 | ### Describe the solution you'd like 14 | 15 | 16 | ### Describe alternatives you've considered 17 | 18 | 19 | ### Additional context 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | 84 | 85 | # macOS 86 | .DS_Store 87 | 88 | # Vim swap files 89 | *.swp 90 | 91 | **/demo/static/*sw.js 92 | **/demo/static/sw.js 93 | 94 | cache -------------------------------------------------------------------------------- /.opensource/README.md: -------------------------------------------------------------------------------- 1 | The `/.opensource/project.json` file is needed for the module to be featured on https://firebaseopensource.com. 2 | -------------------------------------------------------------------------------- /.opensource/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Nuxt Firebase-Module", 3 | "platforms": [ 4 | "Web" 5 | ], 6 | "content": "README.md", 7 | "pages": [], 8 | "tabs": [ 9 | { 10 | "title": "Full Documentation", 11 | "href": "https://firebase.nuxtjs.org/" 12 | }, 13 | { 14 | "title": "Nuxt.js (v2), Firestore & SSR", 15 | "href": "https://medium.com/@pascalluther/nuxt-js-v2-firestore-ssr-938d8fb7d2b0" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "arrowParens": "always", 4 | "singleQuote": true, 5 | "bracketSpacing": false 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-present Pascal Luther 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | nuxt-firebase logo 3 |

4 | 5 | [![](https://david-dm.org/nuxt-community/firebase-module/status.svg?style=flat-square)](https://david-dm.org/nuxt-community/i18n-module) 6 | [![](https://snyk.io/test/github/nuxt-community/firebase-module/badge.svg?style=flat-square)](https://snyk.io/test/github/nuxt-community/firebase-module) 7 | [![](https://img.shields.io/npm/v/@nuxtjs/firebase/latest.svg?style=flat-square)](https://npmjs.com/package/@nuxtjs/firebase) 8 | [![](https://img.shields.io/npm/dt/@nuxtjs/firebase.svg?style=flat-square)](https://npmjs.com/package/@nuxtjs/firebase) 9 | 10 | > Easily integrate Firebase into your Nuxt project. 11 | 12 | ## IMPORTANT! 13 | 14 | > ### ⚠️ **Nuxt 3 not supported ⚠️**: 15 | > 16 | > This module was written for Nuxt 2 and does currently not support Nuxt 3. 17 | > There are currently no plans to support Nuxt 3 in the near future in this module. 18 | > However, you can take a look at [VueFire Nuxt module for Nuxt 3 support](https://vuefire.vuejs.org/nuxt/getting-started.html) 19 | 20 | > ### ℹ️ **Modular Mode (Firebase v9+) ℹ️**: 21 | > 22 | > This module does not support the new modular syntax from Firebase v9+. 23 | > 24 | > If you plan to use the new modular mode of Version 9, we advise you to implement Firebase manually as described in the following [medium article](https://lupas.medium.com/firebase-9-beta-nuxt-js-981cf3dac910). 25 | > 26 | > It is currently unclear when, and if, this module will support the new modular mode. See [discussion](https://github.com/nuxt-community/firebase-module/issues/597). 27 | 28 | ## Links 29 | 30 | - 📘 [Documentation](https://firebase.nuxtjs.org/) 31 | - 🔖 [Release notes](https://github.com/nuxt-community/firebase-module/releases) 32 | - 👥 [Community](https://discord.nuxtjs.org/) 33 | 34 | ## Quick Setup 35 | 36 | Make sure you are using Nuxt 2 and have Firebase v8 installed in your project. 37 | 38 | ```bash 39 | yarn add firebase # OR npm i firebase 40 | ``` 41 | 42 | Install the module via NPM or Yarn: 43 | 44 | ```bash 45 | yarn add @nuxtjs/firebase # OR npm i @nuxtjs/firebase 46 | ``` 47 | 48 | ## Quick Config 49 | 50 | Add the following to your nuxt.config.js. 51 | 52 | See all configuration options [here](https://firebase.nuxtjs.org/guide/options/). 53 | 54 | ```js 55 | modules: [ 56 | [ 57 | '@nuxtjs/firebase', 58 | { 59 | config: { 60 | apiKey: '', 61 | authDomain: '', 62 | projectId: '', 63 | storageBucket: '', 64 | messagingSenderId: '', 65 | appId: '', 66 | measurementId: '' 67 | }, 68 | services: { 69 | auth: true // Just as example. Can be any other service. 70 | } 71 | } 72 | ] 73 | ], 74 | ``` 75 | 76 | ## Quick Usage 77 | 78 | Now you can use all Firebase services with `this.$fire.auth`, `this.$fire.firestore`, `this.$fire.messaging` etc. (see list [here](https://firebase.nuxtjs.org/guide/usage/)). 79 | 80 | Example: 81 | 82 | ```js 83 | try { 84 | await this.$fire.auth.createUserWithEmailAndPassword('foo@foo.foo', 'test') 85 | } catch (e) { 86 | handleError(e) 87 | } 88 | ``` 89 | 90 | ## Guidelines for issues & feature requests 91 | 92 | - Use the GitHub issue search — check if the issue or feature request has already been reported. 93 | - Check if the issue has been fixed — try to reproduce it using the latest master or development branch in the repository. 94 | - Isolate the problem — create a reduced test case and a live example. 95 | 96 | A good issue shouldn't leave others needing to chase you up for more information. Please **try to be as detailed as possible** in your report. What is your environment? What steps will reproduce the issue? What versions are you using? What would you expect to be the outcome? All these details will help people to fix any potential bugs. 97 | 98 | If you have difficulties that are most likely not bugs or if you just have a simple questions, please ask them in the [Nuxt Discord server](https://discord.nuxtjs.org) instead. 99 | 100 | If your issue does not suffice these guidelines, it might be closed immediately. 101 | 102 | ## License 103 | 104 | MIT - [Nuxt-Community](https://github.com/nuxt-community) - [Pascal Luther](https://github.com/lupas) 105 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/firebase-monorepo", 3 | "keywords": [ 4 | "firebase", 5 | "firestore", 6 | "google", 7 | "googleauthentication", 8 | "nuxt", 9 | "realtimedatabase" 10 | ], 11 | "homepage": "https://firebase.nuxtjs.org/", 12 | "repository": "nuxt-community/firebase-module", 13 | "license": "MIT", 14 | "author": "Pascal Luther", 15 | "workspaces": [ 16 | "packages/**" 17 | ], 18 | "scripts": { 19 | "heroku:setup": "heroku login && heroku git:remote -a nuxt-fire-demo", 20 | "heroku:deploy": "git subtree push --prefix packages/demo heroku HEAD:master" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/demo/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | '@nuxtjs/eslint-config-typescript', 9 | 'prettier', 10 | 'prettier/vue', 11 | 'plugin:prettier/recommended', 12 | 'plugin:nuxt/recommended', 13 | ], 14 | plugins: ['prettier'], 15 | // add your custom rules here 16 | rules: {}, 17 | } 18 | -------------------------------------------------------------------------------- /packages/demo/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "nuxt-fire-demo": "nuxt-fire-demo", 4 | "default": "nuxt-fire-demo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/demo/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | arrowParens: 'always', 4 | semi: false 5 | } 6 | -------------------------------------------------------------------------------- /packages/demo/Procfile: -------------------------------------------------------------------------------- 1 | web: nuxt start -------------------------------------------------------------------------------- /packages/demo/README.md: -------------------------------------------------------------------------------- 1 | # 🔥 Nuxt-Fire Demo 2 | 3 |

4 | 5 | > Example project using [nuxt-community/firebase-module](https://github.com/nuxt-community/firebase-module) to integrate Firebase into Nuxt. 6 | 7 | ## Demo 8 | 9 | ### [Live Demo](https://nuxt-fire-demo.herokuapp.com) 10 | 11 | ## Build Setup 12 | 13 | ```bash 14 | # cd to src 15 | $ cd src 16 | 17 | # install dependencies 18 | $ npm i 19 | 20 | # start firebase emulators 21 | $ npm run emulators 22 | 23 | # serve with hot reload at localhost:3000 24 | $ npm run dev 25 | ``` 26 | 27 | For detailed explanation on how things work, checkout [nuxt-community/firebase-module](https://github.com/nuxt-community/firebase-module). 28 | 29 | ## Issues 30 | 31 | If you have any issues with nuxt-firebase, please ask the question in [nuxt-community/firebase-module/issues](https://github.com/nuxt-community/firebase-module/issues). 32 | -------------------------------------------------------------------------------- /packages/demo/components/Btn.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /packages/demo/components/Codeblock.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /packages/demo/components/Form.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/demo/components/Logo/FirebaseLogo.vue: -------------------------------------------------------------------------------- 1 | 133 | 134 | 153 | 154 | 159 | -------------------------------------------------------------------------------- /packages/demo/components/Logo/NuxtLogo.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /packages/demo/components/Logo/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 43 | -------------------------------------------------------------------------------- /packages/demo/components/ServiceTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /packages/demo/components/SubTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Analytics.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 41 | -------------------------------------------------------------------------------- /packages/demo/components/examples/AppCheck.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Auth.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 107 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Firestore.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 84 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Functions.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 50 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Messaging.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 103 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Performance.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 40 | -------------------------------------------------------------------------------- /packages/demo/components/examples/RealTimeDatabase.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 74 | -------------------------------------------------------------------------------- /packages/demo/components/examples/RemoteConfig.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 52 | -------------------------------------------------------------------------------- /packages/demo/components/examples/Storage.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 71 | -------------------------------------------------------------------------------- /packages/demo/components/examples/VuexStore.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 29 | -------------------------------------------------------------------------------- /packages/demo/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | }, 16 | "emulators": { 17 | "functions": { 18 | "port": 12345 19 | }, 20 | "firestore": { 21 | "port": 8080 22 | }, 23 | "database": { 24 | "port": 9000 25 | }, 26 | "hosting": { 27 | "port": 5000 28 | }, 29 | "auth": { 30 | "port": 9099 31 | }, 32 | "storage": { 33 | "port": 9199 34 | }, 35 | "ui": { 36 | "enabled": true 37 | } 38 | }, 39 | "storage": { 40 | "rules": "storage.rules" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/demo/functions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /packages/demo/functions/index.js: -------------------------------------------------------------------------------- 1 | const functions = require('firebase-functions') 2 | const admin = require('firebase-admin') 3 | admin.initializeApp() 4 | const messaging = admin.messaging() 5 | 6 | exports.testFunction = functions.https.onCall(() => { 7 | console.info('Test Function triggered') 8 | return { message: "Yeaaahh it's working!" } 9 | }) 10 | 11 | exports.sendTestPushMessage = functions.https.onCall(async (data) => { 12 | // As defined in https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages 13 | const image = 14 | 'https://avatars2.githubusercontent.com/u/4020037?s=460&u=c5f9c131d565202d8e530295b130239edd25768d&v=4' 15 | const message = { 16 | name: 'testPushMessage', 17 | data: {}, 18 | notification: { 19 | title: `Test Push Message`, 20 | body: 'If you get this, it worked.', 21 | image, 22 | }, 23 | android: {}, 24 | webpush: { 25 | notification: { 26 | // Adds the image to the push notificationm 27 | icon: image, 28 | // Adds actions to the push notification 29 | actions: [ 30 | { 31 | action: 'goToLupasGithub', 32 | title: 'Github: lupas', 33 | icon: '', 34 | }, 35 | { 36 | action: 'goToModuleGithub', 37 | title: 'Firebase Module', 38 | icon: '', 39 | }, 40 | ], 41 | }, 42 | fcm_options: { 43 | // Adds a link to be opened when clicked on the push notification 44 | link: 'https://nuxt-fire-demo.herokuapp.com/', 45 | }, 46 | }, 47 | apns: { 48 | fcm_options: {}, 49 | }, 50 | fcm_options: {}, 51 | token: data.token, 52 | } 53 | try { 54 | await messaging.send(message) 55 | } catch (e) { 56 | console.error(`Did not work to send a message to token ${message.token}`) 57 | console.error(e) 58 | } 59 | }) 60 | -------------------------------------------------------------------------------- /packages/demo/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "description": "Cloud Functions for Firebase", 4 | "scripts": { 5 | "serve": "firebase serve --only functions", 6 | "shell": "firebase functions:shell", 7 | "start": "npm run shell", 8 | "deploy": "firebase deploy --only functions", 9 | "logs": "firebase functions:log", 10 | "emulate": "firebase emulators:start --only functions" 11 | }, 12 | "engines": { 13 | "node": "12" 14 | }, 15 | "dependencies": { 16 | "firebase-admin": "^10.0.1", 17 | "firebase-functions": "^3.11.0" 18 | }, 19 | "devDependencies": { 20 | "firebase-functions-test": "^0.3.3" 21 | }, 22 | "private": true 23 | } 24 | -------------------------------------------------------------------------------- /packages/demo/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/demo/middleware/testMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from '@nuxt/types' 2 | 3 | const testMiddleware: Middleware = ({ app, store }) => { 4 | if (app.$fire.auth) { 5 | // If user is logged in, store.state.authUser will be filled. 6 | // INFO -> Firebase Services can be accessed with app.$fire.auth (etc.) in Middleware. 7 | } 8 | } 9 | 10 | export default testMiddleware 11 | -------------------------------------------------------------------------------- /packages/demo/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { NuxtConfig } from '@nuxt/types' 2 | 3 | const isDev = process.env.NODE_ENV === 'development' 4 | const useEmulators = false // manually change if emulators needed 5 | 6 | const config: NuxtConfig = { 7 | head: { 8 | title: 'nuxt-firebase-demo', 9 | meta: [ 10 | { charset: 'utf-8' }, 11 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 12 | { hid: 'description', name: 'description', content: '' }, 13 | ], 14 | link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }], 15 | }, 16 | 17 | components: true, 18 | 19 | buildModules: [ 20 | '@nuxt/typescript-build', 21 | '@nuxtjs/tailwindcss', 22 | '@nuxtjs/firebase', 23 | ], 24 | 25 | firebase: { 26 | lazy: false, 27 | config: { 28 | apiKey: 'AIzaSyDa-YwgWTp2GDyVYEfv-XLb62100_HoEvU', 29 | authDomain: 'nuxt-fire-demo.firebaseapp.com', 30 | projectId: 'nuxt-fire-demo', 31 | storageBucket: 'nuxt-fire-demo.appspot.com', 32 | messagingSenderId: '807370470428', 33 | appId: '1:807370470428:web:26da98c86c3fd352', 34 | measurementId: 'G-XT6PVC1D4X', 35 | }, 36 | onFirebaseHosting: false, 37 | terminateDatabasesAfterGenerate: true, 38 | services: { 39 | auth: { 40 | initialize: { 41 | onAuthStateChangedAction: 'onAuthStateChanged', 42 | }, 43 | ssr: true, 44 | emulatorPort: isDev && useEmulators ? 9099 : undefined, 45 | disableEmulatorWarnings: false, 46 | }, 47 | firestore: { 48 | memoryOnly: false, 49 | enablePersistence: true, 50 | emulatorPort: isDev && useEmulators ? 8080 : undefined, 51 | }, 52 | functions: { 53 | emulatorPort: isDev && useEmulators ? 12345 : undefined, 54 | }, 55 | storage: { 56 | emulatorPort: isDev && useEmulators ? 9199 : undefined, 57 | emulatorHost: 'localhost', 58 | }, 59 | database: { 60 | emulatorPort: isDev && useEmulators ? 9000 : undefined, 61 | }, 62 | performance: true, 63 | analytics: true, 64 | remoteConfig: { 65 | settings: { 66 | fetchTimeoutMillis: 60000, 67 | minimumFetchIntervalMillis: 43200000, 68 | }, 69 | defaultConfig: { 70 | welcome_message: 'Welcome', 71 | }, 72 | }, 73 | // breaks the app with 'app.$fire.firestore.collection is not a function': 74 | appCheck: true, 75 | messaging: { 76 | createServiceWorker: true, 77 | actions: [ 78 | { 79 | action: 'goToLupasGithub', 80 | url: 'https://github.com/lupas', 81 | }, 82 | { 83 | action: 'goToModuleGithub', 84 | url: 'https://github.com/nuxt-community/firebase-module', 85 | }, 86 | ], 87 | fcmPublicVapidKey: 88 | 'BL_xoiuOe5vbb2vJkCNnuswn03NwCsyCkJUgRbuQA5tpg7J4E4z50MO8b-wrrad6fcysYAaFjHqU7D9o0oCWL8w', 89 | }, 90 | }, 91 | }, 92 | 93 | modules: ['@nuxtjs/pwa'], 94 | // plugins: ['~/plugins/lazyMode'], 95 | 96 | build: {}, 97 | 98 | /* 99 | ** Nuxt.js Middleware 100 | */ 101 | router: { 102 | middleware: ['testMiddleware'], 103 | }, 104 | 105 | pwa: { 106 | workbox: { 107 | importScripts: ['/firebase-auth-sw.js'], 108 | // by default the workbox module will not install the service worker in dev environment to avoid conflicts with HMR 109 | // only set this true for testing and remember to always clear your browser cache in development 110 | dev: process.env.NODE_ENV === 'development', 111 | }, 112 | }, 113 | } 114 | export default config 115 | -------------------------------------------------------------------------------- /packages/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-firebase-demo", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxt", 7 | "build": "nuxt build", 8 | "start": "nuxt start", 9 | "generate": "nuxt generate", 10 | "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .", 11 | "lint": "npm run lint:js", 12 | "emulators": "firebase emulators:start" 13 | }, 14 | "dependencies": { 15 | "@nuxtjs/pwa": "^3.3.3", 16 | "core-js": "^3.19.2", 17 | "firebase": "^9.6.2", 18 | "firebase-admin": "^10.0.1", 19 | "nuxt": "^2.15.8", 20 | "prismjs": "^1.25.0", 21 | "vue-prism-component": "^2.0.0", 22 | "@nuxtjs/firebase": "^8.2.0" 23 | }, 24 | "devDependencies": { 25 | "@nuxt/types": "^2.15.8", 26 | "@nuxt/typescript-build": "^2.1.0", 27 | "@nuxtjs/eslint-config": "^8.0.0", 28 | "@nuxtjs/eslint-config-typescript": "^8.0.0", 29 | "@nuxtjs/eslint-module": "^3.0.2", 30 | "@nuxtjs/tailwindcss": "^4.2.1", 31 | "babel-eslint": "^10.1.0", 32 | "eslint": "^8.1.0", 33 | "eslint-config-prettier": "^8.3.0", 34 | "eslint-plugin-nuxt": "^3.1.0", 35 | "eslint-plugin-prettier": "^4.0.0", 36 | "prettier": "^2.8.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/demo/pages/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 86 | 87 | 97 | -------------------------------------------------------------------------------- /packages/demo/plugins/lazyMode.js: -------------------------------------------------------------------------------- 1 | export default async (context) => { 2 | await context.$fire.databaseReady() 3 | await context.$fire.firestoreReady() 4 | await context.$fire.storageReady() 5 | await context.$fire.functionsReady() 6 | if (process.client) { 7 | await context.$fire.authReady() 8 | await context.$fireAuthStore.subscribe() 9 | await context.$fire.messagingReady() 10 | await context.$fire.performanceReady() 11 | await context.$fire.analyticsReady() 12 | await context.$fire.remoteConfigReady() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/demo/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/demo/static/favicon.ico -------------------------------------------------------------------------------- /packages/demo/static/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/demo/static/icon.png -------------------------------------------------------------------------------- /packages/demo/static/logo_350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/demo/static/logo_350.png -------------------------------------------------------------------------------- /packages/demo/static/logo_500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/demo/static/logo_500.png -------------------------------------------------------------------------------- /packages/demo/static/logo_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/demo/static/logo_text.png -------------------------------------------------------------------------------- /packages/demo/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 | -------------------------------------------------------------------------------- /packages/demo/store/actions.js: -------------------------------------------------------------------------------- 1 | export default { 2 | async nuxtServerInit({ dispatch }, ctx) { 3 | // INFO -> Nuxt-fire Objects can be accessed in nuxtServerInit action via this.$fire___, ctx.$fire___ and ctx.app.$fire___' 4 | 5 | /** Get the VERIFIED authUser on the server */ 6 | if (ctx.res && ctx.res.locals && ctx.res.locals.user) { 7 | const { allClaims: claims, ...authUser } = ctx.res.locals.user 8 | 9 | console.info( 10 | 'Auth User verified on server-side. User: ', 11 | authUser, 12 | 'Claims:', 13 | claims 14 | ) 15 | 16 | await dispatch('onAuthStateChanged', { 17 | authUser, 18 | claims, 19 | }) 20 | } 21 | }, 22 | 23 | async onAuthStateChanged({ commit }, { authUser }) { 24 | if (!authUser) { 25 | commit('RESET_STORE') 26 | return 27 | } 28 | if (authUser && authUser.getIdToken) { 29 | try { 30 | const idToken = await authUser.getIdToken(true) 31 | console.info('idToken', idToken) 32 | } catch (e) { 33 | console.error(e) 34 | } 35 | } 36 | commit('SET_AUTH_USER', { authUser }) 37 | }, 38 | 39 | checkVuexStore(ctx) { 40 | if (this.$fire.auth === null) { 41 | throw 'Vuex Store example not working - this.$fire.auth cannot be accessed.' 42 | } 43 | 44 | alert( 45 | 'Success. Nuxt-fire Objects can be accessed in store actions via this.$fire___' 46 | ) 47 | }, 48 | } 49 | -------------------------------------------------------------------------------- /packages/demo/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | isLoggedIn: (state) => { 3 | try { 4 | return state.authUser.uid !== null 5 | } catch { 6 | return false 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/demo/store/mutations.js: -------------------------------------------------------------------------------- 1 | import initialState from './state' 2 | 3 | export default { 4 | RESET_STORE: (state) => { 5 | Object.assign(state, initialState()) 6 | }, 7 | 8 | SET_AUTH_USER: (state, { authUser }) => { 9 | state.authUser = { 10 | uid: authUser.uid, 11 | email: authUser.email 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/demo/store/state.js: -------------------------------------------------------------------------------- 1 | export default () => ({ 2 | authUser: null 3 | }) 4 | -------------------------------------------------------------------------------- /packages/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": [ 7 | "ESNext", 8 | "ESNext.AsyncIterable", 9 | "DOM" 10 | ], 11 | "esModuleInterop": true, 12 | "allowJs": true, 13 | "sourceMap": true, 14 | "strict": true, 15 | "noEmit": true, 16 | "experimentalDecorators": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "~/*": [ 20 | "./*" 21 | ], 22 | "@/*": [ 23 | "./*" 24 | ] 25 | }, 26 | "types": [ 27 | "@types/node", 28 | "@nuxt/types", 29 | "@nuxtjs/firebase" 30 | ] 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | ".nuxt", 35 | "dist" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /packages/demo/vue-shim.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /packages/docs/README.md: -------------------------------------------------------------------------------- 1 | # @nuxtjs/firebase-docs 2 | 3 | ## Setup 4 | 5 | Install dependencies: 6 | 7 | ```bash 8 | npm i 9 | ``` 10 | 11 | ## Development 12 | 13 | ```bash 14 | npm run dev 15 | ``` 16 | 17 | ## Static Generation 18 | 19 | This will create the `.vitepress/dist` directory for publishing to static hosting: 20 | 21 | ```bash 22 | npm run build 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/docs/docs/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig, DefaultTheme} from 'vitepress' 2 | import {version} from '../../package.json' 3 | import { 4 | twitter, 5 | github, 6 | headTitle, 7 | headDescription, 8 | ogImage, 9 | ogUrl, 10 | } from './meta' 11 | import sidebar from './navigation/sidebar' 12 | 13 | export default defineConfig({ 14 | lang: 'en-US', 15 | title: headTitle, 16 | description: headDescription, 17 | appearance: 'dark', 18 | head: [ 19 | ['meta', {name: 'theme-color', content: '#ffe183'}], 20 | ['link', {rel: 'icon', href: '/icon.png', type: 'image/png'}], 21 | [ 22 | 'link', 23 | { 24 | rel: 'alternate icon', 25 | href: '/favicon.ico', 26 | type: 'image/png', 27 | sizes: '16x16', 28 | }, 29 | ], 30 | [ 31 | 'meta', 32 | { 33 | name: 'author', 34 | content: `Pascal Luther`, 35 | }, 36 | ], 37 | [ 38 | 'meta', 39 | { 40 | name: 'keywords', 41 | content: 'nuxt, nuxtjs, firebase', 42 | }, 43 | ], 44 | ['meta', {property: 'og:title', content: headTitle}], 45 | ['meta', {property: 'og:description', content: headDescription}], 46 | ['meta', {property: 'og:url', content: ogUrl}], 47 | ['meta', {property: 'og:image', content: ogImage}], 48 | ['meta', {name: 'twitter:title', content: headTitle}], 49 | ['meta', {name: 'twitter:description', content: headDescription}], 50 | ['link', {rel: 'mask-icon', href: '/icon.png', color: '#ffffff'}], 51 | [ 52 | 'link', 53 | { 54 | rel: 'apple-touch-icon', 55 | href: '/apple-touch-icon.png', 56 | sizes: '180x180', 57 | }, 58 | ], 59 | ], 60 | 61 | themeConfig: { 62 | logo: '/icon.png', 63 | 64 | outline: [2, 3], 65 | 66 | socialLinks: [ 67 | {icon: 'twitter', link: twitter}, 68 | {icon: 'github', link: github}, 69 | ], 70 | 71 | footer: { 72 | copyright: 'Copyright © 2019-PRESENT Pascal Luther', 73 | }, 74 | 75 | algolia: { 76 | appId: '9F70EYJ2LK', 77 | apiKey: 'cf7ef157f34e96340604d0d75a6fbc1c', // Public Read-Only API Key 78 | indexName: 'nuxtjs_firebase', 79 | }, 80 | 81 | carbonAds: { 82 | code: 'CE7D62JL', 83 | placement: 'firebasenuxtjsorg', 84 | }, 85 | 86 | nav: [ 87 | {text: 'Guide', link: '/guide/'}, 88 | { 89 | text: `v${version}`, 90 | items: [ 91 | { 92 | text: 'Release Notes', 93 | link: 'https://github.com/nuxt-community/firebase-module/releases', 94 | }, 95 | ], 96 | }, 97 | ], 98 | 99 | sidebar: sidebar, 100 | }, 101 | }) 102 | -------------------------------------------------------------------------------- /packages/docs/docs/.vitepress/meta.ts: -------------------------------------------------------------------------------- 1 | // noinspection ES6PreferShortImport: IntelliJ IDE hint to avoid warning to use `~/contributors`, will fail on build if changed 2 | 3 | /* Texts */ 4 | export const headTitle = "Nuxt Firebase"; 5 | export const headSubtitle = "Nuxt Firebase"; 6 | export const headDescription = "XXX"; 7 | 8 | /* CDN fonts and styles */ 9 | export const googleapis = "https://fonts.googleapis.com"; 10 | export const gstatic = "https://fonts.gstatic.com"; 11 | export const font = `${googleapis}/css2?family=Readex+Pro:wght@200;400;600&display=swap`; 12 | 13 | /* vitepress head */ 14 | export const ogUrl = "https://firebase.nuxtjs.org"; 15 | export const ogImage = `${ogUrl}og.png`; 16 | 17 | /* GitHub and social links */ 18 | export const github = "https://github.com/nuxt-community/firebase-module"; 19 | export const releases = "https://github.com/vuejs/vuefire/releases"; 20 | 21 | export const twitter = "https://twitter.com/nuxt_js"; 22 | 23 | /* Avatar/Image/Sponsors servers */ 24 | export const preconnectLinks = [googleapis, gstatic]; 25 | export const preconnectHomeLinks = [googleapis, gstatic]; 26 | 27 | /* PWA runtime caching urlPattern regular expressions */ 28 | export const pwaFontsRegex = new RegExp(`^${googleapis}/.*`, "i"); 29 | export const pwaFontStylesRegex = new RegExp(`^${gstatic}/.*`, "i"); 30 | // eslint-disable-next-line prefer-regex-literals 31 | export const githubusercontentRegex = new RegExp( 32 | "^https://((i.ibb.co)|((raw|user-images).githubusercontent.com))/.*", 33 | "i" 34 | ); 35 | -------------------------------------------------------------------------------- /packages/docs/docs/.vitepress/navigation/sidebar.ts: -------------------------------------------------------------------------------- 1 | import {DefaultTheme} from 'vitepress' 2 | 3 | const sidebar: DefaultTheme.Sidebar = { 4 | '/': [ 5 | { 6 | text: 'Guide', 7 | items: [ 8 | { 9 | text: 'Introduction', 10 | link: '/guide/', 11 | }, 12 | { 13 | text: 'Getting Started', 14 | link: '/guide/getting-started', 15 | }, 16 | { 17 | text: 'Options', 18 | link: '/guide/options', 19 | }, 20 | { 21 | text: 'Usage', 22 | link: '/guide/usage', 23 | }, 24 | ], 25 | }, 26 | { 27 | text: 'Service Options', 28 | items: [ 29 | { 30 | text: '(All Services)', 31 | link: '/service-options/all-services', 32 | }, 33 | { 34 | text: 'appCheck', 35 | link: '/service-options/app-check', 36 | }, 37 | { 38 | text: 'auth', 39 | link: '/service-options/auth', 40 | }, 41 | { 42 | text: 'firestore', 43 | link: '/service-options/firestore', 44 | }, 45 | { 46 | text: 'database', 47 | link: '/service-options/database', 48 | }, 49 | { 50 | text: 'storage', 51 | link: '/service-options/storage', 52 | }, 53 | { 54 | text: 'functions', 55 | link: '/service-options/functions', 56 | }, 57 | { 58 | text: 'performance', 59 | link: '/service-options/performance', 60 | }, 61 | { 62 | text: 'analytics', 63 | link: '/service-options/analytics', 64 | }, 65 | { 66 | text: 'messaging', 67 | link: '/service-options/messaging', 68 | }, 69 | { 70 | text: 'remote-config', 71 | link: '/service-options/remote-config', 72 | }, 73 | ], 74 | }, 75 | { 76 | text: 'Tutorials', 77 | items: [ 78 | { 79 | text: 'Firebase Auth with SSR', 80 | link: '/tutorials/ssr', 81 | }, 82 | { 83 | text: 'Usage with vuexfire', 84 | link: '/tutorials/vuexfire', 85 | }, 86 | { 87 | text: 'Usage with Typescript', 88 | link: '/tutorials/typescript', 89 | }, 90 | ], 91 | }, 92 | { 93 | text: 'Community', 94 | items: [ 95 | { 96 | text: 'Demo', 97 | link: '/community/demo', 98 | }, 99 | { 100 | text: 'Links', 101 | link: '/community/links', 102 | }, 103 | { 104 | text: 'FAQ', 105 | link: '/community/faq', 106 | }, 107 | ], 108 | }, 109 | ], 110 | } 111 | 112 | export default sidebar 113 | -------------------------------------------------------------------------------- /packages/docs/docs/.vitepress/style/vars.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Colors 3 | * -------------------------------------------------------------------------- */ 4 | 5 | /* 50: '#fff8e1', 6 | 100: '#ffedb3', 7 | 200: '#ffe183', 8 | 300: '#ffd650', 9 | 400: '#ffcb29', 10 | 500: '#ffc309', 11 | 600: '#ffb401', 12 | 700: '#ffa200', 13 | 800: '#ff9100', 14 | 900: '#ff7100', */ 15 | 16 | :root { 17 | --vp-c-brand: #00dc82; 18 | --vp-c-brand-light: #03ee8c; 19 | --vp-c-accent: #f78200; 20 | --c-gradient-1: #00dc82; 21 | --c-gradient-2: #f78200; 22 | } 23 | 24 | /** 25 | * Component: Button 26 | * -------------------------------------------------------------------------- */ 27 | 28 | :root { 29 | --vp-button-brand-border: var(--vp-c-brand-light); 30 | --vp-button-brand-text: var(--vp-c-text-dark-1); 31 | --vp-button-brand-bg: var(--vp-c-brand); 32 | --vp-button-brand-hover-border: var(--vp-c-brand-light); 33 | --vp-button-brand-hover-text: var(--vp-c-text-dark-1); 34 | --vp-button-brand-hover-bg: var(--vp-c-brand-light); 35 | --vp-button-brand-active-border: var(--vp-c-brand-light); 36 | --vp-button-brand-active-text: var(--vp-c-text-dark-1); 37 | --vp-button-brand-active-bg: var(--vp-button-brand-bg); 38 | } 39 | 40 | /** 41 | * Component: Home 42 | * -------------------------------------------------------------------------- */ 43 | 44 | :root { 45 | --vp-home-hero-name-color: transparent; 46 | --vp-home-hero-name-background: -webkit-linear-gradient( 47 | 120deg, 48 | var(--c-gradient-1) 25%, 49 | var(--c-gradient-2) 50 | ); 51 | --vp-home-hero-image-background-image: linear-gradient( 52 | -45deg, 53 | var(--vp-c-brand) 30%, 54 | var(--vp-c-accent) 55 | ); 56 | --vp-home-hero-image-filter: blur(30px); 57 | } 58 | 59 | @media (min-width: 640px) { 60 | :root { 61 | --vp-home-hero-image-filter: blur(56px); 62 | } 63 | } 64 | 65 | @media (min-width: 960px) { 66 | :root { 67 | --vp-home-hero-image-filter: blur(72px); 68 | } 69 | } 70 | 71 | /** 72 | * Component: Algolia 73 | * -------------------------------------------------------------------------- */ 74 | 75 | .DocSearch { 76 | --docsearch-primary-color: var(--vp-c-brand) !important; 77 | } 78 | 79 | .dark-only { 80 | display: none; 81 | } 82 | 83 | .dark .dark-only { 84 | display: block; 85 | } 86 | 87 | .dark .light-only { 88 | display: none; 89 | } 90 | -------------------------------------------------------------------------------- /packages/docs/docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import Theme from "vitepress/theme"; 2 | import "../style/vars.css"; 3 | import { h } from "vue"; 4 | 5 | export default { 6 | ...Theme, 7 | Layout() { 8 | return h(Theme.Layout, null, {}); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/docs/docs/community/demo.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | 3 | Check out the [Demo](https://nuxt-fire-demo.herokuapp.com/) by [lupas](https://github.com/lupas) and its [GitHub Repo](https://github.com/lupas/nuxt-firebase-demo) for example code. 4 | -------------------------------------------------------------------------------- /packages/docs/docs/community/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | Create an [issue](https://github.com/nuxt-community/firebase-module/issues) if you have a question and we might add it to the FAQ. 4 | 5 | ## Firestore: Using "array-contains" or "array-contains-any" does not work 6 | 7 | If you are using `array-contains` or `array-contains-any` you might run into the followig error: 8 | 9 | > Function Query.where() called with invalid data. Unsupported field value: a custom Array object 10 | 11 | This issue is not coming from this module but is specific to using Firebase together with Nuxt. You can get rid of this error message by setting `runInNewContext` to `false` like so: 12 | 13 | ::: code-group 14 | 15 | ```js [nuxt.config.js] 16 | render: { 17 | bundleRenderer: { 18 | runInNewContext: false 19 | } 20 | }, 21 | ``` 22 | 23 | ::: 24 | 25 | ## How to add Firebase Polyfills? 26 | 27 | If you want to add Firebase polyfills, you need to ceate a plugin and import the required polyfills like so: 28 | 29 | 1. Creating `/plugins/polyfills.js` containing: 30 | 31 | ::: code-group 32 | 33 | ```js [polyfills.js] 34 | // Import all polyfills 35 | import '@firebase/polyfill' 36 | 37 | // Import specific polyfills: 38 | import '@firebase/polyfill/node_modules/core-js/features/object/values' 39 | ``` 40 | 41 | ::: 42 | 43 | 2. Add to your nuxt.config.js: 44 | 45 | ::: code-group 46 | 47 | ```js [nuxt.config.js] 48 | plugins: [ 49 | { src: '~plugins/polyfills', mode: 'client' }, 50 | ], 51 | ``` 52 | 53 | ::: 54 | 55 | > References: 56 | > [Issue #307](https://github.com/nuxt-community/firebase-module/issues/307) 57 | > [Stack Overflow Question](https://stackoverflow.com/questions/62308061/nuxt-firebase-ie-11-object-doesnt-support-property-or-method-values/64062207#64062207) 58 | 59 | ## How to use this module in SSR mode together with Strapi? 60 | 61 | For Strapi to work together with this module, you need to ignore the Strapi API routes by adding them to the [ignorePaths](https://firebase.nuxtjs.org/service-options/auth#ignorepaths) config like so: 62 | 63 | ```js 64 | auth: { 65 | ssr: { 66 | // ... 67 | ignorePaths: ['/api/'] // or /^api\// 68 | } 69 | } 70 | ``` 71 | 72 | > References: 73 | > [Issue #292](https://github.com/nuxt-community/firebase-module/issues/292) 74 | 75 | ## Nuxt Generate warns with "Nuxt Generate finished but did not exit" 76 | 77 | This warning happens because either Firestore or the RealtimeDb are not terminated at the end of Nuxt Generate. 78 | 79 | To get rid of this warning, you can terminate the services by extending the `generate:done` hook in your `nuxt.config.js` like so: 80 | 81 | ::: code-group 82 | 83 | ```js [nuxt.config.js] 84 | hooks: { 85 | generate: { 86 | async done(builder) { 87 | const appModule = await import('./.nuxt/firebase/app.js') 88 | const { session } = await appModule.default( 89 | builder.options.firebase.config, 90 | { 91 | res: null, 92 | } 93 | ) 94 | try { 95 | session.database().goOffline() 96 | } catch (e) { } 97 | try { 98 | session.firestore().terminate() 99 | } catch (e) { } 100 | }, 101 | }, 102 | }, 103 | ``` 104 | 105 | ::: 106 | 107 | > References: 108 | > [Issue #93](https://github.com/nuxt-community/firebase-module/issues/93) 109 | -------------------------------------------------------------------------------- /packages/docs/docs/community/links.md: -------------------------------------------------------------------------------- 1 | # Links 2 | 3 | Collection of Links related to this module: 4 | 5 | ### Articles 6 | 7 | - [Nuxt.js (v2), Firestore & SSR 🔥](https://medium.com/@pascalluther/nuxt-js-v2-firestore-ssr-938d8fb7d2b0?) 8 | Medium Article about integrating Firestore with Nuxt.js v2. 9 | 10 | - [Nuxt.js (v1), Firestore & SSR 🔥](https://medium.com/@pascalluther/nuxt-js-v1-firestore-and-ssr-73e3140574fc?) Medium Article about integrating Firestore with Nuxt.js v1. 11 | 12 | - [@nuxtjs/firebase social auth](https://dev.to/rodrigopv/nuxtjs-firebase-social-auth-3afe) 13 | Article about how to integrate social auth with nuxtjs/firebase 14 | 15 | ### Videos 16 | 17 | - [Nuxt Firebase로 블로그 만들어보기 12 파이어베이스 인증해보기](https://www.youtube.com/watch?v=Zd6PSfgH3t4) Tutorial video on how to integrate Firebase Auth with nuxt-fire (in Korean) 18 | -------------------------------------------------------------------------------- /packages/docs/docs/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Requirements 4 | 5 | Make sure you are using Nuxt 2 and have Firebase v8 installed in your project. 6 | 7 | ::: code-group 8 | 9 | ```bash [yarn] 10 | yarn add firebase@^8 11 | ``` 12 | 13 | ```bash [npm] 14 | npm install firebase@^8 15 | ``` 16 | 17 | ::: 18 | 19 | ::: danger IMPORTANT - Nuxt 3 not supported! 20 | 21 | This module was written for **Nuxt 2** and does currently not support Nuxt 3. There are currently **no plans** to support Nuxt 3 in the near future in this module. However, you can take a look at VueFire Nuxt module for Nuxt 3 support 22 | 23 | ::: 24 | 25 | ## Install 26 | 27 | Install the module via NPM or Yarn. 28 | 29 | ::: code-group 30 | 31 | ```bash [yarn] 32 | yarn add @nuxtjs/firebase 33 | ``` 34 | 35 | ```bash [npm] 36 | npm install @nuxtjs/firebase 37 | ``` 38 | 39 | ::: 40 | 41 | ## Configure 42 | 43 | Add the below code to your **nuxt.config.js** modules array and adjust it according to your needs. 44 | 45 | Visit the [config section](/guide/options#config) for a detailed overview about each configuration. 46 | 47 | ### Example Configuration 48 | 49 | ::: code-group 50 | 51 | ```js [nuxt.config.js] 52 | modules: [ 53 | [ 54 | '@nuxtjs/firebase', 55 | { 56 | config: { 57 | apiKey: '', 58 | authDomain: '', 59 | projectId: '', 60 | storageBucket: '', 61 | messagingSenderId: '', 62 | appId: '', 63 | measurementId: '' 64 | }, 65 | services: { 66 | auth: true // Just as example. Can be any other service. 67 | } 68 | } 69 | ] 70 | ], 71 | ``` 72 | 73 | ::: 74 | 75 | See list of all available services [here](/guide/options#services). 76 | 77 | You can also separate the config from the module array by using the **firebase** object: 78 | 79 | ::: code-group 80 | 81 | ```js [nuxt.config.js] 82 | modules: ['@nuxtjs/firebase'], 83 | 84 | firebase: { 85 | // options 86 | } 87 | ``` 88 | 89 | ::: 90 | -------------------------------------------------------------------------------- /packages/docs/docs/guide/index.md: -------------------------------------------------------------------------------- 1 | # Nuxt Firebase 2 | 3 | 4 | 5 | 6 | ::: danger IMPORTANT - Nuxt 3 not supported! 7 | 8 | This module was written for **Nuxt 2** and does currently not support Nuxt 3. There are currently **no plans** to support Nuxt 3 in the near future in this module. However, you can take a look at VueFire Nuxt module for Nuxt 3 support 9 | 10 | ::: 11 | 12 | ::: warning Modular Mode (Firebase v9+) 13 | 14 | This module does NOT support the new modular syntax from Firebase v9+. 15 | 16 | If you plan to use the new modular mode of Version 9, we advise you to implement Firebase manually as described in the following medium article. 17 | 18 | It is currently unclear when, and if, this module will support the new modular mode. See discussion. 19 | 20 | ::: 21 | 22 | ## What is this? 23 | 24 | The Nuxt.js Firebase Module is a module that helps you integrate the Firebase JavaScript SDK into your application with ease. By simply configuring this module in your nuxt.config.js file, you can use all Firebase Services throughout your app. 25 | 26 | By importing each individual Firebase service dynamically this module reduces bundle sizes and improves performance of your Nuxt.js app with Firebase. 27 | 28 | The module additionally adds other perks such as a plugin that automated the setup of onAuthStateChanged() for Firebase Authentication or other helper functions that make your life with Firebase easier. 29 | 30 | ## How does it work? 31 | 32 | The module adds a plugin to your Nuxt.js application that handles the initialization of each Firebase service (Authentication, Firestore, etc.). It then injects these services into the global context which makes them easily available throughout your application. 33 | -------------------------------------------------------------------------------- /packages/docs/docs/guide/options.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | ## config 4 | 5 | Your firebase config snippet and other Firebase specific parameters. You can retrieve this information from your Firebase project's overview page: 6 | 7 | `https://console.firebase.google.com/project//overview` 8 | 9 | ::: code-group 10 | 11 | ```js [nuxt.config.js] 12 | config: { 13 | // REQUIRED: Official config for firebase.initializeApp(config): 14 | apiKey: '', 15 | authDomain: '', 16 | projectId: '', 17 | storageBucket: '', 18 | messagingSenderId: '', 19 | appId: '', 20 | measurementId: '' 21 | } 22 | ``` 23 | 24 | ::: 25 | 26 | ::: info 27 | 28 | Can be defined **per NODE_ENV environment** if put in child-objects `config.production` and `config.development`, meaning that e.g. `config.production` gets loaded when `NODE_ENV === 'production'`. 29 | 30 | You can also specify multiple custom environments as mentioned in the [customEnv](/guide/options#customenv) option below. 31 | 32 | ::: 33 | 34 | ## services 35 | 36 | By default, **NO** Firebase products are initialized. To initialize a specific service, set its services flag to `true` or create a child object and name the key after the service. 37 | 38 | Available services: 39 | 40 | ::: code-group 41 | 42 | ```js [nuxt.config.js] 43 | services: { 44 | auth: true, 45 | firestore: true, 46 | functions: true, 47 | storage: true, 48 | database: true, 49 | messaging: true, 50 | performance: true, 51 | appCheck: true, 52 | analytics: true, 53 | remoteConfig: true, 54 | ``` 55 | 56 | ::: 57 | 58 | Each service has advanced options that you can configure. See the **service options** section for more details. 59 | 60 | ## customEnv 61 | 62 | - Type: `Boolean` 63 | - Default: `false` 64 | 65 | By default, the Firebase config will be chosen either directly from the **config-object** or from a **child-object named after the current NODE_ENV environment variable**. 66 | 67 | If set to `true`, however, the module will determine the environment based on the environment variable called `FIRE_ENV`, which you can define yourself. This gives you the flexibility to define as many different Firebase configs as you like, independent of your NODE_ENV. 68 | 69 | ::: danger 70 | 71 | If you decide to turn on this option, you need to define `process.env.FIRE_ENV` in your code and additionally add the following code to your `nuxt.config.js` to make sure that the environment variable gets passed from server to client. 72 | 73 | ::: danger 74 | 75 | ::: code-group 76 | 77 | ```js [nuxt.config.js] 78 | env: { 79 | FIRE_ENV: process.env.FIRE_ENV 80 | } 81 | ``` 82 | 83 | ::: 84 | 85 | After that, you can set FIRE_ENV to anything you like... 86 | 87 | ```js[package.json] 88 | "scripts": { 89 | "serveFoo": "FIRE_ENV=foofoofoo nuxt", 90 | "serveFaa": "FIRE_ENV=faafaafaa nuxt", 91 | } 92 | ``` 93 | 94 | And then add your config to the module options: 95 | 96 | ::: code-group 97 | 98 | ```js [nuxt.config.js] 99 | // within the module's config 100 | config: { 101 | foofoofoo: { 102 | apiKey: '', 103 | authDomain: '', 104 | databaseURL: '', // Optional 105 | projectId: '', 106 | storageBucket: '', 107 | messagingSenderId: '', 108 | appId: '', 109 | measurementId: '' 110 | }, 111 | faafaafaa: { 112 | // 113 | } 114 | } 115 | ``` 116 | 117 | ::: 118 | 119 | ## onFirebaseHosting 120 | 121 | - Type: `Boolean` or `Object` 122 | - Default: `false` 123 | 124 | If your application is hosted on Firebase hosting, you can enable this flag in order to load the newest Firebase scripts in the service workers directly from there instead of www.gstatic.com. 125 | 126 | ## lazy 127 | 128 | - Type: `Boolean` or `Object` 129 | - Default: `false` 130 | 131 | This allows lazy loading of all Firebase services. 132 | 133 | When set to `true`, all services are NOT loaded until you manually load them where needed. We additionally inject the following props for each activated service into the context: 134 | 135 | | Firebase Service | Shortcut | 136 | | ----------------- | ------------------------- | 137 | | Authentication | $fire.authReady() | 138 | | Realtime Database | $fire.databaseReady() | 139 | | Firestore | $fire.firestoreReady() | 140 | | Storage | $fire.storageReady() | 141 | | Functions | $fire.functionsReady() | 142 | | Messaging | $fire.messagingReady() | 143 | | Performance | $fire.performanceReady() | 144 | | Analytics | $fire.analyticsReady() | 145 | | Remote Config | $fire.remoteConfigReady() | 146 | | App Check | $fire.appCheckReady() | 147 | 148 | Simply call the `await this.$fire.serviceNameReady()` function before you access `this.$fire.serviceName` and the service gets dynamically loaded only when needed. 149 | 150 | If the services was already loaded previously, the service does not get loaded a second time. 151 | 152 | **Example:** 153 | 154 | ```js 155 | // 1. Load the service 156 | await this.$fire.authReady() 157 | 158 | // 2. Use the service 159 | await this.$fire.auth.createUserWithEmailAndPassword('foo@foo.foo', 'test') 160 | ``` 161 | 162 | ::: danger Be aware 163 | 164 | You can either enabled lazy loading for all services or none. 165 | 166 | ::: 167 | 168 | ## injectModule 169 | 170 | - Type: `Boolean` or `Object` 171 | - Default: `true` 172 | 173 | Whether to inject the entire [Firebase module](/guide/usage#firemodule) as `this.$fireModule` or not. 174 | 175 | ## terminateDatabasesAfterGenerate 176 | 177 | - Type: `Boolean` 178 | - Default: `false` 179 | 180 | Terminates the Firebase RealTime Database and Firestore after `nuxt generate` has been run. This fixes the below warning by Nuxt and speeds up generate time: 181 | 182 | > The command 'nuxt generate' finished but did not exit after 5s 183 | > This is most likely not caused by a bug in Nuxt 184 | > Make sure to cleanup all timers and listeners you or your plugins/modules start. 185 | > Nuxt will now force exit 186 | > 187 | > DeprecationWarning: Starting with Nuxt version 3 this will be a fatal error 188 | -------------------------------------------------------------------------------- /packages/docs/docs/guide/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ## General Usage 4 | 5 | This module injects two main utilities into your context, `$fire` and `$fireModule`. 6 | 7 | You can access these in almost any context using `app.$fire`/`app.$fireModule` or `this.$fire`/`this.$fireModule` - including store actions. 8 | 9 | ::: danger Understand the difference! 10 | 11 | While `$fire` contains the initialized service instances, `$fireModule` gives you access to the (not-initialized) **Firebase** module itself with all its static methods. 12 | 13 | ::: 14 | 15 | ### $fire 16 | 17 | `$fire` gives you access to the initialized service instances: 18 | 19 | | Firebase Service | Shortcut | Client/Server | 20 | | ----------------- | ------------------ | --------------- | 21 | | Authentication | $fire.auth | Client + Server | 22 | | Realtime Database | $fire.database | Client + Server | 23 | | Firestore | $fire.firestore | Client + Server | 24 | | Storage | $fire.storage | Client + Server | 25 | | Functions | $fire.functions | Client + Server | 26 | | Messaging | $fire.messaging | Client-only | 27 | | Performance | $fire.performance | Client-only | 28 | | Analytics | $fire.analytics | Client-only | 29 | | Remote Config | $fire.remoteConfig | Client-only | 30 | 31 | See [Firebase's official docs](https://firebase.google.com/docs/) for more usage information. 32 | 33 | ::: warning Be aware 34 | 35 | Please be aware that some services are not available on server-side. In universal code, you can wrap your code in `if (process.client) {}` so it only gets executed on the client-side. 36 | 37 | ::: 38 | 39 | ### $fireModule 40 | 41 | `$fireModule` gives you access to the **Firebase** modules themselves with all their static methods. 42 | 43 | | Firebase Module | Shortcut | 44 | | --------------------- | ------------------------ | 45 | | firebase.auth | $fireModule.auth | 46 | | firebase.database | $fireModule.database | 47 | | firebase.firestore | $fireModule.firestore | 48 | | firebase.storage | $fireModule.storage | 49 | | firebase.functions | $fireModule.functions | 50 | | firebase.messaging | $fireModule.messaging | 51 | | firebase.performance | $fireModule.performance | 52 | | firebase.analytics | $fireModule.analytics | 53 | | firebase.remoteConfig | $fireModule.remoteConfig | 54 | 55 | ## Examples 56 | 57 | Access Firebase Authentication in a component method: 58 | 59 | ```js 60 | export default { 61 | methods: { 62 | async createUser() { 63 | try { 64 | await this.$fire.auth.createUserWithEmailAndPassword( 65 | 'foo@foo.foo', 66 | 'test' 67 | ) 68 | } catch (e) { 69 | handleError(e) 70 | } 71 | }, 72 | }, 73 | } 74 | ``` 75 | 76 | Access Firestore and it's Object in a vuex store action: 77 | 78 | ```js 79 | export default { 80 | async randomVuexAction({commit, state, rootState}, userId) { 81 | const ref = this.$fire.firestore.collection('users').doc(userId) 82 | try { 83 | await exerciseRef.update({ 84 | [`randomFoo.FooFoo`]: this.$fireModule.firestore.FieldValue.delete(), 85 | }) 86 | } catch (e) { 87 | return Promise.reject(e) 88 | } 89 | }, 90 | } 91 | ``` 92 | -------------------------------------------------------------------------------- /packages/docs/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: 'home' 3 | 4 | title: Nuxt Firebase 5 | titleTemplate: Easily integrate Firebase into your Nuxt project 6 | 7 | hero: 8 | name: Nuxt Firebase 9 | text: Documentation 10 | tagline: Easily integrate Firebase into your Nuxt project 11 | image: 12 | src: /icon.png 13 | alt: Nuxt Firebase Logo 14 | actions: 15 | - theme: brand 16 | text: Get Started 17 | link: /guide/ 18 | - theme: alt 19 | text: View on GitHub 20 | link: https://github.com/nuxt-community/firebase-module 21 | 22 | features: 23 | - title: Simple Setup 24 | details: Minimal setup required to integrate all Firebase services into your Nuxt.js application. 25 | - title: Performant 26 | details: The module uses dynamic imports of each individual Firebase service to reduce bundle sizes and improve performance. 27 | - title: Additional Features 28 | details: Enjoy the benefits of additional features such as automated setup of .onAuthStateChanged() for Firebase Authentication and more. 29 | --- 30 | -------------------------------------------------------------------------------- /packages/docs/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/docs/docs/public/favicon.ico -------------------------------------------------------------------------------- /packages/docs/docs/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/docs/docs/public/icon.png -------------------------------------------------------------------------------- /packages/docs/docs/public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/docs/docs/public/logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/docs/docs/public/preview-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/docs/docs/public/preview-dark.png -------------------------------------------------------------------------------- /packages/docs/docs/public/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/firebase-module/a3a111dd5bb4e8e3da11b4c57f37ac68362402b6/packages/docs/docs/public/preview.png -------------------------------------------------------------------------------- /packages/docs/docs/public/service-worker.js: -------------------------------------------------------------------------------- 1 | // force clearing previous service worker 2 | self.addEventListener('install', function (e) { 3 | self.skipWaiting() 4 | }) 5 | 6 | self.addEventListener('activate', function (e) { 7 | self.registration 8 | .unregister() 9 | .then(function () { 10 | return self.clients.matchAll() 11 | }) 12 | .then(function (clients) { 13 | clients.forEach((client) => client.navigate(client.url)) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/all-services.md: -------------------------------------------------------------------------------- 1 | # All Services 2 | 3 | All services have the following options: 4 | 5 | ::: code-group 6 | 7 | ```js [nuxt.config.js] 8 | [serviceName]: { 9 | static: false, // default 10 | preload: false, // default 11 | chunkName: process.env.NODE_ENV !== 'production' ? `firebase-${serviceName}` : '[id]' // default 12 | } 13 | ``` 14 | 15 | ::: 16 | 17 | ## static 18 | 19 | By default, each service gets imported dynamically, which splits them into separate chunks. If `static = true` however, we import them statically, so the services are bundled into `vendors.app.js`. 20 | 21 | ```js 22 | // static: false (default) 23 | await import 'firebase/auth' 24 | // static: true 25 | import 'firebase/auth' 26 | ``` 27 | 28 | ## preload 29 | 30 | Preloads dynamically loaded services. More information [here](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules). 31 | 32 | ::: warning Be aware 33 | 34 | Only applies if `static === false`. 35 | 36 | ::: 37 | 38 | ## chunkName 39 | 40 | By default, the dynamically imported services are named `vendors.firebase-${serviceName}.js` in development mode, and `[id]` in production mode (`process.env.NODE_ENV === 'production'`). If you want to change this behaviour, you can do so with this option. 41 | 42 | ::: warning Be aware 43 | 44 | Only applies if `static === false`. 45 | 46 | ::: 47 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/analytics.md: -------------------------------------------------------------------------------- 1 | # analytics 2 | 3 | ::: danger Client-only 4 | 5 | Make sure to wrap universal code in `if (process.client) {}`. 6 | 7 | ::: 8 | 9 | Initializes **Firebase Analytics** and makes it available via `$fire.analytics` and `$fireModule.analytics`. 10 | 11 | - Type: `Boolean` or `Object` 12 | - Default: `false` 13 | 14 | ::: code-group 15 | 16 | ```js [nuxt.config.js] 17 | analytics: { 18 | collectionEnabled: true // default 19 | } 20 | ``` 21 | 22 | ::: 23 | 24 | ## collectionEnabled 25 | 26 | Allows to disable analytics collection. Usefull to disable analytics in development mode or before fullfillment of legal obligation. 27 | 28 | Can be enabled back via `$fireAnalytics.setAnalyticsCollectionEnabled(true)`. 29 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/app-check.md: -------------------------------------------------------------------------------- 1 | # appCheck 2 | 3 | ::: danger Client-only 4 | 5 | Make sure to wrap universal code in `if (process.client) {}`. 6 | 7 | ::: 8 | 9 | Initializes **Firebase App Check** and makes it available via `$fire.appCheck` and `$fireModule.appCheck`. 10 | 11 | - Type: `Boolean` or `Object` 12 | - Default: `false` 13 | 14 | ::: code-group 15 | 16 | ```js [nuxt.config.js] 17 | appCheck: { 18 | debugToken: false, // default 19 | } 20 | ``` 21 | 22 | ::: 23 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/database.md: -------------------------------------------------------------------------------- 1 | # database 2 | 3 | Initializes **Firebase Realtime Database** and makes it available via `$fire.database` and `$fireModule.database`. 4 | 5 | - Type: `Boolean` or `Object` 6 | - Default: `false` 7 | 8 | ::: code-group 9 | 10 | ```js [nuxt.config.js] 11 | database: { 12 | emulatorPort: 9000, 13 | emulatorHost: 'localhost', 14 | } 15 | ``` 16 | 17 | ::: 18 | 19 | ## emulatorPort 20 | 21 | - Type: `Integer` 22 | - Default: `null` 23 | 24 | Sets up `useEmulator("localhost", EMULATOR_PORT)` to point to a RealtimeDatabase emulator running locally. 25 | 26 | More information in the official Firebase [Emulator Docs](https://firebase.google.com/docs/emulator-suite/connect_rtdb). 27 | 28 | ::: info 29 | To not use the emulator in production you can do the following: 30 | 31 | ```js 32 | emulatorPort: process.env.NODE_ENV === 'development' ? 9000 : undefined 33 | ``` 34 | 35 | ::: 36 | 37 | ## emulatorHost 38 | 39 | - Type: `String` 40 | - Default: `localhost`, 41 | 42 | Changes the host used for the emulator. Only applies if the emulatorPort is set. 43 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/firestore.md: -------------------------------------------------------------------------------- 1 | # firestore 2 | 3 | Initializes **Firebase Firestore** and makes it available via `$fire.firestore` and `$fireModule.firestore`. 4 | 5 | - Type: `Boolean` or `Object` 6 | - Default: `false` 7 | 8 | ::: code-group 9 | 10 | ```js [nuxt.config.js] 11 | firestore: { 12 | memoryOnly: false, // default 13 | chunkName: process.env.NODE_ENV !== 'production' ? 'firebase-auth' : '[id]', // default 14 | enablePersistence: true, 15 | emulatorPort: 8080, 16 | emulatorHost: 'localhost', 17 | settings: { 18 | // Firestore Settings - currently only works in SPA mode 19 | } 20 | } 21 | ``` 22 | 23 | ::: 24 | 25 | ## memoryOnly 26 | 27 | With this flag set to true, the _memory-only_ build is loaded as mentioned [here](https://firebase.google.com/support/release-notes/js#version_7130_-_march_26_2020). 28 | 29 | - Type: `Boolean` or `Object` 30 | - Default: `false` 31 | 32 | ## enablePersistence 33 | 34 | Enables persistence in web apps. 35 | 36 | - Type: `Boolean` or `Object` 37 | - Default: `false` 38 | 39 | ::: code-group 40 | 41 | ```js [nuxt.config.js] 42 | firestore: { 43 | // ... 44 | enablePersistence: true 45 | } 46 | 47 | // or 48 | 49 | firestore: { 50 | // ... 51 | enablePersistence: { 52 | /** 53 | * Whether to synchronize the in-memory state of multiple tabs. Setting this 54 | * to 'true' in all open tabs enables shared access to local persistence, 55 | * shared execution of queries and latency-compensated local document updates 56 | * across all connected instances. 57 | * 58 | * To enable this mode, `synchronizeTabs:true` needs to be set globally in all 59 | * active tabs. If omitted or set to 'false', `enablePersistence()` will fail 60 | * in all but the first tab. 61 | */ 62 | synchronizeTabs: true 63 | } 64 | } 65 | ``` 66 | 67 | ::: 68 | 69 | More information [here](https://firebase.google.com/docs/firestore/manage-data/enable-offline). 70 | 71 | ## emulatorPort 72 | 73 | - Type: `Integer` 74 | - Default: `null` 75 | 76 | Sets up `useEmulator("localhost", EMULATOR_PORT)` to point to a Firestore emulator running locally. 77 | 78 | More information in the official Firebase [Emulator Docs](https://firebase.google.com/docs/emulator-suite/connect_firestore). 79 | 80 | ::: info 81 | 82 | To not use the emulator in production you can do the following: 83 | 84 | ```js 85 | emulatorPort: process.env.NODE_ENV === 'development' ? 8080 : undefined 86 | ``` 87 | 88 | ::: 89 | 90 | ## emulatorHost 91 | 92 | - Type: `String` 93 | - Default: `localhost`, 94 | 95 | Changes the host used for the emulator. Only applies if the emulatorPort is set. 96 | 97 | ## settings 98 | 99 | Adds settings to your Firebase initialization, e.g. `host` or `ssl`. 100 | See more [here](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Settings). 101 | 102 | ::: warning Important 103 | 104 | When using settings() in Universal mode (see [this issue](https://github.com/nuxt-community/firebase-module/issues/116)), you need to set `runInNewContext` to `false` in your nuxt.config.js like so: 105 | 106 | ::: code-group 107 | 108 | ```js [nuxt.config.js] 109 | // Add this to your nuxt.config.js 110 | render: { 111 | bundleRenderer: { 112 | runInNewContext: false 113 | } 114 | }, 115 | ``` 116 | 117 | ::: 118 | 119 | ::: 120 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/functions.md: -------------------------------------------------------------------------------- 1 | # functions 2 | 3 | Initializes **Firebase Functions** and makes it available via `$fire.functions` and `$fireModule.functions`. 4 | 5 | - Type: `Boolean` or `Object` 6 | - Default: `false` 7 | 8 | ::: code-group 9 | 10 | ```js [nuxt.config.js] 11 | functions: { 12 | location: 'us-central1', 13 | emulatorPort: 12345, 14 | emulatorHost: 'http://10.10.10.3', 15 | } 16 | ``` 17 | 18 | ::: 19 | 20 | ## location 21 | 22 | - Type: `String` 23 | - Default: `us-central1` 24 | 25 | More information [here](https://firebase.google.com/docs/functions/locations). 26 | 27 | ## emulatorPort 28 | 29 | - Type: `Integer` 30 | - Default: `null` 31 | 32 | Sets up `useFunctionsEmulator("http://localhost:EMULATOR_PORT")` to point to a Cloud Functions emulator running locally instead of the production one. 33 | 34 | More information in the official Firebase [API Docs]() and [Functions Docs](https://firebase.google.com/docs/functions/local-emulator). 35 | 36 | ## emulatorHost 37 | 38 | - Type: `String` 39 | - Default: `http://localhost`, 40 | 41 | Changes the host used for the Cloud Functions emulator. Only applies if the emulatorPort is set. 42 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/messaging.md: -------------------------------------------------------------------------------- 1 | # messaging 2 | 3 | ::: danger Client-only 4 | 5 | Make sure to wrap universal code in `if (process.client) {}`. 6 | 7 | ::: 8 | 9 | Initializes **Firebase Messaging** and makes it available via `$fire.messaging` and `$fireModule.messaging`. 10 | Message payload is expected as defined by Firebase [here](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushConfig). 11 | 12 | - Type: `Boolean` or `Object` 13 | - Default: `false` 14 | 15 | ::: code-group 16 | 17 | ```js [nuxt.config.js] 18 | messaging: { 19 | createServiceWorker: false, 20 | actions: [ 21 | { 22 | action: 'randomName', 23 | url: 'randomUrl' 24 | } 25 | ], 26 | fcmPublicVapidKey: '' // OPTIONAL : Sets vapid key for FCM after initialization 27 | } 28 | ``` 29 | 30 | ::: 31 | 32 | ## createServiceWorker 33 | 34 | - Type: `Boolean` or `Object` 35 | - Default: `false` 36 | 37 | Setting the **createServiceWorker** flag to true automatically creates a service worker called `firebase-messaging-sw.js` in your static folder. The service worker is fully configured for FCM with the newest Firebase scripts. 38 | 39 | ## actions 40 | 41 | > Only works if `createServiceWorker === true` 42 | 43 | An array of actions for which a `notificationClick` handler should be registered in the service worker that opens the defined url for the specific action sent by the payload. 44 | 45 | ```js 46 | { 47 | action: 'randomName', 48 | url: 'randomUrl' 49 | } 50 | ``` 51 | 52 | Make sure to define the action in your payload like so: 53 | 54 | ```js 55 | const message = { 56 | // ... 57 | webpush: { 58 | notification: { 59 | actions: [ 60 | { 61 | action: 'randomName', 62 | title: 'Go to URL', 63 | }, 64 | ], 65 | }, 66 | }, 67 | // ... 68 | } 69 | await messaging.send(message) 70 | ``` 71 | 72 | ## inject 73 | 74 | > Only works if `createServiceWorker === true` 75 | 76 | Injects a string (or an entire code snippet) at the end of the messaging service worker. This allows you to extend the service worker to your liking. 77 | 78 | #### Simple example: 79 | 80 | ::: code-group 81 | 82 | ```js [nuxt.config.js] 83 | ... 84 | inject: 'console.log("This is the end of the service worker.")', 85 | ... 86 | ``` 87 | 88 | ::: 89 | 90 | #### Advanced example: 91 | 92 | ::: code-group 93 | 94 | ```js [nuxt.config.js] 95 | const fs = require('fs') 96 | ... 97 | inject: fs.readFileSync('./javascriptFileWithCodeToBeInjected.js', 'utf8'), 98 | ... 99 | ``` 100 | 101 | ::: 102 | 103 | ## fcmPublicVapidKey 104 | 105 | Allows FCM to use the VAPID key credential when sending message requests to different push services, see more [here](https://firebase.google.com/docs/cloud-messaging/js/client). 106 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/performance.md: -------------------------------------------------------------------------------- 1 | # performance 2 | 3 | ::: danger Client-only 4 | 5 | Make sure to wrap universal code in `if (process.client) {}`. 6 | 7 | ::: 8 | 9 | Initializes **Firebase Performance** and makes it available via `$fire.performance` and `$fireModule.performance`. 10 | 11 | - Type: `Boolean` 12 | - Default: `false` 13 | 14 | ::: code-group 15 | 16 | ```js [nuxt.config.js] 17 | performance: true 18 | ``` 19 | 20 | ::: 21 | 22 | Currently, there are no advanced options available. 23 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/remote-config.md: -------------------------------------------------------------------------------- 1 | # remoteConfig 2 | 3 | ::: danger Client-only 4 | 5 | Make sure to wrap universal code in `if (process.client) {}`. 6 | 7 | ::: 8 | 9 | Initializes **Firebase Remote Config** and makes it available via `$fire.remoteConfig` and `$fireModule.remoteConfig`. 10 | 11 | - Type: `Boolean` or `Object` 12 | - Default: `false` 13 | 14 | ::: code-group 15 | 16 | ```js [nuxt.config.js] 17 | remoteConfig: { 18 | settings: { 19 | fetchTimeoutMillis: 60000, // default 20 | minimumFetchIntervalMillis: 43200000, // default 21 | }, 22 | defaultConfig: { 23 | 'welcome_message': 'Welcome' 24 | } 25 | } 26 | ``` 27 | 28 | ::: 29 | -------------------------------------------------------------------------------- /packages/docs/docs/service-options/storage.md: -------------------------------------------------------------------------------- 1 | # storage 2 | 3 | Initializes **Firebase Storage** and makes it available via `$fire.storage` and `$fireModule.storage`. 4 | 5 | - Type: `Boolean` 6 | - Default: `false` 7 | 8 | ::: code-group 9 | 10 | ```js [nuxt.config.js] 11 | storage: { 12 | emulatorPort: 9199, 13 | emulatorHost: 'localhost', 14 | } 15 | ``` 16 | 17 | ::: 18 | 19 | ## emulatorPort 20 | 21 | - Type: `Integer` 22 | - Default: `null` 23 | 24 | Sets up `useEmulator("localhost:EMULATOR_PORT")` to point to an Storage emulator running locally instead of the production one. 25 | 26 | More information in the official Firebase [Guide to connect your app to the Cloud Storage Emulator](https://firebase.google.com/docs/emulator-suite/connect_storage). 27 | 28 | ::: info 29 | 30 | To not use the emulator in production you can do the following: 31 | 32 | ```js 33 | emulatorPort: process.env.NODE_ENV === 'development' ? 9199 : undefined 34 | ``` 35 | 36 | ::: 37 | 38 | ## emulatorHost 39 | 40 | - Type: `String` 41 | - Default: `localhost`, 42 | 43 | Changes the host used for the Storage emulator. Only applies if the emulatorPort is set. 44 | -------------------------------------------------------------------------------- /packages/docs/docs/tutorials/ssr.md: -------------------------------------------------------------------------------- 1 | # Firebase Auth with SSR 2 | 3 | This module provides an option for the easy setup of **server-side authentication** as described in [this article](https://firebase.google.com/docs/auth/web/service-worker-sessions) of the official Documentation. 4 | 5 | ::: info Please Note: 6 | 7 | This **does not authenticate the Firebase Client SDK on the server**. While you will be able to know if a user is logged in or not and have access to its simplified properties, you **won't be able to do authenticated calls** on server-side. 8 | 9 | This means that all calls on server-side (e.g. fetching data via Firestore in fetch-hooks), which are protected by security rules, will still fail with _insufficient privileges._ 10 | 11 | Reason for this is that the Firebase JS SDK is a client-side library that is not built for authenticating multiple users. See steps 4 and 5 for an **experimental** approach to solve this issue. 12 | 13 | ::: 14 | 15 | ## Step 0 - Install Dependencies 16 | 17 | Install `firebase-admin` and `@nuxtjs/pwa`: 18 | 19 | ::: code-group 20 | 21 | ```bash [yarn] 22 | yarn add firebase-admin @nuxtjs/pwa 23 | ``` 24 | 25 | ```bash [npm] 26 | npm install firebase-admin @nuxtjs/pwa 27 | ``` 28 | 29 | ::: 30 | 31 | ## Step 1 - Enable SSR functionality and configure workbox to include the auth service worker 32 | 33 | Use the [auth.ssr option](/service-options/auth#ssr). 34 | 35 | In `nuxt.config.js`: 36 | 37 | ::: code-group 38 | 39 | ```js [nuxt.config.js] 40 | module.exports = { 41 | // ... 42 | modules: [ 43 | // ... 44 | '@nuxtjs/pwa', 45 | '@nuxtjs/firebase' 46 | ], 47 | firebase: { 48 | // ... 49 | services: { 50 | auth: { 51 | ssr: true 52 | } 53 | // ... 54 | } 55 | }, 56 | pwa: { 57 | // disable the modules you don't need 58 | meta: false, 59 | icon: false, 60 | // if you omit a module key form configuration sensible defaults will be applied 61 | // manifest: false, 62 | 63 | workbox: { 64 | importScripts: [ 65 | // ... 66 | '/firebase-auth-sw.js' 67 | ], 68 | // by default the workbox module will not install the service worker in dev environment to avoid conflicts with HMR 69 | // only set this true for testing and remember to always clear your browser cache in development 70 | dev: process.env.NODE_ENV === 'development', 71 | } 72 | } 73 | }, 74 | ``` 75 | 76 | ::: 77 | 78 | ## Step 2 - Setup Mutations and/or Actions to handle User authentication 79 | 80 | If you don't rely on a full `firebase.User` object you can reuse the client action/mutation configured for [`auth.initialize`](/service-options/auth#initialize). 81 | See [Step 3](#step-3---retrieve-the-server-user) to verify if required properties are present. 82 | 83 | Example action: 84 | 85 | ```js 86 | async onAuthStateChangedAction({ commit, dispatch }, { authUser, claims }) { 87 | if (!authUser) { 88 | await dispatch('cleanupAction') 89 | 90 | return 91 | } 92 | 93 | // you can request additional fields if they are optional (e.g. photoURL) 94 | const { uid, email, emailVerified, displayName, photoURL } = authUser 95 | 96 | commit('SET_USER', { 97 | uid, 98 | email, 99 | emailVerified, 100 | displayName, 101 | photoURL, // results in photoURL being undefined for server auth 102 | // use custom claims to control access (see https://firebase.google.com/docs/auth/admin/custom-claims) 103 | isAdmin: claims.custom_claim 104 | }) 105 | } 106 | ``` 107 | 108 | Example mutation: 109 | 110 | ```js 111 | ON_AUTH_STATE_CHANGED_MUTATION(state, { authUser, claims }) { 112 | // you can request additional fields if they are optional (e.g. photoURL) 113 | const { uid, email, emailVerified, displayName, photoURL } = authUser 114 | 115 | state.authUser = { 116 | uid, 117 | displayName, 118 | email, 119 | emailVerified, 120 | photoURL: photoURL || null, // results in photoURL being null for server auth 121 | // use custom claims to control access (see https://firebase.google.com/docs/auth/admin/custom-claims) 122 | isAdmin: claims.custom_claim 123 | } 124 | } 125 | ``` 126 | 127 | ## Step 3 - Retrieve the server user 128 | 129 | In the nuxtServerInit action in your vuex store you can now access the authUser under the `res.locals.user` property as shown below. 130 | 131 | ::: warning Be aware 132 | 133 | The server user object is not a full `firebase.User`, since it is reproduced from the user claims, it provides only the following properties: 134 | 135 | - `uid`: The users uid 136 | - `email`: The users email 137 | - `emailVerified`: If the email was verified 138 | - `displayName`: The users display name 139 | - `allClaims`: All claims from the [admin.auth.DecodedIdToken](https://firebase.google.com/docs/reference/admin/node/admin.auth.DecodedIdToken) 140 | - `idToken`: The current idToken 141 | 142 | ::: 143 | 144 | ```js 145 | // Store action called nuxtServerInit: 146 | async nuxtServerInit({ dispatch, commit }, { res }) { 147 | if (res && res.locals && res.locals.user) { 148 | const { allClaims: claims, idToken: token, ...authUser } = res.locals.user 149 | 150 | await dispatch('onAuthStateChangedAction', { 151 | authUser, 152 | claims, 153 | token 154 | }) 155 | 156 | // or 157 | 158 | commit('ON_AUTH_STATE_CHANGED_MUTATION', { authUser, claims, token }) 159 | } 160 | } 161 | ``` 162 | 163 | That's it. You receive a server-verified authUser object and can do with it whatever you want in nuxtServerInit. 164 | 165 | ## Step 4 - (Experimental) Authorize the admin SDK 166 | 167 | 168 | 169 | If you [authorize the admin SDK](/service-options/auth#firebase-admin-authorization) the authUser will be augmented to a full [`admin.auth.UserRecord`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserRecord) with an additional `allClaims` property. 170 | 171 | ## Step 5 - (Experimental) Enable server side client SDK login 172 | 173 | 174 | 175 | If you need client SDK services for hydration on page load you can enable this feature in the [options](/service-options/auth#server-side-firebase-client-sdk-login). 176 | -------------------------------------------------------------------------------- /packages/docs/docs/tutorials/typescript.md: -------------------------------------------------------------------------------- 1 | # Usage with Typescript 2 | 3 | The module comes with types by providing a declaration file (`index.d.ts`) within the npm package. 4 | 5 | All you need to do is to include "@nuxtjs/firebase" in your tsconfig.json types like so: 6 | 7 | ```jsonc 8 | // tsconfig.json 9 | { 10 | "compilerOptions": { 11 | "types": [ 12 | "node", 13 | "@nuxt/types", 14 | // ... 15 | "@nuxtjs/firebase" 16 | ] 17 | } 18 | } 19 | ``` 20 | 21 | Don't forget to restart your IDE (e.g. VSCODE) after adding the types. 22 | 23 | [nuxt-fire-demo](https://github.com/lupas/nuxt-fire-demo) shows working examples of nuxt-fire with Typescript. 24 | -------------------------------------------------------------------------------- /packages/docs/docs/tutorials/vuexfire.md: -------------------------------------------------------------------------------- 1 | # Usage with vuexfire 2 | 3 | Vuexfire and this module work very well together. 4 | 5 | This [example](https://github.com/lupas/nuxt-fire-vuexfire-example) shows how to use these two packages together, working with SSR. 6 | -------------------------------------------------------------------------------- /packages/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/firebase-docs", 3 | "version": "8.2.2", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "doc": "docs" 8 | }, 9 | "scripts": { 10 | "dev": "vitepress dev docs", 11 | "build": "vitepress build docs" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "vitepress": "^1.0.0-alpha.51", 17 | "vue": "^3.2.47" 18 | }, 19 | "dependencies": { 20 | "focus-visible": "^5.2.0", 21 | "sass": "^1.58.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/firebase-module/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/firebase-module/.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | 7 | # Plugin 8 | lib/plugins/*.js 9 | lib/plugins/services/*.js 10 | lib/serverMiddleware/*.js 11 | lib/sw-templates/*.js 12 | types/index.d.ts 13 | -------------------------------------------------------------------------------- /packages/firebase-module/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint' 5 | }, 6 | extends: [ 7 | 'prettier', 8 | 'prettier/vue', 9 | 'plugin:prettier/recommended', 10 | '@nuxtjs' 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/firebase-module/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt* 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | 11 | yarn.lock 12 | !docs/yarn.lock 13 | sw.* 14 | .husky -------------------------------------------------------------------------------- /packages/firebase-module/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | arrowParens: 'always', 4 | semi: false, 5 | } 6 | -------------------------------------------------------------------------------- /packages/firebase-module/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | test: { 4 | plugins: ['@babel/plugin-syntax-dynamic-import', 'dynamic-import-node'], 5 | presets: [ 6 | [ 7 | '@babel/preset-env', 8 | { 9 | targets: { 10 | node: 'current', 11 | }, 12 | }, 13 | ], 14 | ], 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /packages/firebase-module/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@commitlint/config-conventional' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /packages/firebase-module/husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 4 | 'pre-commit': 'yarn lint', 5 | 'pre-push': 'yarn lint' 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/firebase-module/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverage: true, 3 | collectCoverageFrom: [ 4 | 'lib/**/*.js', 5 | '!lib/plugins/**/*.js', 6 | '!lib/serverMiddleware/*.js', 7 | '!lib/sw-templates/*.js', 8 | ], 9 | moduleFileExtensions: ['ts', 'js', 'json'], 10 | testEnvironment: 'node', 11 | transform: { 12 | '^.+\\.js$': 'babel-jest', 13 | }, 14 | transformIgnorePatterns: ['node_modules'], 15 | } 16 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins 2 | 3 | The files within the "plugins" folder will be parsed and copied to the /dist folder of the built project. These are then imported as nuxt-plugins. 4 | 5 | [Lodas Template](https://lodash.com/docs/4.17.15#template) is used to parse these plugins. 6 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/main.js: -------------------------------------------------------------------------------- 1 | import createApp from './app.js' 2 | <% 3 | const { enabledServices } = options 4 | serverServices = enabledServices.filter(service => !service.clientOnly) 5 | clientServices = enabledServices 6 | 7 | for (const service of enabledServices) { %> 8 | <%= `import ${service.id}Service from './service.${service.id}.js'`%><% 9 | } %> 10 | 11 | const appConfig = <%= serialize(options.config) %> 12 | 13 | export default async (ctx, inject) => { 14 | 15 | <%/**************************************** 16 | **************** LAZY MODE ************** 17 | ****************************************/%> 18 | <% if (options.lazy) { %> 19 | let firebase, session 20 | let firebaseReady = false 21 | 22 | const fire = { 23 | async appReady() { 24 | if (!firebaseReady) { 25 | ({ firebase, session } = await createApp(appConfig, ctx)) 26 | firebaseReady = true; 27 | 28 | <% if (options.injectModule) { %> 29 | forceInject(ctx, inject, "fireModule", firebase) 30 | <% } %> 31 | } 32 | return session 33 | }, 34 | async ready() { 35 | await fire.appReady() 36 | 37 | let servicePromises = [] 38 | 39 | <% if (serverServices.length) { %> 40 | if (process.server) { 41 | servicePromises = [ 42 | <%= serverServices.reduce((acc, service) => `${acc}fire.${service.id}Ready(),\n `, '') %> 43 | ] 44 | } 45 | <% } %> 46 | 47 | <% if (clientServices.length) { %> 48 | if (process.client) { 49 | servicePromises = [ 50 | <%= clientServices.reduce((acc, service) => `${acc}fire.${service.id}Ready(),\n `, '') %> 51 | ] 52 | } 53 | <% } %> 54 | 55 | await Promise.all(servicePromises) 56 | return session 57 | } 58 | } 59 | 60 | if (process.server) { 61 | <% for (service of serverServices) { %> 62 | <% const serviceName = service.id %> 63 | fire.<%= serviceName %> = null 64 | fire.<%= serviceName %>Ready = async () => { 65 | if (!fire.<%= serviceName %>) { 66 | await fire.appReady() 67 | fire.<%= serviceName %> = await <%= `${service.id}Service(session, firebase, ctx, inject)` %> 68 | } 69 | 70 | return fire.<%= serviceName %> 71 | } 72 | <% } %> 73 | } 74 | 75 | if (process.client) { 76 | <% for (service of clientServices) { %> 77 | <% const serviceName = service.id %> 78 | fire.<%= serviceName %> = null 79 | fire.<%= serviceName %>Ready = async () => { 80 | if (!fire.<%= serviceName %>) { 81 | await fire.appReady() 82 | fire.<%= serviceName %> = await <%= `${service.id}Service(session, firebase, ctx, inject)` %> 83 | } 84 | 85 | return fire.<%= serviceName %> 86 | } 87 | <% } %> 88 | } 89 | 90 | inject('fire', fire) 91 | ctx.$fire = fire 92 | 93 | 94 | <%/**************************************** 95 | ************* NON-LAZY MODE ************* 96 | ****************************************/%> 97 | <% } else { %> 98 | const { firebase, session } = await createApp(appConfig, ctx) 99 | 100 | let servicePromises = [] 101 | 102 | <% if (serverServices.length) { %> 103 | if (process.server) { 104 | servicePromises = [ 105 | <%= serverServices.reduce((acc, service) => `${acc}${service.id}Service(session, firebase, ctx, inject),\n `, '') %> 106 | ] 107 | } 108 | <% } %> 109 | 110 | <% if (clientServices.length) { %> 111 | if (process.client) { 112 | servicePromises = [ 113 | <%= clientServices.reduce((acc, service) => `${acc}${service.id}Service(session, firebase, ctx, inject),\n `, '') %> 114 | ] 115 | } 116 | <% } %> 117 | 118 | const [ 119 | <%= enabledServices.map(service => service.id).join(',\n ') %> 120 | ] = await Promise.all(servicePromises) 121 | 122 | const fire = { 123 | <%= enabledServices.map(service => `${service.id}: ${service.id}`).join(',\n ') %> 124 | } 125 | 126 | <% if (options.injectModule) { %> 127 | inject('fireModule', firebase) 128 | ctx.$fireModule = firebase 129 | <% } %> 130 | 131 | inject('fire', fire) 132 | ctx.$fire = fire 133 | <% } %> 134 | } 135 | 136 | 137 | <%/************************************* 138 | ************* HELPERS******************** 139 | ****************************************/%> 140 | <%/** 141 | Custom inject function that is able to overwrite previously injected values, 142 | which original inject doesn't allow to do. 143 | This method is copied from https://github.com/nuxt-community/sentry-module/blob/master/lib/plugin.lazy.js#L189 144 | which is adapted from the inject method in nuxt/vue-app/template/index.js 145 | Fixes https://github.com/nuxt-community/firebase-module/issues/366 146 | **/%> 147 | function forceInject (ctx, inject, key, value) { 148 | inject(key, value) 149 | const injectKey = '$' + key 150 | ctx[injectKey] = value 151 | if (typeof window !== "undefined" && window.<%= globals.nuxt %>) { 152 | // If clause makes sure it's only run when ready() is called in a component, not in a plugin. 153 | window.<%= globals.nuxt %>.$options[injectKey] = value 154 | } 155 | } -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/analytics.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session, firebase) { 4 | // Can only be initiated on client side 5 | if (!process.client) { 6 | return 7 | } 8 | 9 | <% if (!serviceOptions.static) { %> 10 | <%= writeImportStatement(options) %> 11 | <% } %> 12 | 13 | // Only initialize it if the Browser supports it 14 | const isSupported = await firebase.analytics.isSupported() 15 | if (!isSupported) { 16 | console.info('[@nuxtjs/firebase]: Firebase Analytics was not initialized because it is not supported on this browser.') 17 | return 18 | } 19 | 20 | const analyticsService = session.<%= serviceMapping.id %>() 21 | 22 | <% if ('collectionEnabled' in serviceOptions) { %> 23 | // In development we want to disable analytics collection 24 | analyticsService.setAnalyticsCollectionEnabled(<%= !!serviceOptions.collectionEnabled %>) 25 | <% } %> 26 | 27 | return analyticsService 28 | } 29 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/app.js: -------------------------------------------------------------------------------- 1 | <%= options.writeStaticImports(options) %> 2 | 3 | export default async function createApp(config, {res}) { 4 | <%= (statement = options.writeImportStatement(options)) 5 | && `const firebaseModule = ${statement}` 6 | %> 7 | const firebase = firebaseModule.default 8 | 9 | <% if (typeof options.sessions === 'object') { %> 10 | /************************************************* 11 | * If Firebase "Auth SSR serverLogin Option" is on 12 | *************************************************/ 13 | let session 14 | if (process.server && res && res.locals && res.locals.user) { 15 | const { default: SessionManager } = await import('@nuxtjs/firebase/lib/utils/auth-ssr/ssr-auth-session-manager.js') 16 | const manager = new SessionManager(firebase, { 17 | config, 18 | sessions: <%= serialize(options.sessions) %> 19 | }) 20 | // Resolve the firebase app corresponding to the server user 21 | session = await manager.startSession(res.locals.user.uid) 22 | res.locals._session = session 23 | res.locals._manager = manager 24 | } else { 25 | session = firebase.apps.find(a => a.name === '[DEFAULT]') || firebase.initializeApp(config) 26 | } 27 | 28 | <% } else { %> 29 | /***************************************************** 30 | * Without "Auth SSR serverLogin Option" -> normal init 31 | *****************************************************/ 32 | if (!firebase.apps.length) { 33 | firebase.initializeApp(config) 34 | } 35 | const session = firebase.apps[0] 36 | <% } %> 37 | 38 | return { 39 | firebase, 40 | session 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/appCheck.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | // Can only be initiated on client side 5 | if (!process.client) { 6 | return 7 | } 8 | 9 | <% if (!serviceOptions.static) { %> 10 | <%= writeImportStatement(options) %> 11 | <% } %> 12 | 13 | <% /* Uses debug config, if debug token option is set. */ %> 14 | <% if (serviceOptions.debugToken) { %> 15 | self.FIREBASE_APPCHECK_DEBUG_TOKEN = <%= serviceOptions.debugToken %> 16 | <% } %> 17 | 18 | const appCheckService = session.<%= serviceMapping.id %>() 19 | 20 | return appCheckService 21 | } 22 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/auth.initialize.js: -------------------------------------------------------------------------------- 1 | // runs the functions once BEFORE the root Vue.js Application is instantiated. 2 | export default ({ $fireAuthStore }) => { 3 | // Can only be initiated on client side 4 | if (!process.client) { 5 | return 6 | } 7 | 8 | return $fireAuthStore.subscribe() 9 | } 10 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/auth.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement } = options %> 2 | 3 | <% const hasOnAuthStateChangedMutation = (serviceOptions.initialize && typeof serviceOptions.initialize.onAuthStateChangedMutation === 'string') %> 4 | <% const hasOnAuthStateChangedAction = (serviceOptions.initialize && typeof serviceOptions.initialize.onAuthStateChangedAction === 'string') %> 5 | <% const hasOnAuthStateChanged = (hasOnAuthStateChangedMutation || hasOnAuthStateChangedAction) %> 6 | <% const onIdTokenChangedMutation = (serviceOptions.initialize && typeof serviceOptions.initialize.onIdTokenChangedMutation === 'string') %> 7 | <% const onIdTokenChangedAction = (serviceOptions.initialize && typeof serviceOptions.initialize.onIdTokenChangedAction === 'string') %> 8 | <% const hasIdTokenChanged = (onIdTokenChangedMutation || onIdTokenChangedAction) %> 9 | 10 | export default async function (session, firebase, ctx, inject) { 11 | 12 | <% if (!serviceOptions.static) { %> 13 | <%= writeImportStatement(options) %> 14 | <% } %> 15 | const authService = session.<%= serviceMapping.id %>() 16 | 17 | <% /* Uses emulator, if emulatorPort is set. */ %> 18 | <% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %> 19 | <% const emulatorHost = 20 | typeof serviceOptions.emulatorHost === 'string' 21 | ? serviceOptions.emulatorHost 22 | : 'http://localhost' 23 | %> 24 | authService.useEmulator('<%= `${emulatorHost}` %>:<%= `${serviceOptions.emulatorPort}` %>'<% if (serviceOptions.disableEmulatorWarnings) { %><%= `, { disableWarnings: true }` %><% } %>) 25 | <% } %> 26 | 27 | <% if (serviceOptions.persistence) { %> 28 | if (process.client) { 29 | const persistence = firebase.auth.Auth.Persistence.<%= 30 | serviceOptions.persistence === 'session' 31 | ? 'SESSION' 32 | : serviceOptions.persistence === 'none' 33 | ? 'NONE' 34 | : 'LOCAL' 35 | %> 36 | try { 37 | await authService.setPersistence(persistence) 38 | } catch (err) { 39 | if (err.code === 'auth/invalid-persistence-type') { 40 | console.warn(`[@nuxtjs/firebase]: Invalid persistence type '${persistence}' provided`) 41 | } else if (err.code === 'auth/unsupported-persistence-type') { 42 | console.warn(`[@nuxtjs/firebase]: Persistence type '${persistence}' is not supported in this environment.`) 43 | } 44 | } 45 | } 46 | <% } %> 47 | 48 | <% if (serviceOptions.initialize) { %> 49 | // Sets up a listener, mutations and action for every onAuthStateChanged by Firebase. 50 | const fireAuthStore = { 51 | unsubscribe() { 52 | if (this.unsubscribeAuthStateListener) { 53 | this.unsubscribeAuthStateListener() 54 | delete this.unsubscribeAuthStateListener 55 | } 56 | if (this.unsubscribeIdTokenListener) { 57 | this.unsubscribeIdTokenListener() 58 | delete this.unsubscribeIdTokenListener 59 | } 60 | }, 61 | subscribe() { 62 | const promises = [] 63 | <% if (hasOnAuthStateChanged && !this.unsubscribeAuthStateListener) { %> 64 | promises.push(new Promise(resolve => { 65 | this.unsubscribeAuthStateListener = authService.onAuthStateChanged(async authUser => { 66 | const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null 67 | 68 | <% if (hasOnAuthStateChangedMutation) { %> 69 | ctx.store.commit(<%= serialize(serviceOptions.initialize.onAuthStateChangedMutation) %>, { authUser, claims }) 70 | <% } %> 71 | 72 | <% if (hasOnAuthStateChangedAction) { %> 73 | await ctx.store.dispatch(<%= serialize(serviceOptions.initialize.onAuthStateChangedAction) %>, { authUser, claims }) 74 | <% } %> 75 | 76 | resolve() 77 | }) 78 | })) 79 | <% } %> 80 | 81 | <% if (hasIdTokenChanged && !this.unsubscribeIdTokenListener) { %> 82 | promises.push(new Promise(resolve => { 83 | this.unsubscribeIdTokenListener = authService.onIdTokenChanged(async authUser => { 84 | const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null 85 | 86 | <% if (onIdTokenChangedMutation) { %> 87 | ctx.store.commit(<%= serialize(serviceOptions.initialize.onIdTokenChangedMutation) %>, { authUser, claims }) 88 | <% } %> 89 | 90 | <% if (onIdTokenChangedAction) { %> 91 | await ctx.store.dispatch(<%= serialize(serviceOptions.initialize.onIdTokenChangedAction) %>, { authUser, claims }) 92 | <% } %> 93 | 94 | resolve() 95 | }) 96 | })) 97 | <% } %> 98 | return Promise.all(promises) 99 | } 100 | } 101 | inject('fireAuthStore', fireAuthStore) 102 | <% } %> 103 | 104 | return authService 105 | } 106 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/auth.serverLogin.js: -------------------------------------------------------------------------------- 1 | import admin from 'firebase-admin' 2 | 3 | const config = <%= serialize(options.config) %> 4 | 5 | if (!admin.apps.length) { 6 | const credential = <%= 7 | options.credential === true 8 | ? 'admin.credential.applicationDefault()' 9 | : `admin.credential.cert(require(${serialize(options.credential)}))` 10 | %> 11 | 12 | admin.initializeApp({ 13 | credential, 14 | ...config 15 | }) 16 | } 17 | 18 | export default async ({ res }) => { 19 | if (res && res.locals && res.locals.user && res.locals.user.uid && res.locals._manager) { 20 | const uid = res.locals.user.uid 21 | const manager = res.locals._manager 22 | 23 | // if the user is already logged in to the session, return early 24 | const user = manager.getUser(uid) 25 | if (user) return 26 | 27 | try { 28 | // Retrieve a custom auth token from the users uid 29 | const customToken = await admin.auth().createCustomToken(uid) 30 | 31 | // attempt client sdk sign 32 | await manager.login(uid, customToken) 33 | } catch (error) { 34 | // @TODO: implement appropriate error handling, if at all necessary 35 | console.error(error) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/auth.ssr.js: -------------------------------------------------------------------------------- 1 | import admin from 'firebase-admin' 2 | 3 | const config = <%= serialize(options.config) %> 4 | 5 | const simulateUserRecord = ({ 6 | uid, 7 | email, 8 | email_verified: emailVerified, 9 | name: displayName 10 | }) => ({ 11 | uid, 12 | email, 13 | emailVerified, 14 | displayName 15 | }) 16 | 17 | if (!admin.apps.length) { 18 | <% if (options.credential) { %> 19 | const credential = <%= 20 | options.credential === true 21 | ? 'admin.credential.applicationDefault()' 22 | : `admin.credential.cert(require(${serialize(options.credential)}))` 23 | %> 24 | 25 | admin.initializeApp({ 26 | credential, 27 | ...config 28 | }) 29 | <% } else { %> 30 | admin.initializeApp(config) 31 | <% } %> 32 | } 33 | 34 | export default async ({ req, res }) => { 35 | if (!req || !req.headers.authorization) { 36 | return 37 | } 38 | 39 | // Parse the injected ID token from the request header. 40 | const authorizationHeader = req.headers.authorization || '' 41 | const components = authorizationHeader.split(' ') 42 | const idToken = components.length > 1 ? components[1] : '' 43 | 44 | try { 45 | // Try to verify the id token, additionally checking if the token was revoked 46 | const decodedToken = await admin.auth().verifyIdToken(idToken) 47 | 48 | if (decodedToken.uid) { 49 | const authUser = <%= 50 | options.credential 51 | ? 'await admin.auth().getUser(decodedToken.uid)' 52 | : 'simulateUserRecord(decodedToken)' 53 | %> 54 | 55 | res.locals = { 56 | ...res.locals, 57 | user: { 58 | ...authUser, 59 | allClaims: decodedToken, 60 | idToken, 61 | } 62 | } 63 | } 64 | } catch (e) { 65 | console.error(e) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/database.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | <% if (!serviceOptions.static) { %> 5 | <%= writeImportStatement(options) %> 6 | <% } %> 7 | 8 | const databaseService = session.<%= serviceMapping.id %>() 9 | 10 | <% /* Uses emulator, if emulatorPort is set. */ %> 11 | <% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %> 12 | <% const emulatorHost = 13 | typeof serviceOptions.emulatorHost === 'string' 14 | ? serviceOptions.emulatorHost 15 | : 'localhost' 16 | %> 17 | databaseService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>) 18 | <% } %> 19 | 20 | return databaseService 21 | } 22 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/firestore.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | <% if (!serviceOptions.static) { %> 5 | <%= writeImportStatement(options) %> 6 | <% } %> 7 | 8 | const firestoreService = session.<%= serviceMapping.id %>() 9 | 10 | <% if (typeof serviceOptions.settings === 'object') { %> 11 | firestoreService.settings(<%= serialize(serviceOptions.settings) %>) 12 | <% } %> 13 | 14 | <% /* Uses emulator, if emulatorPort is set. */ %> 15 | <% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %> 16 | <% const emulatorHost = 17 | typeof serviceOptions.emulatorHost === 'string' 18 | ? serviceOptions.emulatorHost 19 | : 'localhost' 20 | %> 21 | // If statement fixes Issue #390, only runs useEmulator when not yet called (relevant on server) 22 | if (process.client || firestoreService._delegate._settings.host === 'firestore.googleapis.com') { 23 | firestoreService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>) 24 | } 25 | <% } %> 26 | 27 | <% if (serviceOptions.enablePersistence) { %> 28 | // persistence should only be enabled client side 29 | if (process.client) { 30 | try { 31 | <% const enablePersistence = Object.assign({}, serviceOptions.enablePersistence) %> 32 | await firestoreService.enablePersistence(<%= serialize(enablePersistence) %>) 33 | } catch (err) { 34 | if (err.code == 'failed-precondition') { 35 | console.warn('[@nuxtjs/firebase]: Firestore Persistence not enabled. Multiple tabs open, persistence can only be enabled in one tab at a a time.') 36 | } else if (err.code == 'unimplemented') { 37 | console.info('[@nuxtjs/firebase]: Firestore Persistence not enabled. The current browser does not support all of the features required to enable persistence.') 38 | } 39 | } 40 | } 41 | <% } %> 42 | 43 | return firestoreService 44 | } 45 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/functions.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | <% if (!serviceOptions.static) { %> 5 | <%= writeImportStatement(options) %> 6 | <% } %> 7 | 8 | <% if (serviceOptions.location) { %> 9 | const functionsService = session.<%= serviceMapping.id %>('<%= serviceOptions.location %>') 10 | <% } else { %> 11 | <% /* If .location is undefined, default will be "us-central1" */ %> 12 | const functionsService = session.<%= serviceMapping.id %>() 13 | <% } %> 14 | 15 | <% /* Uses emulator, if emulatorPort is set. */ %> 16 | <% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %> 17 | <% const emulatorHost = 18 | typeof serviceOptions.emulatorHost === 'string' 19 | ? serviceOptions.emulatorHost 20 | : 'http://localhost' 21 | %> 22 | functionsService.useFunctionsEmulator('<%= `${emulatorHost}` %>:<%= `${serviceOptions.emulatorPort}` %>') 23 | <% } %> 24 | 25 | return functionsService 26 | } 27 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/messaging.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session, firebase) { 4 | // Can only be initiated on client side 5 | if (!process.client) { 6 | return 7 | } 8 | 9 | <% if (!serviceOptions.static) { %> 10 | <%= writeImportStatement(options) %> 11 | <% } %> 12 | 13 | if (firebase.messaging.isSupported()) { 14 | const messagingService = session.<%= serviceMapping.id %>() 15 | 16 | <% if (serviceOptions.fcmPublicVapidKey) { %> 17 | messagingService.getToken({vapidKey: <%= serialize(serviceOptions.fcmPublicVapidKey) %>}) 18 | <% } %> 19 | 20 | return messagingService 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/performance.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | // Can only be initiated on client side 5 | if (!process.client) { 6 | return 7 | } 8 | 9 | <% if (!serviceOptions.static) { %> 10 | <%= writeImportStatement(options) %> 11 | <% } %> 12 | 13 | const performanceService = session.<%= serviceMapping.id %>() 14 | return performanceService 15 | } 16 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/remoteConfig.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | // Can only be initiated on client side 5 | if (!process.client) { 6 | return 7 | } 8 | 9 | <% if (!serviceOptions.static) { %> 10 | <%= writeImportStatement(options) %> 11 | <% } %> 12 | 13 | const remoteConfigService = session.<%= serviceMapping.id %>() 14 | 15 | <% const settings = Object.assign({}, serviceOptions.settings) %> 16 | remoteConfigService.settings = { 17 | fetchTimeoutMillis: <%= `${settings.fetchTimeoutMillis || 60000 }` %>, 18 | minimumFetchIntervalMillis: <%= `${settings.minimumFetchIntervalMillis || 43200000}` %> 19 | } 20 | 21 | <% if (typeof serviceOptions.defaultConfig === 'object') { %> 22 | remoteConfigService.defaultConfig = <%= serialize(serviceOptions.defaultConfig) %> 23 | <% } %> 24 | 25 | return remoteConfigService 26 | } 27 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/plugins/services/storage.js: -------------------------------------------------------------------------------- 1 | <% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %> 2 | 3 | export default async function (session) { 4 | <% if (!serviceOptions.static) { %> 5 | <%= writeImportStatement(options) %> 6 | <% } %> 7 | 8 | const storageService = session.<%= serviceMapping.id %>() 9 | 10 | <% /* Uses emulator, if emulatorPort is set. */ %> 11 | <% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %> 12 | <% const emulatorHost = 13 | typeof serviceOptions.emulatorHost === 'string' 14 | ? serviceOptions.emulatorHost 15 | : 'localhost' 16 | %> 17 | storageService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>) 18 | <% } %> 19 | 20 | return storageService 21 | } 22 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/sw-templates/README.md: -------------------------------------------------------------------------------- 1 | # SW-Templates 2 | 3 | These *service worker templates* will be parsed by lodash template and then copied in the /static folder of the built project. 4 | 5 | [Lodash Template](https://lodash.com/docs/4.17.15#template) is used to parse these plugins. 6 | 7 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/sw-templates/firebase-auth-sw.js: -------------------------------------------------------------------------------- 1 | const ignorePaths = <%= serialize(options.ignorePaths) %> 2 | 3 | <% if (options.loadFromFirebaseHosting) { %> 4 | // Only works on Firebase hosting! 5 | importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js') 6 | importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-auth-compat.js') 7 | importScripts('/__/firebase/init.js') 8 | <% } else { %> 9 | importScripts( 10 | 'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js' 11 | ) 12 | importScripts( 13 | 'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-auth-compat.js' 14 | ) 15 | firebase.initializeApp(<%= serialize(options.config) %>) 16 | <% } %> 17 | 18 | // Initialize authService 19 | const authService = firebase.auth() 20 | 21 | <% /* Uses emulator, if emulatorPort is set. */ %> 22 | <% const authOptions = options.authOptions %> 23 | <% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %> 24 | <% const emulatorHost = 25 | typeof authOptions.emulatorHost === 'string' 26 | ? authOptions.emulatorHost 27 | : 'http://localhost' 28 | %> 29 | authService.useEmulator('<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>') 30 | <% } %> 31 | 32 | 33 | /** 34 | * Returns a promise that resolves with an ID token if available. 35 | * @return {!Promise} The promise that resolves with an ID token if 36 | * available. Otherwise, the promise resolves with null. 37 | */ 38 | const getIdToken = () => { 39 | return new Promise((resolve) => { 40 | const unsubscribe = authService.onAuthStateChanged((user) => { 41 | unsubscribe() 42 | if (user) { 43 | // force token refresh as it might be used to sign in server side 44 | user.getIdToken(true).then((idToken) => { 45 | resolve(idToken) 46 | }, () => { 47 | resolve(null) 48 | }) 49 | } else { 50 | resolve(null) 51 | } 52 | }) 53 | }) 54 | } 55 | 56 | const fetchWithAuthorization = async (original, idToken) => { 57 | // Clone headers as request headers are immutable. 58 | const headers = new Headers() 59 | for (let entry of original.headers.entries()) { 60 | headers.append(entry[0], entry[1]) 61 | } 62 | 63 | // Add ID token to header. 64 | headers.append('Authorization', 'Bearer ' + idToken) 65 | 66 | // Create authorized request 67 | const { url, ...props } = original.clone() 68 | const authorized = new Request(url, { 69 | ...props, 70 | mode: 'same-origin', 71 | redirect: 'manual', 72 | headers 73 | }) 74 | 75 | return fetch(authorized) 76 | } 77 | 78 | self.addEventListener('fetch', (event) => { 79 | const url = new URL(event.request.url) 80 | 81 | const expectsHTML = event.request.headers.get('accept').includes('text/html') 82 | 83 | const isSameOrigin = self.location.origin === url.origin 84 | const isHttps = (self.location.protocol === 'https:' || self.location.hostname === 'localhost' || self.location.hostname === '127.0.0.1') 85 | 86 | const isIgnored = ignorePaths.some(path => { 87 | if (typeof path === 'string') { 88 | return url.pathname.startsWith(path) 89 | } 90 | 91 | return path.test(url.pathname.slice(1)) 92 | }) 93 | 94 | // https://github.com/nuxt-community/firebase-module/issues/465 95 | if (!expectsHTML || !isSameOrigin || !isHttps || isIgnored) { 96 | <% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %> 97 | <% const emulatorHost = 98 | typeof authOptions.emulatorHost === 'string' 99 | ? authOptions.emulatorHost 100 | : 'http://localhost' 101 | %> 102 | if (event.request.url.startsWith('https://www.googleapis.com/identitytoolkit/')) { 103 | event.respondWith( 104 | fetch({ 105 | ...event.request, 106 | ...{ url: event.request.url.replace(/https:\/\//, '<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>/') } 107 | }) 108 | ) 109 | } else event.respondWith(fetch(event.request)) 110 | <% } else { %> 111 | event.respondWith(fetch(event.request)) 112 | <% } %> 113 | return 114 | } 115 | 116 | 117 | // Fetch the resource after checking for the ID token. 118 | // This can also be integrated with existing logic to serve cached files 119 | // in offline mode. 120 | event.respondWith( 121 | getIdToken().then( 122 | idToken => idToken 123 | // if the token was retrieved we attempt an authorized fetch 124 | // if anything goes wrong we fall back to the original request 125 | ? fetchWithAuthorization(event.request, idToken).catch(() => fetch(event.request)) 126 | // otherwise we return a fetch of the original request directly 127 | : fetch(event.request) 128 | ) 129 | ) 130 | }) 131 | 132 | // In service worker script. 133 | self.addEventListener('activate', event => { 134 | event.waitUntil(clients.claim()) 135 | }) -------------------------------------------------------------------------------- /packages/firebase-module/lib/sw-templates/firebase-messaging-sw.js: -------------------------------------------------------------------------------- 1 | <% if (options.loadFromFirebaseHosting) { %> 2 | // Only works on Firebase hosting & not on localhost! 3 | importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js') 4 | importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-messaging-compat.js') 5 | importScripts('/__/firebase/init.js') 6 | <% } else { %> 7 | importScripts( 8 | 'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js' 9 | ) 10 | importScripts( 11 | 'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-messaging-compat.js' 12 | ) 13 | firebase.initializeApp(<%= serialize(options.config) %>) 14 | <% } %> 15 | 16 | // Retrieve an instance of Firebase Messaging so that it can handle background 17 | // messages. 18 | const messaging = firebase.messaging() 19 | 20 | <% if (options.actions) { %> 21 | // Setup event listeners for actions provided in the config: 22 | self.addEventListener('notificationclick', function(e) { 23 | 24 | const actions = <%= serialize(options.actions) %> 25 | const action = actions.find(x => x.action === e.action) 26 | const notification = e.notification 27 | 28 | if (!action) return 29 | 30 | if (action.url) { 31 | clients.openWindow(action.url) 32 | notification.close() 33 | } 34 | }) 35 | <% } %> 36 | 37 | <% if (options.inject) { %> 38 | <%= options.inject %> 39 | <% } %> -------------------------------------------------------------------------------- /packages/firebase-module/lib/utils/auth-ssr/ssr-auth-session-manager.js: -------------------------------------------------------------------------------- 1 | const logger = require('../logger') 2 | 3 | const sessions = { 4 | working: false, 5 | queue: [], 6 | active: [], 7 | } 8 | 9 | const logins = { 10 | working: false, 11 | queue: [], 12 | } 13 | 14 | async function removeSession(session) { 15 | logger.info('deleting session: ', session.instance.name) 16 | 17 | const index = sessions.active.findIndex( 18 | (s) => s.instance.name !== session.instance.name 19 | ) 20 | sessions.active.splice(index, 1) 21 | 22 | await session.instance.delete() 23 | } 24 | 25 | function enqueueSessionOperation(operation) { 26 | return new Promise((resolve) => { 27 | sessions.queue.push({ 28 | operation, 29 | resolve, 30 | }) 31 | 32 | dequeueSessionOperation() 33 | }) 34 | } 35 | 36 | async function dequeueSessionOperation() { 37 | if (sessions.working) { 38 | return 39 | } 40 | sessions.working = true 41 | 42 | const item = sessions.queue.shift() 43 | 44 | if (!item) { 45 | sessions.working = false 46 | 47 | return 48 | } 49 | 50 | const result = await item.operation() 51 | item.resolve(result) 52 | 53 | sessions.working = false 54 | dequeueSessionOperation() 55 | } 56 | 57 | class SessionManager { 58 | constructor(firebase, { config, sessions: sessionConfig }) { 59 | this.firebase = firebase 60 | this.config = config 61 | this.lifetime = sessionConfig.sessionLifetime || 0 62 | this.loginDelay = sessionConfig.loginDelay || 50 63 | } 64 | 65 | getSession(name, touch = true) { 66 | const session = sessions.active.find((s) => s.instance.name === name) 67 | 68 | if (session) { 69 | if (session.timeout) { 70 | logger.debug('session retrieved, aborting removal') 71 | 72 | clearTimeout(session.timeout) 73 | session.timeout = null 74 | } 75 | 76 | if (touch) session.touched = Date.now() 77 | } 78 | 79 | return session 80 | } 81 | 82 | getUser(name) { 83 | const session = this.getSession(name) 84 | 85 | if (!session) { 86 | const error = new Error(`Missing session for user ${name}`) 87 | error.code = 'nuxt-firebase/missing-session' 88 | 89 | throw error 90 | } 91 | 92 | const auth = session.instance.auth() 93 | 94 | return auth.currentUser 95 | } 96 | 97 | startSession(name = '[DEFAULT]') { 98 | return enqueueSessionOperation(() => { 99 | logger.info('starting session for: ', name) 100 | 101 | const session = this.getSession(name) 102 | 103 | if (session) { 104 | if (name === '[DEFAULT]') return session.instance 105 | 106 | session.active++ 107 | logger.debug('found existing, active sessions: ', session.active) 108 | 109 | return session.instance 110 | } 111 | 112 | const instance = 113 | this.firebase.apps.find((a) => a.name === name) ?? 114 | this.firebase.initializeApp(this.config, name) 115 | 116 | sessions.active.push({ 117 | instance, 118 | active: 1, 119 | touched: Date.now(), 120 | }) 121 | 122 | logger.debug('created, active sessions: ', 1) 123 | 124 | return instance 125 | }) 126 | } 127 | 128 | endSession(name = '[DEFAULT]') { 129 | return enqueueSessionOperation(() => { 130 | logger.info('ending session for: ', name) 131 | 132 | const session = this.getSession(name, false) 133 | 134 | if (!session || name === '[DEFAULT]') return 135 | 136 | session.active-- 137 | logger.debug('active sessions: ', session.active) 138 | 139 | if (session.active < 1) { 140 | const logoutTimer = this.lifetime - (Date.now() - session.touched) 141 | 142 | logger.debug('enqueueing session removal in: ', logoutTimer) 143 | 144 | session.timeout = setTimeout(() => { 145 | enqueueSessionOperation(() => removeSession(session)) 146 | }, logoutTimer) 147 | } 148 | }) 149 | } 150 | 151 | login(name, token) { 152 | logger.debug('enqueueing login attempt', Date.now()) 153 | 154 | const session = this.getSession(name) 155 | 156 | const auth = session.instance.auth() 157 | 158 | return new Promise((resolve, reject) => { 159 | logins.queue.push({ 160 | promise: () => auth.signInWithCustomToken(token), 161 | resolve, 162 | reject, 163 | }) 164 | 165 | this.dequeueLoginAttempts() 166 | }) 167 | } 168 | 169 | async dequeueLoginAttempts() { 170 | if (logins.working) { 171 | return 172 | } 173 | logins.working = true 174 | 175 | const current = logins.queue.shift() 176 | 177 | if (!current) { 178 | logins.working = false 179 | return 180 | } 181 | 182 | try { 183 | logger.debug('attempting login: ' + Date.now()) 184 | 185 | const { user } = await current.promise() 186 | 187 | current.resolve(user) 188 | } catch (e) { 189 | current.reject(e) 190 | } 191 | 192 | setTimeout(() => { 193 | logins.working = false 194 | this.dequeueLoginAttempts() 195 | }, this.loginDelay) 196 | } 197 | } 198 | 199 | module.exports = SessionManager 200 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/utils/logger.js: -------------------------------------------------------------------------------- 1 | const consola = require('consola') 2 | 3 | module.exports = consola.withScope('nuxt:firebase') 4 | -------------------------------------------------------------------------------- /packages/firebase-module/lib/utils/template-utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | id: used in... 3 | - module config 4 | - names of the services .js files 5 | - name of the Firebase object/function, e.g. firebase.remoteConfig 6 | - injection names from version 7+ (e.g. $fire.remoteConfig) 7 | importName: name of the import, e.g. import 'firebase/remote-config' 8 | */ 9 | const serviceMappings = { 10 | app: { 11 | id: 'app', 12 | importName: 'app', 13 | clientOnly: false, 14 | }, 15 | auth: { 16 | id: 'auth', 17 | importName: 'auth', 18 | clientOnly: false, 19 | }, 20 | database: { 21 | // = realtime DB 22 | id: 'database', 23 | importName: 'database', 24 | clientOnly: false, 25 | }, 26 | firestore: { 27 | id: 'firestore', 28 | importName: 'firestore', 29 | clientOnly: false, 30 | }, 31 | storage: { 32 | id: 'storage', 33 | importName: 'storage', 34 | clientOnly: false, 35 | }, 36 | functions: { 37 | id: 'functions', 38 | importName: 'functions', 39 | clientOnly: false, 40 | }, 41 | messaging: { 42 | id: 'messaging', 43 | importName: 'messaging', 44 | clientOnly: true, 45 | }, 46 | performance: { 47 | id: 'performance', 48 | importName: 'performance', 49 | clientOnly: true, 50 | }, 51 | analytics: { 52 | id: 'analytics', 53 | importName: 'analytics', 54 | clientOnly: true, 55 | }, 56 | remoteConfig: { 57 | id: 'remoteConfig', 58 | importName: 'remote-config', 59 | clientOnly: true, 60 | }, 61 | appCheck: { 62 | id: 'appCheck', 63 | importName: 'app-check', 64 | clientOnly: true, 65 | }, 66 | } 67 | 68 | function writeStaticImports(options) { 69 | return Object.values(serviceMappings) 70 | .map((serviceMapping) => 71 | writeImportStatement(options, serviceMapping, true) 72 | ) 73 | .filter(Boolean) 74 | .join('\n') 75 | } 76 | 77 | function writeImportStatement(options, serviceMapping, staticOnly = false) { 78 | if (!serviceMapping) { 79 | serviceMapping = options.serviceMapping 80 | // TODO - does this make sense? 81 | } 82 | 83 | const serviceOptions = options.services[serviceMapping.id] 84 | if (!serviceOptions) { 85 | return 86 | } 87 | 88 | const useStaticImport = serviceOptions.static 89 | 90 | let pathAppendix = '' 91 | if (serviceOptions.memoryOnly) { 92 | // Only works with Firestore 93 | pathAppendix = '/memory' 94 | } 95 | 96 | const servicePath = serviceMapping.importName 97 | const importPath = `'firebase/compat/${servicePath}${pathAppendix}'` 98 | 99 | if (staticOnly) { 100 | if (!useStaticImport) { 101 | return 102 | } 103 | return `import ${importPath}` 104 | } 105 | 106 | const webpackComments = [] 107 | 108 | // Add Chunk Name Comment 109 | let webpackChunkName = serviceOptions.chunkName 110 | if (!webpackChunkName && process.env.NODE_ENV !== 'production') { 111 | webpackChunkName = `firebase-${servicePath}` 112 | } 113 | 114 | if (webpackChunkName) { 115 | webpackComments.push(`webpackChunkName: '${webpackChunkName}'`) 116 | } 117 | 118 | // Add Preload Comment 119 | if (serviceOptions.preload) { 120 | webpackComments.push('webpackPreload: true') 121 | } 122 | 123 | // Add strings surrounding the comment 124 | let webpackCommentsString = '' 125 | if (webpackComments.length) { 126 | webpackCommentsString = `/* ${webpackComments.join(', ')} */` 127 | } 128 | 129 | return `await import(${webpackCommentsString}${importPath})` 130 | } 131 | 132 | module.exports = { 133 | serviceMappings, 134 | writeStaticImports, 135 | writeImportStatement, 136 | } 137 | -------------------------------------------------------------------------------- /packages/firebase-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/firebase", 3 | "version": "8.2.2", 4 | "description": "Intergrate Firebase into your Nuxt project.", 5 | "keywords": [ 6 | "firebase", 7 | "firestore", 8 | "google", 9 | "googleauthentication", 10 | "nuxt", 11 | "realtimedatabase" 12 | ], 13 | "homepage": "https://firebase.nuxtjs.org/", 14 | "repository": "nuxt-community/firebase-module", 15 | "license": "MIT", 16 | "author": "Pascal Luther", 17 | "files": [ 18 | "lib", 19 | "types/*.d.ts" 20 | ], 21 | "main": "lib/module.js", 22 | "types": "types/index.d.ts", 23 | "scripts": { 24 | "lint": "eslint --ext .js,.vue lib test", 25 | "release": "standard-version && git push --follow-tags && npm publish", 26 | "test": "npm run lint && jest", 27 | "commit": "npx git-cz", 28 | "docs": "cd docs && npm run dev" 29 | }, 30 | "dependencies": { 31 | "consola": "^2.15.3" 32 | }, 33 | "devDependencies": { 34 | "@babel/core": "^7.14.5", 35 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 36 | "@babel/preset-env": "^7.16.8", 37 | "@commitlint/cli": "latest", 38 | "@commitlint/config-conventional": "latest", 39 | "@nuxt/types": "^2.15.6", 40 | "@nuxtjs/eslint-config": "^8.0.0", 41 | "@nuxtjs/module-test-utils": "^1.6.3", 42 | "babel-eslint": "^10.1.0", 43 | "babel-jest": "^28.1.0", 44 | "babel-plugin-dynamic-import-node": "^2.3.3", 45 | "codecov": "latest", 46 | "core-js": "^3.14.0", 47 | "cz-conventional-changelog": "latest", 48 | "eslint": "^8.0.1", 49 | "firebase": "^9.6.2", 50 | "husky": "^7.0.2", 51 | "jest": "^28.1.0", 52 | "nuxt": "^2.15.6", 53 | "proxy-mock-js": "^1.0.3", 54 | "standard-version": "^9.3.0", 55 | "eslint-config-prettier": "^8.3.0", 56 | "eslint-plugin-prettier": "^4.0.0", 57 | "prettier": "^2.8.4" 58 | }, 59 | "peerDependencies": { 60 | "firebase": "^9.6.2", 61 | "nuxt": "^2.15.6" 62 | }, 63 | "publishConfig": { 64 | "access": "public" 65 | }, 66 | "config": { 67 | "commitizen": { 68 | "path": "./node_modules/cz-conventional-changelog" 69 | } 70 | }, 71 | "optionalDependencies": { 72 | "firebase-admin": "^10.0.0" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/firebase-module/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /packages/firebase-module/test/__snapshots__/default.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`default plugin contents 1`] = ` 4 | "import createApp from './app.js' 5 | 6 | import authService from './service.auth.js' 7 | import databaseService from './service.database.js' 8 | import firestoreService from './service.firestore.js' 9 | import storageService from './service.storage.js' 10 | import functionsService from './service.functions.js' 11 | import messagingService from './service.messaging.js' 12 | import performanceService from './service.performance.js' 13 | import analyticsService from './service.analytics.js' 14 | import remoteConfigService from './service.remoteConfig.js' 15 | 16 | const appConfig = {\\"apiKey\\":\\"\\\\u003CapiKey\\\\u003E\\",\\"authDomain\\":\\"\\\\u003CauthDomain\\\\u003E\\",\\"databaseURL\\":\\"\\\\u003CdatabaseURL\\\\u003E\\",\\"projectId\\":\\"\\\\u003CprojectId\\\\u003E\\",\\"storageBucket\\":\\"\\\\u003CstorageBucket\\\\u003E\\",\\"messagingSenderId\\":\\"\\\\u003CmessagingSenderId\\\\u003E\\",\\"appId\\":\\"\\\\u003CappId\\\\u003E\\",\\"measurementId\\":\\"\\\\u003CmeasurementId\\\\u003E\\"} 17 | 18 | export default async (ctx, inject) => { 19 | /**************************************** 20 | **************** LAZY MODE ************** 21 | ****************************************/ 22 | 23 | const { firebase, session } = await createApp(appConfig, ctx) 24 | 25 | let servicePromises = [] 26 | 27 | if (process.server) { 28 | servicePromises = [ 29 | authService(session, firebase, ctx, inject), 30 | databaseService(session, firebase, ctx, inject), 31 | firestoreService(session, firebase, ctx, inject), 32 | storageService(session, firebase, ctx, inject), 33 | functionsService(session, firebase, ctx, inject), 34 | 35 | ] 36 | } 37 | 38 | if (process.client) { 39 | servicePromises = [ 40 | authService(session, firebase, ctx, inject), 41 | databaseService(session, firebase, ctx, inject), 42 | firestoreService(session, firebase, ctx, inject), 43 | storageService(session, firebase, ctx, inject), 44 | functionsService(session, firebase, ctx, inject), 45 | messagingService(session, firebase, ctx, inject), 46 | performanceService(session, firebase, ctx, inject), 47 | analyticsService(session, firebase, ctx, inject), 48 | remoteConfigService(session, firebase, ctx, inject), 49 | 50 | ] 51 | } 52 | 53 | const [ 54 | auth, 55 | database, 56 | firestore, 57 | storage, 58 | functions, 59 | messaging, 60 | performance, 61 | analytics, 62 | remoteConfig 63 | ] = await Promise.all(servicePromises) 64 | 65 | const fire = { 66 | auth: auth, 67 | database: database, 68 | firestore: firestore, 69 | storage: storage, 70 | functions: functions, 71 | messaging: messaging, 72 | performance: performance, 73 | analytics: analytics, 74 | remoteConfig: remoteConfig 75 | } 76 | 77 | inject('fire', fire) 78 | ctx.$fire = fire 79 | } 80 | " 81 | `; 82 | -------------------------------------------------------------------------------- /packages/firebase-module/test/__snapshots__/lazy-init-auth.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`lazy-init-auth init auth plugin exist 1`] = ` 4 | "// runs the functions once BEFORE the root Vue.js Application is instantiated. 5 | export default ({ $fireAuthStore }) => { 6 | return $fireAuthStore.subscribe() 7 | } 8 | " 9 | `; 10 | -------------------------------------------------------------------------------- /packages/firebase-module/test/__snapshots__/lazy.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`lazy plugin contents 1`] = ` 4 | "import createApp from './app.js' 5 | 6 | import authService from './service.auth.js' 7 | import databaseService from './service.database.js' 8 | import firestoreService from './service.firestore.js' 9 | import storageService from './service.storage.js' 10 | import functionsService from './service.functions.js' 11 | import messagingService from './service.messaging.js' 12 | import performanceService from './service.performance.js' 13 | import analyticsService from './service.analytics.js' 14 | import remoteConfigService from './service.remoteConfig.js' 15 | 16 | const appConfig = {\\"apiKey\\":\\"\\\\u003CapiKey\\\\u003E\\",\\"authDomain\\":\\"\\\\u003CauthDomain\\\\u003E\\",\\"databaseURL\\":\\"\\\\u003CdatabaseURL\\\\u003E\\",\\"projectId\\":\\"\\\\u003CprojectId\\\\u003E\\",\\"storageBucket\\":\\"\\\\u003CstorageBucket\\\\u003E\\",\\"messagingSenderId\\":\\"\\\\u003CmessagingSenderId\\\\u003E\\",\\"appId\\":\\"\\\\u003CappId\\\\u003E\\",\\"measurementId\\":\\"\\\\u003CmeasurementId\\\\u003E\\"} 17 | 18 | export default async (ctx, inject) => { 19 | /**************************************** 20 | **************** LAZY MODE ************** 21 | ****************************************/ 22 | 23 | let firebase, session 24 | let firebaseReady = false 25 | 26 | const fire = { 27 | async appReady() { 28 | if (!firebaseReady) { 29 | ({ firebase, session } = await createApp(appConfig, ctx)) 30 | firebaseReady = true; 31 | } 32 | return session 33 | }, 34 | async ready() { 35 | await fire.appReady() 36 | 37 | let servicePromises = [] 38 | 39 | if (process.server) { 40 | servicePromises = [ 41 | fire.authReady(), 42 | fire.databaseReady(), 43 | fire.firestoreReady(), 44 | fire.storageReady(), 45 | fire.functionsReady(), 46 | 47 | ] 48 | } 49 | 50 | if (process.client) { 51 | servicePromises = [ 52 | fire.authReady(), 53 | fire.databaseReady(), 54 | fire.firestoreReady(), 55 | fire.storageReady(), 56 | fire.functionsReady(), 57 | fire.messagingReady(), 58 | fire.performanceReady(), 59 | fire.analyticsReady(), 60 | fire.remoteConfigReady(), 61 | 62 | ] 63 | } 64 | 65 | await Promise.all(servicePromises) 66 | return session 67 | } 68 | } 69 | 70 | if (process.server) { 71 | fire.auth = null 72 | fire.authReady = async () => { 73 | if (!fire.auth) { 74 | await fire.appReady() 75 | fire.auth = await authService(session, firebase, ctx, inject) 76 | } 77 | 78 | return fire.auth 79 | } 80 | 81 | fire.database = null 82 | fire.databaseReady = async () => { 83 | if (!fire.database) { 84 | await fire.appReady() 85 | fire.database = await databaseService(session, firebase, ctx, inject) 86 | } 87 | 88 | return fire.database 89 | } 90 | 91 | fire.firestore = null 92 | fire.firestoreReady = async () => { 93 | if (!fire.firestore) { 94 | await fire.appReady() 95 | fire.firestore = await firestoreService(session, firebase, ctx, inject) 96 | } 97 | 98 | return fire.firestore 99 | } 100 | 101 | fire.storage = null 102 | fire.storageReady = async () => { 103 | if (!fire.storage) { 104 | await fire.appReady() 105 | fire.storage = await storageService(session, firebase, ctx, inject) 106 | } 107 | 108 | return fire.storage 109 | } 110 | 111 | fire.functions = null 112 | fire.functionsReady = async () => { 113 | if (!fire.functions) { 114 | await fire.appReady() 115 | fire.functions = await functionsService(session, firebase, ctx, inject) 116 | } 117 | 118 | return fire.functions 119 | } 120 | } 121 | 122 | if (process.client) { 123 | fire.auth = null 124 | fire.authReady = async () => { 125 | if (!fire.auth) { 126 | await fire.appReady() 127 | fire.auth = await authService(session, firebase, ctx, inject) 128 | } 129 | 130 | return fire.auth 131 | } 132 | 133 | fire.database = null 134 | fire.databaseReady = async () => { 135 | if (!fire.database) { 136 | await fire.appReady() 137 | fire.database = await databaseService(session, firebase, ctx, inject) 138 | } 139 | 140 | return fire.database 141 | } 142 | 143 | fire.firestore = null 144 | fire.firestoreReady = async () => { 145 | if (!fire.firestore) { 146 | await fire.appReady() 147 | fire.firestore = await firestoreService(session, firebase, ctx, inject) 148 | } 149 | 150 | return fire.firestore 151 | } 152 | 153 | fire.storage = null 154 | fire.storageReady = async () => { 155 | if (!fire.storage) { 156 | await fire.appReady() 157 | fire.storage = await storageService(session, firebase, ctx, inject) 158 | } 159 | 160 | return fire.storage 161 | } 162 | 163 | fire.functions = null 164 | fire.functionsReady = async () => { 165 | if (!fire.functions) { 166 | await fire.appReady() 167 | fire.functions = await functionsService(session, firebase, ctx, inject) 168 | } 169 | 170 | return fire.functions 171 | } 172 | 173 | fire.messaging = null 174 | fire.messagingReady = async () => { 175 | if (!fire.messaging) { 176 | await fire.appReady() 177 | fire.messaging = await messagingService(session, firebase, ctx, inject) 178 | } 179 | 180 | return fire.messaging 181 | } 182 | 183 | fire.performance = null 184 | fire.performanceReady = async () => { 185 | if (!fire.performance) { 186 | await fire.appReady() 187 | fire.performance = await performanceService(session, firebase, ctx, inject) 188 | } 189 | 190 | return fire.performance 191 | } 192 | 193 | fire.analytics = null 194 | fire.analyticsReady = async () => { 195 | if (!fire.analytics) { 196 | await fire.appReady() 197 | fire.analytics = await analyticsService(session, firebase, ctx, inject) 198 | } 199 | 200 | return fire.analytics 201 | } 202 | 203 | fire.remoteConfig = null 204 | fire.remoteConfigReady = async () => { 205 | if (!fire.remoteConfig) { 206 | await fire.appReady() 207 | fire.remoteConfig = await remoteConfigService(session, firebase, ctx, inject) 208 | } 209 | 210 | return fire.remoteConfig 211 | } 212 | } 213 | 214 | inject('fire', fire) 215 | ctx.$fire = fire 216 | 217 | /**************************************** 218 | ************* NON-LAZY MODE ************* 219 | ****************************************/ 220 | } 221 | " 222 | `; 223 | -------------------------------------------------------------------------------- /packages/firebase-module/test/__snapshots__/with-module.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`with-module plugin contents 1`] = ` 4 | "import createApp from './app.js' 5 | 6 | import authService from './service.auth.js' 7 | import databaseService from './service.database.js' 8 | import firestoreService from './service.firestore.js' 9 | import storageService from './service.storage.js' 10 | import functionsService from './service.functions.js' 11 | import messagingService from './service.messaging.js' 12 | import performanceService from './service.performance.js' 13 | import analyticsService from './service.analytics.js' 14 | import remoteConfigService from './service.remoteConfig.js' 15 | 16 | const appConfig = {\\"apiKey\\":\\"\\\\u003CapiKey\\\\u003E\\",\\"authDomain\\":\\"\\\\u003CauthDomain\\\\u003E\\",\\"databaseURL\\":\\"\\\\u003CdatabaseURL\\\\u003E\\",\\"projectId\\":\\"\\\\u003CprojectId\\\\u003E\\",\\"storageBucket\\":\\"\\\\u003CstorageBucket\\\\u003E\\",\\"messagingSenderId\\":\\"\\\\u003CmessagingSenderId\\\\u003E\\",\\"appId\\":\\"\\\\u003CappId\\\\u003E\\",\\"measurementId\\":\\"\\\\u003CmeasurementId\\\\u003E\\"} 17 | 18 | export default async (ctx, inject) => { 19 | /**************************************** 20 | **************** LAZY MODE ************** 21 | ****************************************/ 22 | 23 | const { firebase, session } = await createApp(appConfig, ctx) 24 | 25 | let servicePromises = [] 26 | 27 | if (process.server) { 28 | servicePromises = [ 29 | authService(session, firebase, ctx, inject), 30 | databaseService(session, firebase, ctx, inject), 31 | firestoreService(session, firebase, ctx, inject), 32 | storageService(session, firebase, ctx, inject), 33 | functionsService(session, firebase, ctx, inject), 34 | 35 | ] 36 | } 37 | 38 | if (process.client) { 39 | servicePromises = [ 40 | authService(session, firebase, ctx, inject), 41 | databaseService(session, firebase, ctx, inject), 42 | firestoreService(session, firebase, ctx, inject), 43 | storageService(session, firebase, ctx, inject), 44 | functionsService(session, firebase, ctx, inject), 45 | messagingService(session, firebase, ctx, inject), 46 | performanceService(session, firebase, ctx, inject), 47 | analyticsService(session, firebase, ctx, inject), 48 | remoteConfigService(session, firebase, ctx, inject), 49 | 50 | ] 51 | } 52 | 53 | const [ 54 | auth, 55 | database, 56 | firestore, 57 | storage, 58 | functions, 59 | messaging, 60 | performance, 61 | analytics, 62 | remoteConfig 63 | ] = await Promise.all(servicePromises) 64 | 65 | const fire = { 66 | auth: auth, 67 | database: database, 68 | firestore: firestore, 69 | storage: storage, 70 | functions: functions, 71 | messaging: messaging, 72 | performance: performance, 73 | analytics: analytics, 74 | remoteConfig: remoteConfig 75 | } 76 | 77 | inject('fireModule', firebase) 78 | ctx.$fireModule = firebase 79 | 80 | inject('fire', fire) 81 | ctx.$fire = fire 82 | } 83 | " 84 | `; 85 | -------------------------------------------------------------------------------- /packages/firebase-module/test/default.test.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const fs = require('fs-extra') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const FirebaseModule = require('..') 5 | 6 | jest.mock('firebase/compat/app', () => ({ 7 | apps: [ 8 | new Proxy( 9 | {}, 10 | { 11 | get(target, name) { 12 | return jest.fn(() => ({})) 13 | }, 14 | } 15 | ), 16 | ], 17 | messaging: { 18 | isSupported: jest.fn(), 19 | }, 20 | })) 21 | 22 | describe('default', () => { 23 | let nuxt 24 | const buildDir = resolve(__dirname, '.nuxt-default') 25 | 26 | beforeAll(async () => { 27 | const config = { 28 | rootDir: resolve(__dirname, '..'), 29 | buildDir, 30 | srcDir: resolve(__dirname, 'fixture'), 31 | modules: [ 32 | [ 33 | FirebaseModule, 34 | { 35 | injectModule: false, 36 | config: { 37 | // REQUIRED: Official config for firebase.initializeApp(config): 38 | apiKey: '', 39 | authDomain: '', 40 | databaseURL: '', 41 | projectId: '', 42 | storageBucket: '', 43 | messagingSenderId: '', 44 | appId: '', 45 | measurementId: '', 46 | }, 47 | services: { 48 | analytics: true, 49 | auth: true, 50 | firestore: true, 51 | functions: true, 52 | messaging: true, 53 | performance: true, 54 | database: true, 55 | remoteConfig: true, 56 | storage: true, 57 | }, 58 | }, 59 | ], 60 | ], 61 | } 62 | config.dev = false 63 | 64 | nuxt = new Nuxt(config) 65 | const BundleBuilder = { build: (_) => _ } 66 | const builder = new Builder(nuxt, BundleBuilder) 67 | await builder.build() 68 | }, 60000) 69 | 70 | afterAll(async () => { 71 | await nuxt.close() 72 | }) 73 | 74 | test('plugin contents', async () => { 75 | const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), { 76 | encoding: 'utf8', 77 | }) 78 | 79 | expect(content).toContain('auth,') 80 | expect(content).toContain('messaging,') 81 | 82 | expect(content).not.toContain('Mess') 83 | 84 | expect(content).toMatchSnapshot() 85 | }) 86 | 87 | test('exec plugin (server)', async () => { 88 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 89 | (m) => m.default || m 90 | ) 91 | const ctx = {} 92 | const inject = jest.fn() 93 | 94 | await Plugin(ctx, inject) 95 | expect(inject).toHaveBeenCalledTimes(1) 96 | expect(ctx.$fire).toBeDefined() 97 | expect(ctx.$fireModule).toBeUndefined() 98 | }) 99 | 100 | test('exec plugin (client)', async () => { 101 | process.client = true 102 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 103 | (m) => m.default || m 104 | ) 105 | const ctx = {} 106 | const inject = jest.fn() 107 | 108 | await Plugin(ctx, inject) 109 | expect(inject).toHaveBeenCalledTimes(1) 110 | expect(ctx.$fire).toBeDefined() 111 | expect(ctx.$fireModule).toBeUndefined() 112 | }) 113 | }) 114 | -------------------------------------------------------------------------------- /packages/firebase-module/test/fixture/nuxt.config.js: -------------------------------------------------------------------------------- 1 | import FirebaseModule from '../..' 2 | 3 | export default { 4 | rootDir: __dirname, 5 | render: { 6 | resourceHints: false, 7 | }, 8 | modules: [FirebaseModule], 9 | firebase: { 10 | lazy: true, 11 | injectModule: true, 12 | config: { 13 | // REQUIRED: Official config for firebase.initializeApp(config): 14 | apiKey: '', 15 | authDomain: '', 16 | databaseURL: 'https://test.firebaseio.com', 17 | projectId: '', 18 | storageBucket: '', 19 | messagingSenderId: '', 20 | appId: '', 21 | measurementId: '', 22 | }, 23 | services: { 24 | auth: true, 25 | database: true, 26 | messaging: true, 27 | analytics: true, 28 | remoteConfig: true, 29 | }, 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /packages/firebase-module/test/fixture/pages/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /packages/firebase-module/test/lazy-init-auth.test.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const fs = require('fs-extra') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const FirebaseModule = require('..') 5 | 6 | jest.mock('firebase/compat/app', () => { 7 | const { getProxyMock } = require('proxy-mock-js') 8 | const spyFn = (name, fn) => jest.fn(fn) 9 | const session = getProxyMock({}, 'firebaseSession', spyFn) 10 | 11 | /* const session = new Proxy({}, { 12 | get(target, name) { 13 | return jest.fn(() => ({})) 14 | } 15 | }) */ 16 | 17 | return { 18 | apps: [session], 19 | messaging: { 20 | isSupported: jest.fn(), 21 | }, 22 | } 23 | }) 24 | 25 | describe('lazy-init-auth', () => { 26 | let nuxt 27 | const buildDir = resolve(__dirname, '.nuxt-lazy-init-auth') 28 | 29 | beforeAll(async () => { 30 | const config = { 31 | rootDir: resolve(__dirname, '..'), 32 | buildDir, 33 | srcDir: resolve(__dirname, 'fixture'), 34 | modules: [ 35 | [ 36 | FirebaseModule, 37 | { 38 | injectModule: false, 39 | lazy: true, 40 | config: { 41 | // REQUIRED: Official config for firebase.initializeApp(config): 42 | apiKey: '', 43 | authDomain: '', 44 | databaseURL: '', 45 | projectId: '', 46 | storageBucket: '', 47 | messagingSenderId: '', 48 | appId: '', 49 | measurementId: '', 50 | }, 51 | services: { 52 | analytics: true, 53 | auth: { 54 | initialize: { 55 | onAuthStateChangedAction: 'onAuthStateChanged', 56 | }, 57 | }, 58 | firestore: true, 59 | functions: true, 60 | messaging: true, 61 | performance: true, 62 | database: true, 63 | remoteConfig: true, 64 | storage: true, 65 | }, 66 | }, 67 | ], 68 | ], 69 | } 70 | config.dev = false 71 | 72 | nuxt = new Nuxt(config) 73 | const BundleBuilder = { build: (_) => _ } 74 | const builder = new Builder(nuxt, BundleBuilder) 75 | await builder.build() 76 | }, 60000) 77 | 78 | afterAll(async () => { 79 | await nuxt.close() 80 | }) 81 | 82 | test('init auth plugin exist', async () => { 83 | const content = await fs.readFile( 84 | resolve(buildDir, 'firebase/service.auth.initialize.js'), 85 | { encoding: 'utf8' } 86 | ) 87 | expect(content).toMatchSnapshot() 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /packages/firebase-module/test/lazy.test.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const fs = require('fs-extra') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const FirebaseModule = require('..') 5 | 6 | jest.mock('firebase/compat/app', () => { 7 | const { getProxyMock } = require('proxy-mock-js') 8 | const spyFn = (name, fn) => jest.fn(fn) 9 | const session = getProxyMock({}, 'firebaseSession', spyFn) 10 | 11 | /* const session = new Proxy({}, { 12 | get(target, name) { 13 | return jest.fn(() => ({})) 14 | } 15 | }) */ 16 | 17 | return { 18 | apps: [session], 19 | messaging: { 20 | isSupported: jest.fn(), 21 | }, 22 | } 23 | }) 24 | 25 | describe('lazy', () => { 26 | let nuxt 27 | const buildDir = resolve(__dirname, '.nuxt-lazy') 28 | 29 | beforeAll(async () => { 30 | const config = { 31 | rootDir: resolve(__dirname, '..'), 32 | buildDir, 33 | srcDir: resolve(__dirname, 'fixture'), 34 | modules: [ 35 | [ 36 | FirebaseModule, 37 | { 38 | injectModule: false, 39 | lazy: true, 40 | config: { 41 | // REQUIRED: Official config for firebase.initializeApp(config): 42 | apiKey: '', 43 | authDomain: '', 44 | databaseURL: '', 45 | projectId: '', 46 | storageBucket: '', 47 | messagingSenderId: '', 48 | appId: '', 49 | measurementId: '', 50 | }, 51 | services: { 52 | analytics: true, 53 | auth: true, 54 | firestore: true, 55 | functions: true, 56 | messaging: true, 57 | performance: true, 58 | database: true, 59 | remoteConfig: true, 60 | storage: true, 61 | }, 62 | }, 63 | ], 64 | ], 65 | } 66 | config.dev = false 67 | 68 | nuxt = new Nuxt(config) 69 | const BundleBuilder = { build: (_) => _ } 70 | const builder = new Builder(nuxt, BundleBuilder) 71 | await builder.build() 72 | }, 60000) 73 | 74 | afterAll(async () => { 75 | await nuxt.close() 76 | }) 77 | 78 | test('plugin contents', async () => { 79 | const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), { 80 | encoding: 'utf8', 81 | }) 82 | 83 | expect(content).toContain('fire.auth = null') 84 | expect(content).toContain('fire.messaging = null') 85 | 86 | expect(content).not.toContain('Mess') 87 | 88 | expect(content).toMatchSnapshot() 89 | }) 90 | 91 | test('exec plugin (server)', async () => { 92 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 93 | (m) => m.default || m 94 | ) 95 | const ctx = {} 96 | const inject = jest.fn() 97 | 98 | await Plugin(ctx, inject) 99 | expect(inject).toHaveBeenCalledTimes(1) 100 | expect(ctx.$fire).toBeDefined() 101 | expect(ctx.$fireModule).toBeUndefined() 102 | 103 | expect(ctx.$fire.appReady).toBeDefined() 104 | 105 | // TODO: test the appReady call. Doesnt work atm due to Jest not detecting 106 | // a async callback in the session var. Not fully sure whats happening 107 | // const app = await ctx.$fire.appReady() 108 | }) 109 | 110 | test('exec plugin (client)', async () => { 111 | process.client = true 112 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 113 | (m) => m.default || m 114 | ) 115 | const ctx = {} 116 | const inject = jest.fn() 117 | 118 | await Plugin(ctx, inject) 119 | expect(inject).toHaveBeenCalledTimes(1) 120 | expect(ctx.$fire).toBeDefined() 121 | expect(ctx.$fireModule).toBeUndefined() 122 | }) 123 | }) 124 | -------------------------------------------------------------------------------- /packages/firebase-module/test/with-module.test.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const fs = require('fs-extra') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const FirebaseModule = require('..') 5 | 6 | jest.mock('firebase/compat/app', () => ({ 7 | apps: [ 8 | new Proxy( 9 | {}, 10 | { 11 | get(target, name) { 12 | return jest.fn(() => ({})) 13 | }, 14 | } 15 | ), 16 | ], 17 | messaging: { 18 | isSupported: jest.fn(), 19 | }, 20 | })) 21 | 22 | describe('with-module', () => { 23 | let nuxt 24 | const buildDir = resolve(__dirname, '.nuxt-with-module') 25 | 26 | beforeAll(async () => { 27 | const config = { 28 | rootDir: resolve(__dirname, '..'), 29 | buildDir, 30 | srcDir: resolve(__dirname, 'fixture'), 31 | modules: [ 32 | [ 33 | FirebaseModule, 34 | { 35 | injectModule: true, 36 | config: { 37 | // REQUIRED: Official config for firebase.initializeApp(config): 38 | apiKey: '', 39 | authDomain: '', 40 | databaseURL: '', 41 | projectId: '', 42 | storageBucket: '', 43 | messagingSenderId: '', 44 | appId: '', 45 | measurementId: '', 46 | }, 47 | services: { 48 | analytics: true, 49 | auth: true, 50 | firestore: true, 51 | functions: true, 52 | messaging: true, 53 | performance: true, 54 | database: true, 55 | remoteConfig: true, 56 | storage: true, 57 | }, 58 | }, 59 | ], 60 | ], 61 | } 62 | config.dev = false 63 | 64 | nuxt = new Nuxt(config) 65 | const BundleBuilder = { build: (_) => _ } 66 | const builder = new Builder(nuxt, BundleBuilder) 67 | await builder.build() 68 | }, 60000) 69 | 70 | afterAll(async () => { 71 | await nuxt.close() 72 | }) 73 | 74 | test('plugin contents', async () => { 75 | const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), { 76 | encoding: 'utf8', 77 | }) 78 | 79 | expect(content).toContain('auth,') 80 | expect(content).toContain('messaging,') 81 | expect(content).toContain('firebase') 82 | 83 | expect(content).not.toContain('Mess') 84 | 85 | expect(content).toMatchSnapshot() 86 | }) 87 | 88 | test('exec plugin (server)', async () => { 89 | process.server = true 90 | process.client = false 91 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 92 | (m) => m.default || m 93 | ) 94 | const ctx = {} 95 | const inject = jest.fn() 96 | 97 | await Plugin(ctx, inject) 98 | expect(inject).toHaveBeenCalledTimes(2) 99 | expect(ctx.$fire).toBeDefined() 100 | expect(ctx.$fireModule).toBeDefined() 101 | }) 102 | 103 | test('exec plugin (client)', async () => { 104 | process.server = false 105 | process.client = true 106 | const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then( 107 | (m) => m.default || m 108 | ) 109 | const ctx = {} 110 | const inject = jest.fn() 111 | 112 | await Plugin(ctx, inject) 113 | expect(inject).toHaveBeenCalledTimes(2) 114 | expect(ctx.$fire).toBeDefined() 115 | expect(ctx.$fireModule).toBeDefined() 116 | }) 117 | }) 118 | -------------------------------------------------------------------------------- /packages/firebase-module/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ServerResponse } from 'http' 2 | import { Vue } from 'vue/types/vue' 3 | import { NuxtAppOptions, Configuration } from '@nuxt/types' 4 | import { NuxtConfiguration } from '@nuxt/vue-app' 5 | import { ServiceAccount } from 'firebase-admin' 6 | 7 | import firebase from 'firebase/compat' 8 | import { auth } from 'firebase-admin' 9 | 10 | /*********************************** 11 | * Module Config 12 | ************************************/ 13 | export interface FirebaseConfiguration { 14 | apiKey: string 15 | authDomain: string 16 | databaseURL?: string 17 | projectId: string 18 | storageBucket: string 19 | messagingSenderId: string 20 | appId: string 21 | measurementId: string 22 | } 23 | 24 | interface ServiceConfig { 25 | static?: boolean 26 | preload?: boolean 27 | chunkName?: string 28 | } 29 | 30 | interface messagingAction { 31 | action: string 32 | url?: string 33 | } 34 | 35 | export interface AuthServiceConfig extends ServiceConfig { 36 | persistence?: firebase.auth.Auth.Persistence 37 | 38 | initialize?: { 39 | onAuthStateChangedMutation?: string 40 | onAuthStateChangedAction?: string 41 | onIdTokenChangedMutation?: string 42 | onIdTokenChangedAction?: string 43 | subscribeManually?: boolean 44 | } 45 | 46 | ssr?: 47 | | boolean 48 | | { 49 | credential: string | ServiceAccount | true 50 | serverLogin?: 51 | | boolean 52 | | { 53 | sessionLifetime?: number 54 | loginDelay?: number 55 | } 56 | ignorePaths?: (string | RegExp)[] 57 | } 58 | 59 | emulatorPort?: number 60 | emulatorHost?: string 61 | disableEmulatorWarnings?: boolean 62 | } 63 | 64 | export interface FirestoreServiceConfig extends ServiceConfig { 65 | memoryOnly?: boolean 66 | enablePersistence?: 67 | | boolean 68 | | { 69 | synchronizeTabs: boolean 70 | } 71 | emulatorPort?: number 72 | emulatorHost?: string 73 | settings?: firebase.firestore.Settings 74 | } 75 | 76 | export interface FunctionsServiceConfig extends ServiceConfig { 77 | location?: string 78 | emulatorPort?: number 79 | emulatorHost?: string 80 | } 81 | 82 | export interface StorageServiceConfig extends ServiceConfig { 83 | emulatorPort?: number 84 | emulatorHost?: string 85 | } 86 | 87 | export interface DatabaseServiceConfig extends ServiceConfig { 88 | emulatorPort?: number 89 | emulatorHost?: string 90 | } 91 | 92 | export interface MessagingServiceConfig extends ServiceConfig { 93 | createServiceWorker?: 94 | | boolean 95 | | { 96 | notification: { 97 | title: string 98 | body: string 99 | image: string 100 | vibrate: number[] 101 | clickPath: string 102 | } 103 | } 104 | actions?: messagingAction[] 105 | fcmPublicVapidKey?: string 106 | inject?: string 107 | } 108 | 109 | export interface PerformanceServiceConfig extends ServiceConfig {} 110 | 111 | export interface AppCheckServiceConfig extends ServiceConfig { 112 | debugToken?: string | boolean 113 | } 114 | 115 | export interface AnalyticsServiceConfig extends ServiceConfig { 116 | collectionEnabled?: boolean 117 | } 118 | 119 | export interface RemoteConfigServiceConfig extends ServiceConfig { 120 | settings?: { 121 | fetchTimeoutMillis?: number 122 | minimumFetchIntervalMillis?: number 123 | } 124 | defaultConfig?: Record 125 | } 126 | 127 | export interface FirebaseModuleConfiguration { 128 | injectModule?: boolean 129 | lazy?: boolean 130 | config: 131 | | { 132 | [envKey: string]: FirebaseConfiguration 133 | } 134 | | FirebaseConfiguration 135 | services: { 136 | auth?: boolean | AuthServiceConfig 137 | firestore?: boolean | FirestoreServiceConfig 138 | functions?: boolean | FunctionsServiceConfig 139 | storage?: boolean | StorageServiceConfig 140 | database?: boolean | DatabaseServiceConfig 141 | messaging?: boolean | MessagingServiceConfig 142 | performance?: boolean | PerformanceServiceConfig 143 | appCheck?: boolean | AppCheckServiceConfig 144 | analytics?: boolean | AnalyticsServiceConfig 145 | remoteConfig?: boolean | RemoteConfigServiceConfig 146 | } 147 | customEnv?: boolean 148 | onFirebaseHosting?: boolean | object 149 | terminateDatabasesAfterGenerate?: boolean 150 | } 151 | 152 | /*********************************** 153 | * Injections 154 | ************************************/ 155 | 156 | interface ReadyFunction { 157 | (): void 158 | } 159 | 160 | interface NuxtFireInstance { 161 | auth: firebase.auth.Auth 162 | authReady: ReadyFunction 163 | database: firebase.database.Database 164 | databaseReady: ReadyFunction 165 | firestore: firebase.firestore.Firestore 166 | firestoreReady: ReadyFunction 167 | functions: firebase.functions.Functions 168 | functionsReady: ReadyFunction 169 | storage: firebase.storage.Storage 170 | storageReady: ReadyFunction 171 | messaging: firebase.messaging.Messaging 172 | messagingReady: ReadyFunction 173 | performance: firebase.performance.Performance 174 | performanceReady: ReadyFunction 175 | appCheck: firebase.appCheck.AppCheck 176 | appCheckReady: ReadyFunction 177 | analytics: firebase.analytics.Analytics 178 | analyticsReady: ReadyFunction 179 | remoteConfig: firebase.remoteConfig.RemoteConfig 180 | remoteConfigReady: ReadyFunction 181 | } 182 | 183 | interface NuxtFireAuthStore { 184 | subscribe: () => Promise 185 | unsubscribe: () => void 186 | } 187 | 188 | declare module '@nuxt/vue-app' { 189 | interface NuxtConfiguration { 190 | firebase?: FirebaseModuleConfiguration 191 | } 192 | interface Context { 193 | $fireModule: typeof firebase 194 | $fire: NuxtFireInstance 195 | $fireAuthStore: NuxtFireAuthStore 196 | } 197 | interface NuxtAppOptions { 198 | $fireModule: typeof firebase 199 | $fire: NuxtFireInstance 200 | $fireAuthStore: NuxtFireAuthStore 201 | } 202 | } 203 | 204 | declare module '@nuxt/types' { 205 | interface Context { 206 | $fireModule: typeof firebase 207 | $fire: NuxtFireInstance 208 | $fireAuthStore: NuxtFireAuthStore 209 | } 210 | 211 | interface NuxtAppOptions { 212 | $fireModule: typeof firebase 213 | $fire: NuxtFireInstance 214 | $fireAuthStore: NuxtFireAuthStore 215 | } 216 | 217 | interface Configuration { 218 | firebase?: FirebaseModuleConfiguration 219 | } 220 | } 221 | 222 | declare module 'vue/types/vue' { 223 | interface Vue { 224 | $fireModule: typeof firebase 225 | $fire: NuxtFireInstance 226 | $fireAuthStore: NuxtFireAuthStore 227 | } 228 | } 229 | 230 | declare module '@nuxt/vue-app' { 231 | interface NuxtAppOptions { 232 | $fireModule: typeof firebase 233 | $fire: NuxtFireInstance 234 | $fireAuthStore: NuxtFireAuthStore 235 | } 236 | } 237 | 238 | declare module 'vuex/types/index' { 239 | interface Store { 240 | $fireModule: typeof firebase 241 | $fire: NuxtFireInstance 242 | $fireAuthStore: NuxtFireAuthStore 243 | } 244 | } 245 | 246 | /*********************************** 247 | * Misc 248 | ************************************/ 249 | 250 | export type FireAuthServerUser = Omit< 251 | auth.UserRecord, 252 | 'disabled' | 'metadata' | 'providerData' 253 | > & 254 | Partial> & { 255 | allClaims: auth.DecodedIdToken 256 | idToken: string 257 | } 258 | 259 | declare module 'http' { 260 | interface ServerResponse { 261 | locals: Record<'user', FireAuthServerUser> & Record 262 | } 263 | } 264 | --------------------------------------------------------------------------------