Repository: lupas/nuxt-fire
Branch: master
Commit: a3a111dd5bb4
Files: 129
Total size: 200.6 KB
Directory structure:
gitextract_svas7q_e/
├── .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.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.json
│ ├── layouts/
│ │ └── default.vue
│ ├── middleware/
│ │ └── testMiddleware.ts
│ ├── nuxt.config.ts
│ ├── package.json
│ ├── pages/
│ │ └── index.vue
│ ├── plugins/
│ │ └── lazyMode.js
│ ├── 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/
│ │ │ └── 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
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# Enables "Sponsor" button on project
github: lupas
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug report
about: Report a bug report to help us improve the module.
title: ''
labels: ''
assignees: ''
---
### Version
@nuxtjs/firebase:
firebase:
nuxt:
### Reproduction Link
### Steps to reproduce
### What is Expected?
### What is actually happening?
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: StackOverflow
url: https://stackoverflow.com/questions/tagged/firebase+nuxt.js
about: Ask general Nuxt & Firebase questions not specifically related to this module on StackOverflow.
- name: Nuxt Community Discord
url: https://discord.nuxtjs.org/
about: Asking more specific questions about the module on Discord.
- name: nuxt-firebase Documentation
url: https://firebase.nuxtjs.org/
about: Check our documentation before reporting issues or questions.
- name: Firebase Documentation
url: https://firebase.google.com/docs/web/setup
about: Make sure to study the Firebase documentation before asking questions, too.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea or enhancement for this project.
title: ''
labels: ''
assignees: ''
---
### Is your feature request related to a problem? Please describe.
### Describe the solution you'd like
### Describe alternatives you've considered
### Additional context
================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# macOS
.DS_Store
# Vim swap files
*.swp
**/demo/static/*sw.js
**/demo/static/sw.js
cache
================================================
FILE: .opensource/README.md
================================================
The `/.opensource/project.json` file is needed for the module to be featured on https://firebaseopensource.com.
================================================
FILE: .opensource/project.json
================================================
{
"name": "Nuxt Firebase-Module",
"platforms": [
"Web"
],
"content": "README.md",
"pages": [],
"tabs": [
{
"title": "Full Documentation",
"href": "https://firebase.nuxtjs.org/"
},
{
"title": "Nuxt.js (v2), Firestore & SSR",
"href": "https://medium.com/@pascalluther/nuxt-js-v2-firestore-ssr-938d8fb7d2b0"
}
]
}
================================================
FILE: .prettierrc.json
================================================
{
"semi": false,
"arrowParens": "always",
"singleQuote": true,
"bracketSpacing": false
}
================================================
FILE: .vscode/settings.json
================================================
{
"git.ignoreLimitWarning": true
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018-present Pascal Luther
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[](https://david-dm.org/nuxt-community/i18n-module)
[](https://snyk.io/test/github/nuxt-community/firebase-module)
[](https://npmjs.com/package/@nuxtjs/firebase)
[](https://npmjs.com/package/@nuxtjs/firebase)
> Easily integrate Firebase into your Nuxt project.
## IMPORTANT!
> ### ⚠️ **Nuxt 3 not supported ⚠️**:
>
> 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](https://vuefire.vuejs.org/nuxt/getting-started.html)
> ### ℹ️ **Modular Mode (Firebase v9+) ℹ️**:
>
> This module does not support the new modular syntax from Firebase v9+.
>
> 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).
>
> 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).
## Links
- 📘 [Documentation](https://firebase.nuxtjs.org/)
- 🔖 [Release notes](https://github.com/nuxt-community/firebase-module/releases)
- 👥 [Community](https://discord.nuxtjs.org/)
## Quick Setup
Make sure you are using Nuxt 2 and have Firebase v8 installed in your project.
```bash
yarn add firebase # OR npm i firebase
```
Install the module via NPM or Yarn:
```bash
yarn add @nuxtjs/firebase # OR npm i @nuxtjs/firebase
```
## Quick Config
Add the following to your nuxt.config.js.
See all configuration options [here](https://firebase.nuxtjs.org/guide/options/).
```js
modules: [
[
'@nuxtjs/firebase',
{
config: {
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: ''
},
services: {
auth: true // Just as example. Can be any other service.
}
}
]
],
```
## Quick Usage
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/)).
Example:
```js
try {
await this.$fire.auth.createUserWithEmailAndPassword('foo@foo.foo', 'test')
} catch (e) {
handleError(e)
}
```
## Guidelines for issues & feature requests
- Use the GitHub issue search — check if the issue or feature request has already been reported.
- Check if the issue has been fixed — try to reproduce it using the latest master or development branch in the repository.
- Isolate the problem — create a reduced test case and a live example.
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.
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.
If your issue does not suffice these guidelines, it might be closed immediately.
## License
MIT - [Nuxt-Community](https://github.com/nuxt-community) - [Pascal Luther](https://github.com/lupas)
================================================
FILE: package.json
================================================
{
"name": "@nuxtjs/firebase-monorepo",
"keywords": [
"firebase",
"firestore",
"google",
"googleauthentication",
"nuxt",
"realtimedatabase"
],
"homepage": "https://firebase.nuxtjs.org/",
"repository": "nuxt-community/firebase-module",
"license": "MIT",
"author": "Pascal Luther",
"workspaces": [
"packages/**"
],
"scripts": {
"heroku:setup": "heroku login && heroku git:remote -a nuxt-fire-demo",
"heroku:deploy": "git subtree push --prefix packages/demo heroku HEAD:master"
}
}
================================================
FILE: packages/demo/.eslintrc.js
================================================
module.exports = {
root: true,
env: {
browser: true,
node: true,
},
extends: [
'@nuxtjs/eslint-config-typescript',
'prettier',
'prettier/vue',
'plugin:prettier/recommended',
'plugin:nuxt/recommended',
],
plugins: ['prettier'],
// add your custom rules here
rules: {},
}
================================================
FILE: packages/demo/.firebaserc
================================================
{
"projects": {
"nuxt-fire-demo": "nuxt-fire-demo",
"default": "nuxt-fire-demo"
}
}
================================================
FILE: packages/demo/.prettierrc.js
================================================
module.exports = {
singleQuote: true,
arrowParens: 'always',
semi: false
}
================================================
FILE: packages/demo/Procfile
================================================
web: nuxt start
================================================
FILE: packages/demo/README.md
================================================
# 🔥 Nuxt-Fire Demo
> Example project using [nuxt-community/firebase-module](https://github.com/nuxt-community/firebase-module) to integrate Firebase into Nuxt.
## Demo
### [Live Demo](https://nuxt-fire-demo.herokuapp.com)
## Build Setup
```bash
# cd to src
$ cd src
# install dependencies
$ npm i
# start firebase emulators
$ npm run emulators
# serve with hot reload at localhost:3000
$ npm run dev
```
For detailed explanation on how things work, checkout [nuxt-community/firebase-module](https://github.com/nuxt-community/firebase-module).
## Issues
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).
================================================
FILE: packages/demo/components/Btn.vue
================================================
Loading...
================================================
FILE: packages/demo/components/Codeblock.vue
================================================
================================================
FILE: packages/demo/components/Form.vue
================================================
================================================
FILE: packages/demo/components/Logo/FirebaseLogo.vue
================================================
================================================
FILE: packages/demo/components/Logo/NuxtLogo.vue
================================================
================================================
FILE: packages/demo/components/Logo/index.vue
================================================
================================================
FILE: packages/demo/components/ServiceTitle.vue
================================================
{{ title }}
================================================
FILE: packages/demo/components/SubTitle.vue
================================================
{{ title }}
================================================
FILE: packages/demo/components/examples/Analytics.vue
================================================
Log Event
async logEvent() {
try {
await this.$fire.analytics.logEvent('analytics_button_clicked')
} catch (e) {
alert(e)
}
}
This will log an event in Firebase Analytics.
================================================
FILE: packages/demo/components/examples/AppCheck.vue
================================================
================================================
FILE: packages/demo/components/examples/Auth.vue
================================================
You are logged in with {{ authUser.email }}.
Logout
async createUser() {
try {
await this.$fire.auth.createUserWithEmailAndPassword('foo@foo.foo', 'test')
} catch (e) {
alert(e)
}
}
================================================
FILE: packages/demo/components/examples/Firestore.vue
================================================
Write to Firestore
async writeToFirestore() {
const messageRef = this.$fire.firestore.collection('message').doc('message')
try {
await messageRef.set({
message: 'Nuxt-Fire with Firestore rocks!'
})
} catch (e) {
alert(e)
return
}
alert('Success.')
}
Read from Firestore
async readFromFirestore() {
const messageRef = this.$fire.firestore.collection('message').doc('message')
try {
const messageDoc = await messageRef.get()
alert(messageDoc.data().message)
} catch (e) {
alert(e)
return
}
}
================================================
FILE: packages/demo/components/examples/Functions.vue
================================================
Call Test Function
Might take some seconds.
async callTestFunction() {
try {
const res = await this.$fire.functions.httpsCallable('testFunction')()
alert(res.data)
} catch (e) {
alert(e)
return
}
}
================================================
FILE: packages/demo/components/examples/Messaging.vue
================================================
Start Listeners
Request Permission
Get ID Token
Send Test Push Message
================================================
FILE: packages/demo/components/examples/Performance.vue
================================================
{{
traceStarted ? 'In Progress' : 'Start Trace'
}}
================================================
FILE: packages/demo/components/examples/RealTimeDatabase.vue
================================================
Write to Realtime DB
async writeToRealtimeDb() {
const messageRef = this.$fire.database.ref('message')
try {
await messageRef.set({
message: 'Nuxt-Fire with Firebase Realtime Database rocks!'
})
} catch (e) {
alert(e)
return
}
alert('Success.')
}
Read from Realtime DB
async readFromRealtimeDb() {
const messageRef = this.$fire.database.ref('message')
try {
const snapshot = await messageRef.once('value')
alert(snapshot.val().message)
} catch (e) {
alert(e)
return
}
}
================================================
FILE: packages/demo/components/examples/RemoteConfig.vue
================================================
Reads Remote Config
async readRemoteConfig() {
try {
await this.$fire.remoteConfig.fetchAndActivate();
} catch (e) {
alert(e);
return;
}
const exampleMessage = await this.$fire.remoteConfig.getValue("exampleMessage");
alert(
`Success. Read RemoteConfig parameter 'exampleMessage' is: ${exampleMessage._value}`
);
}
================================================
FILE: packages/demo/components/examples/Storage.vue
================================================
Upload File
async uploadFile() {
const storageRef = this.$fire.storage.ref().child('message.txt')
const message = 'Nuxt-Fire with Firebase Storage rocks!'
try {
const snapshot = await storageRef.putString(message)
alert('File uploaded.')
} catch (e) {
alert(e.message)
}
}
Get File URL
async getFileUrl() {
const storageRef = this.$fire.storage.ref().child('message.txt')
try {
const url = await storageRef.getDownloadURL()
alert(`The file can be found here: ${url}`)
} catch (e) {
alert(e.message)
}
}
================================================
FILE: packages/demo/components/examples/VuexStore.vue
================================================
Tests if fireXXX objects can be accessed in a vuex store action.
Test Vuex Store
================================================
FILE: packages/demo/firebase.json
================================================
{
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"emulators": {
"functions": {
"port": 12345
},
"firestore": {
"port": 8080
},
"database": {
"port": 9000
},
"hosting": {
"port": 5000
},
"auth": {
"port": 9099
},
"storage": {
"port": 9199
},
"ui": {
"enabled": true
}
},
"storage": {
"rules": "storage.rules"
}
}
================================================
FILE: packages/demo/functions/.gitignore
================================================
node_modules/
================================================
FILE: packages/demo/functions/index.js
================================================
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp()
const messaging = admin.messaging()
exports.testFunction = functions.https.onCall(() => {
console.info('Test Function triggered')
return { message: "Yeaaahh it's working!" }
})
exports.sendTestPushMessage = functions.https.onCall(async (data) => {
// As defined in https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages
const image =
'https://avatars2.githubusercontent.com/u/4020037?s=460&u=c5f9c131d565202d8e530295b130239edd25768d&v=4'
const message = {
name: 'testPushMessage',
data: {},
notification: {
title: `Test Push Message`,
body: 'If you get this, it worked.',
image,
},
android: {},
webpush: {
notification: {
// Adds the image to the push notificationm
icon: image,
// Adds actions to the push notification
actions: [
{
action: 'goToLupasGithub',
title: 'Github: lupas',
icon: '',
},
{
action: 'goToModuleGithub',
title: 'Firebase Module',
icon: '',
},
],
},
fcm_options: {
// Adds a link to be opened when clicked on the push notification
link: 'https://nuxt-fire-demo.herokuapp.com/',
},
},
apns: {
fcm_options: {},
},
fcm_options: {},
token: data.token,
}
try {
await messaging.send(message)
} catch (e) {
console.error(`Did not work to send a message to token ${message.token}`)
console.error(e)
}
})
================================================
FILE: packages/demo/functions/package.json
================================================
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log",
"emulate": "firebase emulators:start --only functions"
},
"engines": {
"node": "12"
},
"dependencies": {
"firebase-admin": "^10.0.1",
"firebase-functions": "^3.11.0"
},
"devDependencies": {
"firebase-functions-test": "^0.3.3"
},
"private": true
}
================================================
FILE: packages/demo/layouts/default.vue
================================================
================================================
FILE: packages/demo/middleware/testMiddleware.ts
================================================
import { Middleware } from '@nuxt/types'
const testMiddleware: Middleware = ({ app, store }) => {
if (app.$fire.auth) {
// If user is logged in, store.state.authUser will be filled.
// INFO -> Firebase Services can be accessed with app.$fire.auth (etc.) in Middleware.
}
}
export default testMiddleware
================================================
FILE: packages/demo/nuxt.config.ts
================================================
import { NuxtConfig } from '@nuxt/types'
const isDev = process.env.NODE_ENV === 'development'
const useEmulators = false // manually change if emulators needed
const config: NuxtConfig = {
head: {
title: 'nuxt-firebase-demo',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
components: true,
buildModules: [
'@nuxt/typescript-build',
'@nuxtjs/tailwindcss',
'@nuxtjs/firebase',
],
firebase: {
lazy: false,
config: {
apiKey: 'AIzaSyDa-YwgWTp2GDyVYEfv-XLb62100_HoEvU',
authDomain: 'nuxt-fire-demo.firebaseapp.com',
projectId: 'nuxt-fire-demo',
storageBucket: 'nuxt-fire-demo.appspot.com',
messagingSenderId: '807370470428',
appId: '1:807370470428:web:26da98c86c3fd352',
measurementId: 'G-XT6PVC1D4X',
},
onFirebaseHosting: false,
terminateDatabasesAfterGenerate: true,
services: {
auth: {
initialize: {
onAuthStateChangedAction: 'onAuthStateChanged',
},
ssr: true,
emulatorPort: isDev && useEmulators ? 9099 : undefined,
disableEmulatorWarnings: false,
},
firestore: {
memoryOnly: false,
enablePersistence: true,
emulatorPort: isDev && useEmulators ? 8080 : undefined,
},
functions: {
emulatorPort: isDev && useEmulators ? 12345 : undefined,
},
storage: {
emulatorPort: isDev && useEmulators ? 9199 : undefined,
emulatorHost: 'localhost',
},
database: {
emulatorPort: isDev && useEmulators ? 9000 : undefined,
},
performance: true,
analytics: true,
remoteConfig: {
settings: {
fetchTimeoutMillis: 60000,
minimumFetchIntervalMillis: 43200000,
},
defaultConfig: {
welcome_message: 'Welcome',
},
},
// breaks the app with 'app.$fire.firestore.collection is not a function':
appCheck: true,
messaging: {
createServiceWorker: true,
actions: [
{
action: 'goToLupasGithub',
url: 'https://github.com/lupas',
},
{
action: 'goToModuleGithub',
url: 'https://github.com/nuxt-community/firebase-module',
},
],
fcmPublicVapidKey:
'BL_xoiuOe5vbb2vJkCNnuswn03NwCsyCkJUgRbuQA5tpg7J4E4z50MO8b-wrrad6fcysYAaFjHqU7D9o0oCWL8w',
},
},
},
modules: ['@nuxtjs/pwa'],
// plugins: ['~/plugins/lazyMode'],
build: {},
/*
** Nuxt.js Middleware
*/
router: {
middleware: ['testMiddleware'],
},
pwa: {
workbox: {
importScripts: ['/firebase-auth-sw.js'],
// by default the workbox module will not install the service worker in dev environment to avoid conflicts with HMR
// only set this true for testing and remember to always clear your browser cache in development
dev: process.env.NODE_ENV === 'development',
},
},
}
export default config
================================================
FILE: packages/demo/package.json
================================================
{
"name": "nuxt-firebase-demo",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
"lint": "npm run lint:js",
"emulators": "firebase emulators:start"
},
"dependencies": {
"@nuxtjs/pwa": "^3.3.3",
"core-js": "^3.19.2",
"firebase": "^9.6.2",
"firebase-admin": "^10.0.1",
"nuxt": "^2.15.8",
"prismjs": "^1.25.0",
"vue-prism-component": "^2.0.0",
"@nuxtjs/firebase": "^8.2.0"
},
"devDependencies": {
"@nuxt/types": "^2.15.8",
"@nuxt/typescript-build": "^2.1.0",
"@nuxtjs/eslint-config": "^8.0.0",
"@nuxtjs/eslint-config-typescript": "^8.0.0",
"@nuxtjs/eslint-module": "^3.0.2",
"@nuxtjs/tailwindcss": "^4.2.1",
"babel-eslint": "^10.1.0",
"eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^3.1.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.8.4"
}
}
================================================
FILE: packages/demo/pages/index.vue
================================================
================================================
FILE: packages/demo/plugins/lazyMode.js
================================================
export default async (context) => {
await context.$fire.databaseReady()
await context.$fire.firestoreReady()
await context.$fire.storageReady()
await context.$fire.functionsReady()
if (process.client) {
await context.$fire.authReady()
await context.$fireAuthStore.subscribe()
await context.$fire.messagingReady()
await context.$fire.performanceReady()
await context.$fire.analyticsReady()
await context.$fire.remoteConfigReady()
}
}
================================================
FILE: packages/demo/storage.rules
================================================
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}
================================================
FILE: packages/demo/store/actions.js
================================================
export default {
async nuxtServerInit({ dispatch }, ctx) {
// INFO -> Nuxt-fire Objects can be accessed in nuxtServerInit action via this.$fire___, ctx.$fire___ and ctx.app.$fire___'
/** Get the VERIFIED authUser on the server */
if (ctx.res && ctx.res.locals && ctx.res.locals.user) {
const { allClaims: claims, ...authUser } = ctx.res.locals.user
console.info(
'Auth User verified on server-side. User: ',
authUser,
'Claims:',
claims
)
await dispatch('onAuthStateChanged', {
authUser,
claims,
})
}
},
async onAuthStateChanged({ commit }, { authUser }) {
if (!authUser) {
commit('RESET_STORE')
return
}
if (authUser && authUser.getIdToken) {
try {
const idToken = await authUser.getIdToken(true)
console.info('idToken', idToken)
} catch (e) {
console.error(e)
}
}
commit('SET_AUTH_USER', { authUser })
},
checkVuexStore(ctx) {
if (this.$fire.auth === null) {
throw 'Vuex Store example not working - this.$fire.auth cannot be accessed.'
}
alert(
'Success. Nuxt-fire Objects can be accessed in store actions via this.$fire___'
)
},
}
================================================
FILE: packages/demo/store/getters.js
================================================
export default {
isLoggedIn: (state) => {
try {
return state.authUser.uid !== null
} catch {
return false
}
}
}
================================================
FILE: packages/demo/store/mutations.js
================================================
import initialState from './state'
export default {
RESET_STORE: (state) => {
Object.assign(state, initialState())
},
SET_AUTH_USER: (state, { authUser }) => {
state.authUser = {
uid: authUser.uid,
email: authUser.email
}
}
}
================================================
FILE: packages/demo/store/state.js
================================================
export default () => ({
authUser: null
})
================================================
FILE: packages/demo/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2018",
"module": "ESNext",
"moduleResolution": "Node",
"lib": [
"ESNext",
"ESNext.AsyncIterable",
"DOM"
],
"esModuleInterop": true,
"allowJs": true,
"sourceMap": true,
"strict": true,
"noEmit": true,
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
},
"types": [
"@types/node",
"@nuxt/types",
"@nuxtjs/firebase"
]
},
"exclude": [
"node_modules",
".nuxt",
"dist"
]
}
================================================
FILE: packages/demo/vue-shim.d.ts
================================================
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
================================================
FILE: packages/docs/README.md
================================================
# @nuxtjs/firebase-docs
## Setup
Install dependencies:
```bash
npm i
```
## Development
```bash
npm run dev
```
## Static Generation
This will create the `.vitepress/dist` directory for publishing to static hosting:
```bash
npm run build
```
================================================
FILE: packages/docs/docs/.vitepress/config.ts
================================================
import {defineConfig, DefaultTheme} from 'vitepress'
import {version} from '../../package.json'
import {
twitter,
github,
headTitle,
headDescription,
ogImage,
ogUrl,
} from './meta'
import sidebar from './navigation/sidebar'
export default defineConfig({
lang: 'en-US',
title: headTitle,
description: headDescription,
appearance: 'dark',
head: [
['meta', {name: 'theme-color', content: '#ffe183'}],
['link', {rel: 'icon', href: '/icon.png', type: 'image/png'}],
[
'link',
{
rel: 'alternate icon',
href: '/favicon.ico',
type: 'image/png',
sizes: '16x16',
},
],
[
'meta',
{
name: 'author',
content: `Pascal Luther`,
},
],
[
'meta',
{
name: 'keywords',
content: 'nuxt, nuxtjs, firebase',
},
],
['meta', {property: 'og:title', content: headTitle}],
['meta', {property: 'og:description', content: headDescription}],
['meta', {property: 'og:url', content: ogUrl}],
['meta', {property: 'og:image', content: ogImage}],
['meta', {name: 'twitter:title', content: headTitle}],
['meta', {name: 'twitter:description', content: headDescription}],
['link', {rel: 'mask-icon', href: '/icon.png', color: '#ffffff'}],
[
'link',
{
rel: 'apple-touch-icon',
href: '/apple-touch-icon.png',
sizes: '180x180',
},
],
],
themeConfig: {
logo: '/icon.png',
outline: [2, 3],
socialLinks: [
{icon: 'twitter', link: twitter},
{icon: 'github', link: github},
],
footer: {
copyright: 'Copyright © 2019-PRESENT Pascal Luther',
},
algolia: {
appId: '9F70EYJ2LK',
apiKey: 'cf7ef157f34e96340604d0d75a6fbc1c', // Public Read-Only API Key
indexName: 'nuxtjs_firebase',
},
carbonAds: {
code: 'CE7D62JL',
placement: 'firebasenuxtjsorg',
},
nav: [
{text: 'Guide', link: '/guide/'},
{
text: `v${version}`,
items: [
{
text: 'Release Notes',
link: 'https://github.com/nuxt-community/firebase-module/releases',
},
],
},
],
sidebar: sidebar,
},
})
================================================
FILE: packages/docs/docs/.vitepress/meta.ts
================================================
// noinspection ES6PreferShortImport: IntelliJ IDE hint to avoid warning to use `~/contributors`, will fail on build if changed
/* Texts */
export const headTitle = "Nuxt Firebase";
export const headSubtitle = "Nuxt Firebase";
export const headDescription = "XXX";
/* CDN fonts and styles */
export const googleapis = "https://fonts.googleapis.com";
export const gstatic = "https://fonts.gstatic.com";
export const font = `${googleapis}/css2?family=Readex+Pro:wght@200;400;600&display=swap`;
/* vitepress head */
export const ogUrl = "https://firebase.nuxtjs.org";
export const ogImage = `${ogUrl}og.png`;
/* GitHub and social links */
export const github = "https://github.com/nuxt-community/firebase-module";
export const releases = "https://github.com/vuejs/vuefire/releases";
export const twitter = "https://twitter.com/nuxt_js";
/* Avatar/Image/Sponsors servers */
export const preconnectLinks = [googleapis, gstatic];
export const preconnectHomeLinks = [googleapis, gstatic];
/* PWA runtime caching urlPattern regular expressions */
export const pwaFontsRegex = new RegExp(`^${googleapis}/.*`, "i");
export const pwaFontStylesRegex = new RegExp(`^${gstatic}/.*`, "i");
// eslint-disable-next-line prefer-regex-literals
export const githubusercontentRegex = new RegExp(
"^https://((i.ibb.co)|((raw|user-images).githubusercontent.com))/.*",
"i"
);
================================================
FILE: packages/docs/docs/.vitepress/navigation/sidebar.ts
================================================
import {DefaultTheme} from 'vitepress'
const sidebar: DefaultTheme.Sidebar = {
'/': [
{
text: 'Guide',
items: [
{
text: 'Introduction',
link: '/guide/',
},
{
text: 'Getting Started',
link: '/guide/getting-started',
},
{
text: 'Options',
link: '/guide/options',
},
{
text: 'Usage',
link: '/guide/usage',
},
],
},
{
text: 'Service Options',
items: [
{
text: '(All Services)',
link: '/service-options/all-services',
},
{
text: 'appCheck',
link: '/service-options/app-check',
},
{
text: 'auth',
link: '/service-options/auth',
},
{
text: 'firestore',
link: '/service-options/firestore',
},
{
text: 'database',
link: '/service-options/database',
},
{
text: 'storage',
link: '/service-options/storage',
},
{
text: 'functions',
link: '/service-options/functions',
},
{
text: 'performance',
link: '/service-options/performance',
},
{
text: 'analytics',
link: '/service-options/analytics',
},
{
text: 'messaging',
link: '/service-options/messaging',
},
{
text: 'remote-config',
link: '/service-options/remote-config',
},
],
},
{
text: 'Tutorials',
items: [
{
text: 'Firebase Auth with SSR',
link: '/tutorials/ssr',
},
{
text: 'Usage with vuexfire',
link: '/tutorials/vuexfire',
},
{
text: 'Usage with Typescript',
link: '/tutorials/typescript',
},
],
},
{
text: 'Community',
items: [
{
text: 'Demo',
link: '/community/demo',
},
{
text: 'Links',
link: '/community/links',
},
{
text: 'FAQ',
link: '/community/faq',
},
],
},
],
}
export default sidebar
================================================
FILE: packages/docs/docs/.vitepress/style/vars.css
================================================
/**
* Colors
* -------------------------------------------------------------------------- */
/* 50: '#fff8e1',
100: '#ffedb3',
200: '#ffe183',
300: '#ffd650',
400: '#ffcb29',
500: '#ffc309',
600: '#ffb401',
700: '#ffa200',
800: '#ff9100',
900: '#ff7100', */
:root {
--vp-c-brand: #00dc82;
--vp-c-brand-light: #03ee8c;
--vp-c-accent: #f78200;
--c-gradient-1: #00dc82;
--c-gradient-2: #f78200;
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-text: var(--vp-c-text-dark-1);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-brand-hover-text: var(--vp-c-text-dark-1);
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-active-text: var(--vp-c-text-dark-1);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
var(--c-gradient-1) 25%,
var(--c-gradient-2)
);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
var(--vp-c-brand) 30%,
var(--vp-c-accent)
);
--vp-home-hero-image-filter: blur(30px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(72px);
}
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand) !important;
}
.dark-only {
display: none;
}
.dark .dark-only {
display: block;
}
.dark .light-only {
display: none;
}
================================================
FILE: packages/docs/docs/.vitepress/theme/index.ts
================================================
import Theme from "vitepress/theme";
import "../style/vars.css";
import { h } from "vue";
export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {});
},
};
================================================
FILE: packages/docs/docs/community/demo.md
================================================
# Demo
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.
================================================
FILE: packages/docs/docs/community/faq.md
================================================
# FAQ
Create an [issue](https://github.com/nuxt-community/firebase-module/issues) if you have a question and we might add it to the FAQ.
## Firestore: Using "array-contains" or "array-contains-any" does not work
If you are using `array-contains` or `array-contains-any` you might run into the followig error:
> Function Query.where() called with invalid data. Unsupported field value: a custom Array object
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:
::: code-group
```js [nuxt.config.js]
render: {
bundleRenderer: {
runInNewContext: false
}
},
```
:::
## How to add Firebase Polyfills?
If you want to add Firebase polyfills, you need to ceate a plugin and import the required polyfills like so:
1. Creating `/plugins/polyfills.js` containing:
::: code-group
```js [polyfills.js]
// Import all polyfills
import '@firebase/polyfill'
// Import specific polyfills:
import '@firebase/polyfill/node_modules/core-js/features/object/values'
```
:::
2. Add to your nuxt.config.js:
::: code-group
```js [nuxt.config.js]
plugins: [
{ src: '~plugins/polyfills', mode: 'client' },
],
```
:::
> References:
> [Issue #307](https://github.com/nuxt-community/firebase-module/issues/307)
> [Stack Overflow Question](https://stackoverflow.com/questions/62308061/nuxt-firebase-ie-11-object-doesnt-support-property-or-method-values/64062207#64062207)
## How to use this module in SSR mode together with Strapi?
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:
```js
auth: {
ssr: {
// ...
ignorePaths: ['/api/'] // or /^api\//
}
}
```
> References:
> [Issue #292](https://github.com/nuxt-community/firebase-module/issues/292)
## Nuxt Generate warns with "Nuxt Generate finished but did not exit"
This warning happens because either Firestore or the RealtimeDb are not terminated at the end of Nuxt Generate.
To get rid of this warning, you can terminate the services by extending the `generate:done` hook in your `nuxt.config.js` like so:
::: code-group
```js [nuxt.config.js]
hooks: {
generate: {
async done(builder) {
const appModule = await import('./.nuxt/firebase/app.js')
const { session } = await appModule.default(
builder.options.firebase.config,
{
res: null,
}
)
try {
session.database().goOffline()
} catch (e) { }
try {
session.firestore().terminate()
} catch (e) { }
},
},
},
```
:::
> References:
> [Issue #93](https://github.com/nuxt-community/firebase-module/issues/93)
================================================
FILE: packages/docs/docs/community/links.md
================================================
# Links
Collection of Links related to this module:
### Articles
- [Nuxt.js (v2), Firestore & SSR 🔥](https://medium.com/@pascalluther/nuxt-js-v2-firestore-ssr-938d8fb7d2b0?)
Medium Article about integrating Firestore with Nuxt.js v2.
- [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.
- [@nuxtjs/firebase social auth](https://dev.to/rodrigopv/nuxtjs-firebase-social-auth-3afe)
Article about how to integrate social auth with nuxtjs/firebase
### Videos
- [Nuxt Firebase로 블로그 만들어보기 12 파이어베이스 인증해보기](https://www.youtube.com/watch?v=Zd6PSfgH3t4) Tutorial video on how to integrate Firebase Auth with nuxt-fire (in Korean)
================================================
FILE: packages/docs/docs/guide/getting-started.md
================================================
# Getting Started
## Requirements
Make sure you are using Nuxt 2 and have Firebase v8 installed in your project.
::: code-group
```bash [yarn]
yarn add firebase@^8
```
```bash [npm]
npm install firebase@^8
```
:::
::: danger IMPORTANT - Nuxt 3 not supported!
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
:::
## Install
Install the module via NPM or Yarn.
::: code-group
```bash [yarn]
yarn add @nuxtjs/firebase
```
```bash [npm]
npm install @nuxtjs/firebase
```
:::
## Configure
Add the below code to your **nuxt.config.js** modules array and adjust it according to your needs.
Visit the [config section](/guide/options#config) for a detailed overview about each configuration.
### Example Configuration
::: code-group
```js [nuxt.config.js]
modules: [
[
'@nuxtjs/firebase',
{
config: {
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: ''
},
services: {
auth: true // Just as example. Can be any other service.
}
}
]
],
```
:::
See list of all available services [here](/guide/options#services).
You can also separate the config from the module array by using the **firebase** object:
::: code-group
```js [nuxt.config.js]
modules: ['@nuxtjs/firebase'],
firebase: {
// options
}
```
:::
================================================
FILE: packages/docs/docs/guide/index.md
================================================
# Nuxt Firebase
::: danger IMPORTANT - Nuxt 3 not supported!
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
:::
::: warning Modular Mode (Firebase v9+)
This module does NOT support the new modular syntax from Firebase v9+.
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.
It is currently unclear when, and if, this module will support the new modular mode. See discussion.
:::
## What is this?
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.
By importing each individual Firebase service dynamically this module reduces bundle sizes and improves performance of your Nuxt.js app with Firebase.
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.
## How does it work?
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.
================================================
FILE: packages/docs/docs/guide/options.md
================================================
# Options
## config
Your firebase config snippet and other Firebase specific parameters. You can retrieve this information from your Firebase project's overview page:
`https://console.firebase.google.com/project//overview`
::: code-group
```js [nuxt.config.js]
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: ''
}
```
:::
::: info
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'`.
You can also specify multiple custom environments as mentioned in the [customEnv](/guide/options#customenv) option below.
:::
## services
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.
Available services:
::: code-group
```js [nuxt.config.js]
services: {
auth: true,
firestore: true,
functions: true,
storage: true,
database: true,
messaging: true,
performance: true,
appCheck: true,
analytics: true,
remoteConfig: true,
```
:::
Each service has advanced options that you can configure. See the **service options** section for more details.
## customEnv
- Type: `Boolean`
- Default: `false`
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**.
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.
::: danger
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.
::: danger
::: code-group
```js [nuxt.config.js]
env: {
FIRE_ENV: process.env.FIRE_ENV
}
```
:::
After that, you can set FIRE_ENV to anything you like...
```js[package.json]
"scripts": {
"serveFoo": "FIRE_ENV=foofoofoo nuxt",
"serveFaa": "FIRE_ENV=faafaafaa nuxt",
}
```
And then add your config to the module options:
::: code-group
```js [nuxt.config.js]
// within the module's config
config: {
foofoofoo: {
apiKey: '',
authDomain: '',
databaseURL: '', // Optional
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: ''
},
faafaafaa: {
//
}
}
```
:::
## onFirebaseHosting
- Type: `Boolean` or `Object`
- Default: `false`
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.
## lazy
- Type: `Boolean` or `Object`
- Default: `false`
This allows lazy loading of all Firebase services.
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:
| Firebase Service | Shortcut |
| ----------------- | ------------------------- |
| Authentication | $fire.authReady() |
| Realtime Database | $fire.databaseReady() |
| Firestore | $fire.firestoreReady() |
| Storage | $fire.storageReady() |
| Functions | $fire.functionsReady() |
| Messaging | $fire.messagingReady() |
| Performance | $fire.performanceReady() |
| Analytics | $fire.analyticsReady() |
| Remote Config | $fire.remoteConfigReady() |
| App Check | $fire.appCheckReady() |
Simply call the `await this.$fire.serviceNameReady()` function before you access `this.$fire.serviceName` and the service gets dynamically loaded only when needed.
If the services was already loaded previously, the service does not get loaded a second time.
**Example:**
```js
// 1. Load the service
await this.$fire.authReady()
// 2. Use the service
await this.$fire.auth.createUserWithEmailAndPassword('foo@foo.foo', 'test')
```
::: danger Be aware
You can either enabled lazy loading for all services or none.
:::
## injectModule
- Type: `Boolean` or `Object`
- Default: `true`
Whether to inject the entire [Firebase module](/guide/usage#firemodule) as `this.$fireModule` or not.
## terminateDatabasesAfterGenerate
- Type: `Boolean`
- Default: `false`
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:
> The command 'nuxt generate' finished but did not exit after 5s
> This is most likely not caused by a bug in Nuxt
> Make sure to cleanup all timers and listeners you or your plugins/modules start.
> Nuxt will now force exit
>
> DeprecationWarning: Starting with Nuxt version 3 this will be a fatal error
================================================
FILE: packages/docs/docs/guide/usage.md
================================================
# Usage
## General Usage
This module injects two main utilities into your context, `$fire` and `$fireModule`.
You can access these in almost any context using `app.$fire`/`app.$fireModule` or `this.$fire`/`this.$fireModule` - including store actions.
::: danger Understand the difference!
While `$fire` contains the initialized service instances, `$fireModule` gives you access to the (not-initialized) **Firebase** module itself with all its static methods.
:::
### $fire
`$fire` gives you access to the initialized service instances:
| Firebase Service | Shortcut | Client/Server |
| ----------------- | ------------------ | --------------- |
| Authentication | $fire.auth | Client + Server |
| Realtime Database | $fire.database | Client + Server |
| Firestore | $fire.firestore | Client + Server |
| Storage | $fire.storage | Client + Server |
| Functions | $fire.functions | Client + Server |
| Messaging | $fire.messaging | Client-only |
| Performance | $fire.performance | Client-only |
| Analytics | $fire.analytics | Client-only |
| Remote Config | $fire.remoteConfig | Client-only |
See [Firebase's official docs](https://firebase.google.com/docs/) for more usage information.
::: warning Be aware
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.
:::
### $fireModule
`$fireModule` gives you access to the **Firebase** modules themselves with all their static methods.
| Firebase Module | Shortcut |
| --------------------- | ------------------------ |
| firebase.auth | $fireModule.auth |
| firebase.database | $fireModule.database |
| firebase.firestore | $fireModule.firestore |
| firebase.storage | $fireModule.storage |
| firebase.functions | $fireModule.functions |
| firebase.messaging | $fireModule.messaging |
| firebase.performance | $fireModule.performance |
| firebase.analytics | $fireModule.analytics |
| firebase.remoteConfig | $fireModule.remoteConfig |
## Examples
Access Firebase Authentication in a component method:
```js
export default {
methods: {
async createUser() {
try {
await this.$fire.auth.createUserWithEmailAndPassword(
'foo@foo.foo',
'test'
)
} catch (e) {
handleError(e)
}
},
},
}
```
Access Firestore and it's Object in a vuex store action:
```js
export default {
async randomVuexAction({commit, state, rootState}, userId) {
const ref = this.$fire.firestore.collection('users').doc(userId)
try {
await exerciseRef.update({
[`randomFoo.FooFoo`]: this.$fireModule.firestore.FieldValue.delete(),
})
} catch (e) {
return Promise.reject(e)
}
},
}
```
================================================
FILE: packages/docs/docs/index.md
================================================
---
layout: 'home'
title: Nuxt Firebase
titleTemplate: Easily integrate Firebase into your Nuxt project
hero:
name: Nuxt Firebase
text: Documentation
tagline: Easily integrate Firebase into your Nuxt project
image:
src: /icon.png
alt: Nuxt Firebase Logo
actions:
- theme: brand
text: Get Started
link: /guide/
- theme: alt
text: View on GitHub
link: https://github.com/nuxt-community/firebase-module
features:
- title: Simple Setup
details: Minimal setup required to integrate all Firebase services into your Nuxt.js application.
- title: Performant
details: The module uses dynamic imports of each individual Firebase service to reduce bundle sizes and improve performance.
- title: Additional Features
details: Enjoy the benefits of additional features such as automated setup of .onAuthStateChanged() for Firebase Authentication and more.
---
================================================
FILE: packages/docs/docs/public/service-worker.js
================================================
// force clearing previous service worker
self.addEventListener('install', function (e) {
self.skipWaiting()
})
self.addEventListener('activate', function (e) {
self.registration
.unregister()
.then(function () {
return self.clients.matchAll()
})
.then(function (clients) {
clients.forEach((client) => client.navigate(client.url))
})
})
================================================
FILE: packages/docs/docs/service-options/all-services.md
================================================
# All Services
All services have the following options:
::: code-group
```js [nuxt.config.js]
[serviceName]: {
static: false, // default
preload: false, // default
chunkName: process.env.NODE_ENV !== 'production' ? `firebase-${serviceName}` : '[id]' // default
}
```
:::
## static
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`.
```js
// static: false (default)
await import 'firebase/auth'
// static: true
import 'firebase/auth'
```
## preload
Preloads dynamically loaded services. More information [here](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules).
::: warning Be aware
Only applies if `static === false`.
:::
## chunkName
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.
::: warning Be aware
Only applies if `static === false`.
:::
================================================
FILE: packages/docs/docs/service-options/analytics.md
================================================
# analytics
::: danger Client-only
Make sure to wrap universal code in `if (process.client) {}`.
:::
Initializes **Firebase Analytics** and makes it available via `$fire.analytics` and `$fireModule.analytics`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
analytics: {
collectionEnabled: true // default
}
```
:::
## collectionEnabled
Allows to disable analytics collection. Usefull to disable analytics in development mode or before fullfillment of legal obligation.
Can be enabled back via `$fireAnalytics.setAnalyticsCollectionEnabled(true)`.
================================================
FILE: packages/docs/docs/service-options/app-check.md
================================================
# appCheck
::: danger Client-only
Make sure to wrap universal code in `if (process.client) {}`.
:::
Initializes **Firebase App Check** and makes it available via `$fire.appCheck` and `$fireModule.appCheck`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
appCheck: {
debugToken: false, // default
}
```
:::
================================================
FILE: packages/docs/docs/service-options/auth.md
================================================
# auth
Initializes **Firebase Authentication** and makes it available via `$fire.auth` and `$fireModule.auth`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
auth: {
persistence: 'local', // default
initialize: {
onAuthStateChangedMutation: 'ON_AUTH_STATE_CHANGED_MUTATION',
onAuthStateChangedAction: 'onAuthStateChangedAction',
subscribeManually: false
},
ssr: false, // default
emulatorPort: 9099,
emulatorHost: 'http://localhost',
}
```
:::
## persistence
Set firebase auth persistence, see [here](https://firebase.google.com/docs/auth/web/auth-state-persistence).
## initialize
This sets up an `onAuthStateChanged()` and/or `onIdTokenChanged()` listener and hooks them up to the vuex store.
Just add a mutation/action to your vuex store ([as seen below](#onauthstatechangedmutation)) that handles what to do with the authUser object (e.g. save it to the state or get user data from FireStore) and then define the name of the action/mutation in the `firebase.services.auth.initialize` configuration as above.
::: info
You can also use namespaces for your store actions/mutations like so: `onAuthStateChangedAction: 'namespaceName/actionName'`.
:::
When `onAuthStateChanged()` or `onIdTokenChanged()` get triggered by Firebase, the defined mutation/action will be called with the `authUser` and `claims` attributes as [as seen below](#onauthstatechangedmutation)
To unsubscribe from both listeners simply call the `$fireAuthStore.unsubscribe()` function.
::: warning Be aware
This does not work in _lazy-mode_, since auth is not initialized. If you want to use this option in lazy-mode, call the _authReady()_ function in a separate plugin.
:::
### onAuthStateChangedMutation
```js
ON_AUTH_STATE_CHANGED_MUTATION: (state, {authUser, claims}) => {
if (!authUser) {
// claims = null
// perform logout operations
} else {
// Do something with the authUser and the claims object...
}
}
```
::: warning Be aware
Do not save the `authUser` directly to the store, since this will save an object reference to the state which gets directly updated by Firebase Auth periodically and therefore throws a `vuex` error if `strict != false`.
```js
export const mutations = {
ON_AUTH_STATE_CHANGED_MUTATION: (state, {authUser, claims}) => {
// Don't do this:
state.user = authUser
// Do this:
const {uid, email, emailVerified} = authUser
state.user = {uid, email, emailVerified}
},
}
```
:::
### onAuthStateChangedAction
```js
onAuthStateChangedAction: (ctx, {authUser, claims}) => {
if (!authUser) {
// claims = null
// Perform logout operations
} else {
// Do something with the authUser and the claims object...
}
}
```
### onIdTokenChangedAction
Same as `onAuthStateChangedAction`, but also gets triggered when the idToken changes (e.g. expires).
::: warning Be aware
The Firebase SDK automatically refreshed your id token, so this option shall only be used if you use the idToken for custom authentication scenarios.
:::
### onIdTokenChangedMutation
Same as `onAuthStateChangedMutation`, but also gets triggered when the idToken changes (e.g. expires).
::: warning Be aware
The Firebase SDK automatically refreshed your id token, so this option shall only be used if you use the idToken for custom authentication scenarios.
:::
### subscribeManually
By settings `subscribeManually: true`, the `onAuthStateChanged()` listener won't be set up until you call it manually:
```js
// e.g. in a seperate Plugin
this.$fireAuthStore.subscribe()
```
This is needed in case you need to start other plugins _after_ Firebase is initialized but _before_ `onAuthStateChanged()` is set up.
::: info Example:
For example with the Sentry module, you migth want to set some user-related information in Sentry each time `onAuthStateChanged` is triggered. In that case, Sentry needs to be setup before `onAuthStateChanged()`.
You can achieve this by manually calling `this.$fireAuthStore.subscribe()` after Sentry has been initialized.
:::
## ssr
This sets up SSR ready functionality with minimal effort.
If `ssr = true`, the module generates a service worker that refreshes the Firebase Auth idToken and sends it with each request to the server if the user is logged in, as described [here](https://firebase.google.com/docs/auth/web/service-worker-sessions).
The option further adds a plugin that checks on server side if the token is valid and then injects a simplified [`admin.auth.UserRecord`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserRecord) into the context variable `res.locals.user`.
The simplified user record contains the following properties:
- `uid`: The users uid
- `email`: The users email
- `emailVerified`: If the email was verified
- `displayName`: The users display name
- `allClaims`: All claims from the [admin.auth.DecodedIdToken](https://firebase.google.com/docs/reference/admin/node/admin.auth.DecodedIdToken)
The injected user can be used by context aware life cycle hooks on the server side (e.g. the store action `nuxtServerInit`).
A tutorial on how to set this up can be found [here](/tutorials/ssr).
::: info Please Note
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.
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.
Reason for this is that the Firebase JS SDK is a client-side library that is not built for authenticating multiple users. See the [serverlogin](/service-options/auth#serverlogin) option for an experimental approach to solve this issue.
:::
### ignorePaths
The service worker session automatically ignores external resources, static files and HMR calls.
If you need to ignore additional routes, define them here.
::: code-group
```js [nuxt.config.js]
auth: {
ssr: {
ignorePaths: [
'/admin', // path is ignored if url.pathname.startsWith('/admin')
/^api/, // path is ignored if url.pathname without the leading slash (/) matches the RegExp
]
}
}
```
:::
### credential
Enables Firebase admin authorization.
::: code-group
```js [nuxt.config.js]
auth: {
ssr: {
// retrieved credentials from GOOGLE_APPLICATION_CREDENTIALS env variable
credential: true
// provide the path to the service account file
// CAREFUL - don't deploy to publicly accessible location!
credential: '/absolute/path/to/serviceAccount.json'
// nuxt aliases are supported
credential: '~/assets/serviceAccount.json'
}
}
```
:::
If you want additional information on the user the module can inject a full [`admin.auth.UserRecord`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserRecord) into the `ctx.res.locals.user` property.
The `allClaims` property is set in addition to the default user record properties.
To enable this you can authorize the firebase admin by [generating a service account key](https://firebase.google.com/docs/admin/setup#initialize-sdk) and link to it with this configuration.
::: danger
**NEVER deploy your service account key to a publicly accessible location**
The service account key file is highly sensitive as it grants full access to your firebase project.
In production always prefer providing the path to the key file through the `GOOGLE_APPLICATION_CREDENTIALS` environment variable (`auth.ssr.credential = true`) and store the key file in a location which is not exposed by your webserver.
:::
### serverLogin
Enables server side Firebase client SDK login.
::: code-group
```js [nuxt.config.js]
auth: {
ssr: {
// Set 'credential' as described above.
serverLogin: true
// or
serverLogin: {
// Takes a duration in milliseconds
sessionLifetime: 0 // default (session is kept only for the duration of the request)
// Takes a duration in milliseconds
loginDelay: 50 // default (20 queries per second = minimum recommended delay)
}
}
}
```
:::
Once you have properly setup the admin sdk via the [credential option](#credential) you can enable server side login to use firebase services on the server, e.g. to perform store hydration on page load.
Simply set `auth.ssr.serverLogin = true`.
The module creates a separate firebase app/session for every authenticated user to avoid authorization context leakage.
You can configure the session lifetime with `auth.ssr.serverLogin.sessionLifetime`
::: warning Be aware
**Programmatic server implementation**
If you are using an external server implementation to start nuxt programmatically:
- The `@nuxtjs/firebase` module has to be included in your server package (`yarn add @nuxtjs/firebase`).
- Make sure to initialize the nuxt build outside of the server request callback for session management to work properly:
```js
import express from 'express'
import {Nuxt} from 'nuxt'
const server = express()
// do this outside of the server callback so the nuxt build is kept in memory
const nuxt = new Nuxt({
dev: false,
buildDir: '.nuxt',
})
server.use(async (req, res, next) => {
// this will resolve immediately after the first render
await nuxt.ready()
nuxt.render(req, res, next)
})
```
:::
::: danger
**Do not use this feature for high traffic sites**
This module provides this feature to facilitate data hydration in SSR calls.
However, the client SDK is not intended for use on a server.
Authentication is rate limited by IP for security reasons by Firebase. The base limit is 20 QPS / IP (as of March 2020) and a couple dozen logins per user per 10 minutes, but it’s subject to change as needed, without notice by Firebase.
Try to reduce the need for SSR by providing pre-rendered pages ([`nuxt generate`](https://nuxtjs.org/guide#static-generated-pre-rendering-)) through static hosting and only fall back on SSR for authenticated and dynamic routes.
If you run into rate limiting issues try adjusting the `serverLogin.loginDelay` configuration.
:::
::: danger
**Do not use the Client SDK in API Operations**
If you have an API which is served over Nuxt SSR:
1. Please ensure it does not use `firebase` client sdk functionality (e.g. `auth`, `firestore`, `storage`, ...).
Instead use the corresponding functionality of a fully authenticated `firebase-admin` instance.
2. Add the API base path (e.g. `'/api/'`) to the [`auth.ssr.ignorePaths`](#ignorepaths) configuration.
::: warning Be aware
## emulatorPort
- Type: `Integer`
- Default: `null`
Sets up `useEmulator("http://localhost:EMULATOR_PORT")` to point to an Authentication emulator running locally instead of the production one.
More information in the official Firebase [Guide to connect your app to the Authentication Emulator](https://firebase.google.com/docs/emulator-suite/connect_auth).
::: info
To not use the emulator in production you can do the following:
```js
emulatorPort: process.env.NODE_ENV === 'development' ? 9099 : undefined
```
:::
## emulatorHost
- Type: `String`
- Default: `http://localhost`,
Changes the host used for the Authentication emulator. Only applies if the emulatorPort is set.
## disableEmulatorWarnings
- Type: `Boolean`
- Default: false
Disables the auth emulators warning messages, see [here](https://github.com/firebase/firebase-tools/issues/2773).
## Example of SignIn with a provider Google
```js
try {
const provider = new this.$fireModule.auth.GoogleAuthProvider()
const user = await this.$fire.auth.signInWithPopup(provider)
console.log(user) // here you can do what you want with the user data
this.$router.push('/') // that return from firebase
} catch (e) {
// handle the error
}
```
The same code with work with facebook as well just change it to `FacebookAuthProvider`
Full example is [here](https://dev.to/rodrigopv/nuxtjs-firebase-social-auth-3afe).
================================================
FILE: packages/docs/docs/service-options/database.md
================================================
# database
Initializes **Firebase Realtime Database** and makes it available via `$fire.database` and `$fireModule.database`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
database: {
emulatorPort: 9000,
emulatorHost: 'localhost',
}
```
:::
## emulatorPort
- Type: `Integer`
- Default: `null`
Sets up `useEmulator("localhost", EMULATOR_PORT)` to point to a RealtimeDatabase emulator running locally.
More information in the official Firebase [Emulator Docs](https://firebase.google.com/docs/emulator-suite/connect_rtdb).
::: info
To not use the emulator in production you can do the following:
```js
emulatorPort: process.env.NODE_ENV === 'development' ? 9000 : undefined
```
:::
## emulatorHost
- Type: `String`
- Default: `localhost`,
Changes the host used for the emulator. Only applies if the emulatorPort is set.
================================================
FILE: packages/docs/docs/service-options/firestore.md
================================================
# firestore
Initializes **Firebase Firestore** and makes it available via `$fire.firestore` and `$fireModule.firestore`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
firestore: {
memoryOnly: false, // default
chunkName: process.env.NODE_ENV !== 'production' ? 'firebase-auth' : '[id]', // default
enablePersistence: true,
emulatorPort: 8080,
emulatorHost: 'localhost',
settings: {
// Firestore Settings - currently only works in SPA mode
}
}
```
:::
## memoryOnly
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).
- Type: `Boolean` or `Object`
- Default: `false`
## enablePersistence
Enables persistence in web apps.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
firestore: {
// ...
enablePersistence: true
}
// or
firestore: {
// ...
enablePersistence: {
/**
* Whether to synchronize the in-memory state of multiple tabs. Setting this
* to 'true' in all open tabs enables shared access to local persistence,
* shared execution of queries and latency-compensated local document updates
* across all connected instances.
*
* To enable this mode, `synchronizeTabs:true` needs to be set globally in all
* active tabs. If omitted or set to 'false', `enablePersistence()` will fail
* in all but the first tab.
*/
synchronizeTabs: true
}
}
```
:::
More information [here](https://firebase.google.com/docs/firestore/manage-data/enable-offline).
## emulatorPort
- Type: `Integer`
- Default: `null`
Sets up `useEmulator("localhost", EMULATOR_PORT)` to point to a Firestore emulator running locally.
More information in the official Firebase [Emulator Docs](https://firebase.google.com/docs/emulator-suite/connect_firestore).
::: info
To not use the emulator in production you can do the following:
```js
emulatorPort: process.env.NODE_ENV === 'development' ? 8080 : undefined
```
:::
## emulatorHost
- Type: `String`
- Default: `localhost`,
Changes the host used for the emulator. Only applies if the emulatorPort is set.
## settings
Adds settings to your Firebase initialization, e.g. `host` or `ssl`.
See more [here](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Settings).
::: warning Important
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:
::: code-group
```js [nuxt.config.js]
// Add this to your nuxt.config.js
render: {
bundleRenderer: {
runInNewContext: false
}
},
```
:::
:::
================================================
FILE: packages/docs/docs/service-options/functions.md
================================================
# functions
Initializes **Firebase Functions** and makes it available via `$fire.functions` and `$fireModule.functions`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
functions: {
location: 'us-central1',
emulatorPort: 12345,
emulatorHost: 'http://10.10.10.3',
}
```
:::
## location
- Type: `String`
- Default: `us-central1`
More information [here](https://firebase.google.com/docs/functions/locations).
## emulatorPort
- Type: `Integer`
- Default: `null`
Sets up `useFunctionsEmulator("http://localhost:EMULATOR_PORT")` to point to a Cloud Functions emulator running locally instead of the production one.
More information in the official Firebase [API Docs]() and [Functions Docs](https://firebase.google.com/docs/functions/local-emulator).
## emulatorHost
- Type: `String`
- Default: `http://localhost`,
Changes the host used for the Cloud Functions emulator. Only applies if the emulatorPort is set.
================================================
FILE: packages/docs/docs/service-options/messaging.md
================================================
# messaging
::: danger Client-only
Make sure to wrap universal code in `if (process.client) {}`.
:::
Initializes **Firebase Messaging** and makes it available via `$fire.messaging` and `$fireModule.messaging`.
Message payload is expected as defined by Firebase [here](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushConfig).
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
messaging: {
createServiceWorker: false,
actions: [
{
action: 'randomName',
url: 'randomUrl'
}
],
fcmPublicVapidKey: '' // OPTIONAL : Sets vapid key for FCM after initialization
}
```
:::
## createServiceWorker
- Type: `Boolean` or `Object`
- Default: `false`
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.
## actions
> Only works if `createServiceWorker === true`
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.
```js
{
action: 'randomName',
url: 'randomUrl'
}
```
Make sure to define the action in your payload like so:
```js
const message = {
// ...
webpush: {
notification: {
actions: [
{
action: 'randomName',
title: 'Go to URL',
},
],
},
},
// ...
}
await messaging.send(message)
```
## inject
> Only works if `createServiceWorker === true`
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.
#### Simple example:
::: code-group
```js [nuxt.config.js]
...
inject: 'console.log("This is the end of the service worker.")',
...
```
:::
#### Advanced example:
::: code-group
```js [nuxt.config.js]
const fs = require('fs')
...
inject: fs.readFileSync('./javascriptFileWithCodeToBeInjected.js', 'utf8'),
...
```
:::
## fcmPublicVapidKey
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).
================================================
FILE: packages/docs/docs/service-options/performance.md
================================================
# performance
::: danger Client-only
Make sure to wrap universal code in `if (process.client) {}`.
:::
Initializes **Firebase Performance** and makes it available via `$fire.performance` and `$fireModule.performance`.
- Type: `Boolean`
- Default: `false`
::: code-group
```js [nuxt.config.js]
performance: true
```
:::
Currently, there are no advanced options available.
================================================
FILE: packages/docs/docs/service-options/remote-config.md
================================================
# remoteConfig
::: danger Client-only
Make sure to wrap universal code in `if (process.client) {}`.
:::
Initializes **Firebase Remote Config** and makes it available via `$fire.remoteConfig` and `$fireModule.remoteConfig`.
- Type: `Boolean` or `Object`
- Default: `false`
::: code-group
```js [nuxt.config.js]
remoteConfig: {
settings: {
fetchTimeoutMillis: 60000, // default
minimumFetchIntervalMillis: 43200000, // default
},
defaultConfig: {
'welcome_message': 'Welcome'
}
}
```
:::
================================================
FILE: packages/docs/docs/service-options/storage.md
================================================
# storage
Initializes **Firebase Storage** and makes it available via `$fire.storage` and `$fireModule.storage`.
- Type: `Boolean`
- Default: `false`
::: code-group
```js [nuxt.config.js]
storage: {
emulatorPort: 9199,
emulatorHost: 'localhost',
}
```
:::
## emulatorPort
- Type: `Integer`
- Default: `null`
Sets up `useEmulator("localhost:EMULATOR_PORT")` to point to an Storage emulator running locally instead of the production one.
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).
::: info
To not use the emulator in production you can do the following:
```js
emulatorPort: process.env.NODE_ENV === 'development' ? 9199 : undefined
```
:::
## emulatorHost
- Type: `String`
- Default: `localhost`,
Changes the host used for the Storage emulator. Only applies if the emulatorPort is set.
================================================
FILE: packages/docs/docs/tutorials/ssr.md
================================================
# Firebase Auth with SSR
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.
::: info Please Note:
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.
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._
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.
:::
## Step 0 - Install Dependencies
Install `firebase-admin` and `@nuxtjs/pwa`:
::: code-group
```bash [yarn]
yarn add firebase-admin @nuxtjs/pwa
```
```bash [npm]
npm install firebase-admin @nuxtjs/pwa
```
:::
## Step 1 - Enable SSR functionality and configure workbox to include the auth service worker
Use the [auth.ssr option](/service-options/auth#ssr).
In `nuxt.config.js`:
::: code-group
```js [nuxt.config.js]
module.exports = {
// ...
modules: [
// ...
'@nuxtjs/pwa',
'@nuxtjs/firebase'
],
firebase: {
// ...
services: {
auth: {
ssr: true
}
// ...
}
},
pwa: {
// disable the modules you don't need
meta: false,
icon: false,
// if you omit a module key form configuration sensible defaults will be applied
// manifest: false,
workbox: {
importScripts: [
// ...
'/firebase-auth-sw.js'
],
// by default the workbox module will not install the service worker in dev environment to avoid conflicts with HMR
// only set this true for testing and remember to always clear your browser cache in development
dev: process.env.NODE_ENV === 'development',
}
}
},
```
:::
## Step 2 - Setup Mutations and/or Actions to handle User authentication
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).
See [Step 3](#step-3---retrieve-the-server-user) to verify if required properties are present.
Example action:
```js
async onAuthStateChangedAction({ commit, dispatch }, { authUser, claims }) {
if (!authUser) {
await dispatch('cleanupAction')
return
}
// you can request additional fields if they are optional (e.g. photoURL)
const { uid, email, emailVerified, displayName, photoURL } = authUser
commit('SET_USER', {
uid,
email,
emailVerified,
displayName,
photoURL, // results in photoURL being undefined for server auth
// use custom claims to control access (see https://firebase.google.com/docs/auth/admin/custom-claims)
isAdmin: claims.custom_claim
})
}
```
Example mutation:
```js
ON_AUTH_STATE_CHANGED_MUTATION(state, { authUser, claims }) {
// you can request additional fields if they are optional (e.g. photoURL)
const { uid, email, emailVerified, displayName, photoURL } = authUser
state.authUser = {
uid,
displayName,
email,
emailVerified,
photoURL: photoURL || null, // results in photoURL being null for server auth
// use custom claims to control access (see https://firebase.google.com/docs/auth/admin/custom-claims)
isAdmin: claims.custom_claim
}
}
```
## Step 3 - Retrieve the server user
In the nuxtServerInit action in your vuex store you can now access the authUser under the `res.locals.user` property as shown below.
::: warning Be aware
The server user object is not a full `firebase.User`, since it is reproduced from the user claims, it provides only the following properties:
- `uid`: The users uid
- `email`: The users email
- `emailVerified`: If the email was verified
- `displayName`: The users display name
- `allClaims`: All claims from the [admin.auth.DecodedIdToken](https://firebase.google.com/docs/reference/admin/node/admin.auth.DecodedIdToken)
- `idToken`: The current idToken
:::
```js
// Store action called nuxtServerInit:
async nuxtServerInit({ dispatch, commit }, { res }) {
if (res && res.locals && res.locals.user) {
const { allClaims: claims, idToken: token, ...authUser } = res.locals.user
await dispatch('onAuthStateChangedAction', {
authUser,
claims,
token
})
// or
commit('ON_AUTH_STATE_CHANGED_MUTATION', { authUser, claims, token })
}
}
```
That's it. You receive a server-verified authUser object and can do with it whatever you want in nuxtServerInit.
## Step 4 - (Experimental) Authorize the admin SDK
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.
## Step 5 - (Experimental) Enable server side client SDK login
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).
================================================
FILE: packages/docs/docs/tutorials/typescript.md
================================================
# Usage with Typescript
The module comes with types by providing a declaration file (`index.d.ts`) within the npm package.
All you need to do is to include "@nuxtjs/firebase" in your tsconfig.json types like so:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
"node",
"@nuxt/types",
// ...
"@nuxtjs/firebase"
]
}
}
```
Don't forget to restart your IDE (e.g. VSCODE) after adding the types.
[nuxt-fire-demo](https://github.com/lupas/nuxt-fire-demo) shows working examples of nuxt-fire with Typescript.
================================================
FILE: packages/docs/docs/tutorials/vuexfire.md
================================================
# Usage with vuexfire
Vuexfire and this module work very well together.
This [example](https://github.com/lupas/nuxt-fire-vuexfire-example) shows how to use these two packages together, working with SSR.
================================================
FILE: packages/docs/package.json
================================================
{
"name": "@nuxtjs/firebase-docs",
"version": "8.2.2",
"description": "",
"main": "index.js",
"directories": {
"doc": "docs"
},
"scripts": {
"dev": "vitepress dev docs",
"build": "vitepress build docs"
},
"author": "",
"license": "ISC",
"devDependencies": {
"vitepress": "^1.0.0-alpha.51",
"vue": "^3.2.47"
},
"dependencies": {
"focus-visible": "^5.2.0",
"sass": "^1.58.3"
}
}
================================================
FILE: packages/firebase-module/.editorconfig
================================================
# editorconfig.org
root = true
[*]
indent_size = 2
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: packages/firebase-module/.eslintignore
================================================
# Common
node_modules
dist
.nuxt
coverage
# Plugin
lib/plugins/*.js
lib/plugins/services/*.js
lib/serverMiddleware/*.js
lib/sw-templates/*.js
types/index.d.ts
================================================
FILE: packages/firebase-module/.eslintrc.js
================================================
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
extends: [
'prettier',
'prettier/vue',
'plugin:prettier/recommended',
'@nuxtjs'
]
}
================================================
FILE: packages/firebase-module/.gitignore
================================================
node_modules
*.iml
.idea
*.log*
.nuxt*
.vscode
.DS_Store
coverage
dist
yarn.lock
!docs/yarn.lock
sw.*
.husky
================================================
FILE: packages/firebase-module/.prettierrc.js
================================================
module.exports = {
singleQuote: true,
arrowParens: 'always',
semi: false,
}
================================================
FILE: packages/firebase-module/CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [8.2.2](https://github.com/nuxt-community/firebase-module/compare/v8.2.0...v8.2.2) (2022-01-24)
## [8.2.0](https://github.com/nuxt-community/firebase-module/compare/v8.1.1...v8.2.0) (2022-01-11)
### Features
* **demo:** added appcheck to demop ([f62bfc1](https://github.com/nuxt-community/firebase-module/commit/f62bfc19291fa35692f8dbb03976515876ad096a))
### Bug Fixes
* add lazy load to app check and fix collection is not a function (by eljias) ([6c0c1d1](https://github.com/nuxt-community/firebase-module/commit/6c0c1d11bf480bae0601db236f809a5bdedfd7e3))
### [8.1.1](https://github.com/nuxt-community/firebase-module/compare/v8.1.0...v8.1.1) (2021-12-02)
## [8.1.0](https://github.com/nuxt-community/firebase-module/compare/v8.0.0...v8.1.0) (2021-11-30)
### Features
- updated readme ([93ca96b](https://github.com/nuxt-community/firebase-module/commit/93ca96bd59356b108647e216192f85dbcf74629e))
### Bug Fixes
- fixed import error in terminateDatabasesInGenerateHooks ([326af38](https://github.com/nuxt-community/firebase-module/commit/326af3863334a3ae62fb510af19e3cff8fa2bf84))
## [8.0.0](https://github.com/nuxt-community/firebase-module/compare/v8.0.1...v8.0.0) (2021-10-30)
### [7.6.1](https://github.com/nuxt-community/firebase-module/compare/v7.6.0...v7.6.1) (2021-06-11)
### Features
- add storage emulators ([348900d](https://github.com/nuxt-community/firebase-module/commit/348900d4fc86da1ff3166fe20b4c902e4f13df8d))
- **docs:** Updated to use docus ([e629931](https://github.com/nuxt-community/firebase-module/commit/e629931cef9bad76ff2a4427c67df720285f9a38))
### Bug Fixes
- add type for $fireAuthStore ([bacdae9](https://github.com/nuxt-community/firebase-module/commit/bacdae907201a20432603983541f0327d9223702))
- **docs:** Minor fixes & color update ([2631eb6](https://github.com/nuxt-community/firebase-module/commit/2631eb6e4104f2fc8a9a8aec8cb91972026f2a55))
- **docs:** Nuxt down to 2.14.11 ([6978c43](https://github.com/nuxt-community/firebase-module/commit/6978c434814c7567fb0dcd89fd814845d6f1a941))
- **docs:** Use bebel preset-env 7.12.7 ([5b48d8f](https://github.com/nuxt-community/firebase-module/commit/5b48d8f57972668b6f0be11ebecb9570d752f602))
- **docs:** use nuxt v 2.14.12 for docs ([549e35e](https://github.com/nuxt-community/firebase-module/commit/549e35e44b6d089f6a3d3faa175a0fc3d999366d))
## [7.5.0](https://github.com/nuxt-community/firebase-module/compare/v7.4.1...v7.5.0) (2021-02-18)
### Features
- **terminatedatabasesaftergenerate:** added 'terminateDatabasesAfterGenerate' config ([4df37a7](https://github.com/nuxt-community/firebase-module/commit/4df37a7add07caa711d556fc00c331ffe66e164e)), closes [#451](https://github.com/nuxt-community/firebase-module/issues/451)
### Bug Fixes
- **config:** made "databaseUrl" config value optional ([fbb4a7d](https://github.com/nuxt-community/firebase-module/commit/fbb4a7d92be913a81905a36405ee6cc80bdf2a67)), closes [#458](https://github.com/nuxt-community/firebase-module/issues/458)
- **firestore:** call useEmulator after enablePersistence to fix "already started" issue ([bc16b45](https://github.com/nuxt-community/firebase-module/commit/bc16b45a712e3c6400f7c9f8fa1af4233679b46c)), closes [#451](https://github.com/nuxt-community/firebase-module/issues/451)
### [7.4.1](https://github.com/nuxt-community/firebase-module/compare/v7.4.0...v7.4.1) (2021-01-20)
### Bug Fixes
- **auth:** fixes build error appearing when auth.initialize is not set ([71c3fb0](https://github.com/nuxt-community/firebase-module/commit/71c3fb024fe0795cfa67f4230dd1634acb785ac1)), closes [#446](https://github.com/nuxt-community/firebase-module/issues/446)
## [7.4.0](https://github.com/nuxt-community/firebase-module/compare/v7.3.3...v7.4.0) (2021-01-19)
### Features
- **auth:** added onIdTokenChanged() handlers to auth.initialize ([fcf0846](https://github.com/nuxt-community/firebase-module/commit/fcf08463621b36e597dc31d9c542c46632a5beb9)), closes [#411](https://github.com/nuxt-community/firebase-module/issues/411)
### [7.3.3](https://github.com/nuxt-community/firebase-module/compare/v7.3.2...v7.3.3) (2021-01-18)
### Bug Fixes
- **forceinject:** fixed issue in lazy-mode that did not allow to initialize services in nuxt plugins ([c5b5cb3](https://github.com/nuxt-community/firebase-module/commit/c5b5cb34148bda432d1320567cf5a9118bb394b0)), closes [#366](https://github.com/nuxt-community/firebase-module/issues/366)
### [7.3.2](https://github.com/nuxt-community/firebase-module/compare/v7.3.1...v7.3.2) (2021-01-17)
### Bug Fixes
- **forceinject:** fixed forceInject failing when ...ready() is called in a plugin in lazy mode ([c15222f](https://github.com/nuxt-community/firebase-module/commit/c15222fb3374aa7abadac9ed59c7fd4935d9d19a)), closes [#366](https://github.com/nuxt-community/firebase-module/issues/366)
### [7.3.1](https://github.com/nuxt-community/firebase-module/compare/v7.3.0...v7.3.1) (2021-01-17)
### Bug Fixes
- **lazy:** fixed fireModule not being injected if ready() functions are only called in V-components ([3f37365](https://github.com/nuxt-community/firebase-module/commit/3f37365dfa5091244569710f3865c00018468e71)), closes [#366](https://github.com/nuxt-community/firebase-module/issues/366)
## [7.3.0](https://github.com/nuxt-community/firebase-module/compare/v7.2.3...v7.3.0) (2020-12-28)
### Features
- **messaging sw:** allow users to inject a string into the messaging sw ([7e6174f](https://github.com/nuxt-community/firebase-module/commit/7e6174fc50aebc88f48228630580b9ede88fdcb1))
### [7.2.3](https://github.com/nuxt-community/firebase-module/compare/v7.2.2...v7.2.3) (2020-12-28)
### [7.2.2](https://github.com/nuxt-community/firebase-module/compare/v7.2.1...v7.2.2) (2020-12-23)
### Bug Fixes
- **auth:** fixed issue where Firestore did not work in SSR because of Auth not being initialized ([9482f16](https://github.com/nuxt-community/firebase-module/commit/9482f1650c31050265febd558d79d345791100d5))
- **firestore-emulator:** fixed issue that caused useEmulator to be triggered multiple times in SSR ([ebac666](https://github.com/nuxt-community/firebase-module/commit/ebac6669524100fe303e4ba30a69b332f241fb85)), closes [#390](https://github.com/nuxt-community/firebase-module/issues/390)
- **messaging:** fixed error with onFirebaseHosting in sw trying to load scripts from /\_\_/ on lh ([383b9cd](https://github.com/nuxt-community/firebase-module/commit/383b9cdeb10c26233c4f8e73f0cedda31d7486d6)), closes [#379](https://github.com/nuxt-community/firebase-module/issues/379)
### [7.2.1](https://github.com/nuxt-community/firebase-module/compare/v7.2.0...v7.2.1) (2020-12-22)
### Bug Fixes
~~\* **auth**: fixed 'auth' being initialized on server-side, which lead to a memory leak in SSR mode (daa9b9e), closes #399~~
⚠️⚠️⚠️ Release had a bug, please upgrade to v7.2.2. ⚠️⚠️
## [7.2.0](https://github.com/nuxt-community/firebase-module/compare/v7.1.2...v7.2.0) (2020-12-22)
### Features
- **auth:** added disableEmulatorWarnings option ([1de60b9](https://github.com/nuxt-community/firebase-module/commit/1de60b9c3cd4ea22df28beaf3a3646a8315fb5e6)), closes [#415](https://github.com/nuxt-community/firebase-module/issues/415)
### [7.1.2](https://github.com/nuxt-community/firebase-module/compare/v7.1.1...v7.1.2) (2020-12-08)
### Bug Fixes
- **types:** fixed fcmPublicVapidKey not correctly placed in .d.ts ([0c5c4a7](https://github.com/nuxt-community/firebase-module/commit/0c5c4a7077009294e60797dc3d4d0923bb907cf3))
### [7.1.1](https://github.com/nuxt-community/firebase-module/compare/v7.1.0...v7.1.1) (2020-11-14)
### Bug Fixes
- **auth-emulator-ssr:** call useEmulator in auth ssr service-worker, if emulator is in use ([004e696](https://github.com/nuxt-community/firebase-module/commit/004e696e90c0be06573a9038439fb910efaee84f))
## [7.0.0](https://github.com/nuxt-community/firebase-module/compare/v6.1.1...v7.0.0) (2020-10-31)
## [7.1.0](https://github.com/nuxt-community/firebase-module/compare/v7.0.2...v7.1.0) (2020-11-05)
### Features
- **emulators:** added options to connect to emulators for Firestore & RealtimeDB ([c724e1c](https://github.com/nuxt-community/firebase-module/commit/c724e1c3245620a62f54529b3929ea79f75c938f))
### [7.0.2](https://github.com/nuxt-community/firebase-module/compare/v7.0.1...v7.0.2) (2020-11-05)
### Bug Fixes
- **messaging:** fixed "actions" not properly passed to messaging-sw ([53d48f7](https://github.com/nuxt-community/firebase-module/commit/53d48f7db7c2b2af5bbf9870a19e01804053f139))
- found action is always first action ([31d0586](https://github.com/nuxt-community/firebase-module/commit/31d058611786b514e085f48d71f44120ef83559c))
## [7.0.1](https://github.com/nuxt-community/firebase-module/compare/v7.0.0...v7.0.1) (2020-11-05)
### Bug Fixes
- **types:** added missing types (emulatorHost etc.) ([2a76c6b](https://github.com/nuxt-community/firebase-module/commit/eec46c5ea92561076c4d6013750c0b708dbd981f))
## [7.0.0](https://github.com/nuxt-community/firebase-module/compare/v6.1.1...v7.0.0) (2020-10-31)
### Features
- **analytics.issupported:** added check whether browser supports Firebase Analytics before init ([52ec6ef](https://github.com/nuxt-community/firebase-module/commit/52ec6efa6c1cfbd0ddaac4a73676f948da4d807e))
- **auth:** added initialize.subscribeManually and removed "helper" function ([91ad279](https://github.com/nuxt-community/firebase-module/commit/91ad2792f142f7fcf22f0775242dc7330e485230))
- **firebase-v8:** updated code to work with Firebase v8+ ([4ae48b5](https://github.com/nuxt-community/firebase-module/commit/4ae48b51bc35f007c89bcc46febeded30f288893))
- **functions:** added emulatorHost option to Firebase Functions ([08db302](https://github.com/nuxt-community/firebase-module/commit/08db302013fdac1213e783f6cd860ca62cc15cbe))
- add support for lazy service loading ([4e96d28](https://github.com/nuxt-community/firebase-module/commit/4e96d28a43014c85a01a0c4c953f756bd2ec0812))
### Bug Fixes
- **analytics:** Fixed service naming issue ([addd317](https://github.com/nuxt-community/firebase-module/commit/addd317c7abf4ea9d70bd17943411f11cdaefac4))
- **auth:** Fixed initialize ([c4b203d](https://github.com/nuxt-community/firebase-module/commit/c4b203d5a6d1aea521e70097a47c1b104b02c044))
- **auth-credential:** fixed auth-credential import (require) ([faeed48](https://github.com/nuxt-community/firebase-module/commit/faeed4803908d7a262ac73759b1608ad91a6ef95))
- **auth-serverlogin:** fixed serverLogin issue (ctx.res missing) ([edd1a75](https://github.com/nuxt-community/firebase-module/commit/edd1a755401fcd25886644554325dcaf6778e89d))
- **fireObj:** fireObj was not injected in non-lazy + non-legacy mode ([dc66991](https://github.com/nuxt-community/firebase-module/commit/dc6699171c1e35552f7a02f093adb4ac329b9f46))
- **initauth:** async import of initAuth within auth plugin ([36eb8f4](https://github.com/nuxt-community/firebase-module/commit/36eb8f490797f9cc7a03216f18806c1a93cd8700))
- **initAuth:** Fixed mmissing options in initAuth & small lazy mode fix ([8e54384](https://github.com/nuxt-community/firebase-module/commit/8e54384dd1109439a0c33f358b1c30a009a27002))
- **legacymodeinfo:** fixed error 'Cannot use 'in' operator to search for 'legacyMode' in undefined ' ([0684e64](https://github.com/nuxt-community/firebase-module/commit/0684e64bb708a2b4fdee23b2c3a6d8f73f117a68))
- **loggerinfo:** added module name to legyMode info log because it's not clear on multi-line log ([cb85c29](https://github.com/nuxt-community/firebase-module/commit/cb85c291dec1508068b34b5d363bde601cdd1318))
- **naming:** Improved readability by consistanly naming services constants ([0d62e76](https://github.com/nuxt-community/firebase-module/commit/0d62e7618df69bb63fca01b7f3a3a214ed32d280))
- **netlify:** updated netlify.toml ([26f5aa9](https://github.com/nuxt-community/firebase-module/commit/26f5aa9aaa0ad1ff4dc6903178547acc1904097c))
- **packageejson:** missing comma ([a6669fc](https://github.com/nuxt-community/firebase-module/commit/a6669fc872751077b3b089648e76276ac20f1512))
- **remoteconfig:** fixed 'defaultConfig' being child of 'settings' instead of main obj ([7e1020c](https://github.com/nuxt-community/firebase-module/commit/7e1020c3c024c2b938f8a339a38d700036f46605))
- **static:** fixed static=true also dynamically importing the modules ([cf61833](https://github.com/nuxt-community/firebase-module/commit/cf61833da715799cf88914d45b8eed62993d6933))
- **ts:** Added ready() to $fire and added missing 'storage' ([bb78d3a](https://github.com/nuxt-community/firebase-module/commit/bb78d3a6e3348430201a0c8cf5220b981e6603db))
- **ts:** Fixed $fire.database ([6bd9df9](https://github.com/nuxt-community/firebase-module/commit/6bd9df9560436d3db59afaa8a88391a779024520))
- make initAuth work again ([db8a467](https://github.com/nuxt-community/firebase-module/commit/db8a467db2e865c4ea0c570cce276bf635400368))
- review comments ([f5265ae](https://github.com/nuxt-community/firebase-module/commit/f5265aecf210978ce333d6bd7621676a4ad12719))
- use existing injection name ([a6971ac](https://github.com/nuxt-community/firebase-module/commit/a6971acc0d440b3553975e40a09d819d0d8c1077))
- use service mapping ([33489a1](https://github.com/nuxt-community/firebase-module/commit/33489a17a1f35d95680f79ac98d31a16c1412df5))
- use service mapping ([bd16287](https://github.com/nuxt-community/firebase-module/commit/bd1628735f333b448562b9eda5cc5a9d3e9d9e06))
### [6.1.1](https://github.com/nuxt-community/firebase-module/compare/v6.1.0...v6.1.1) (2020-07-25)
### Bug Fixes
- **types:** improve typing of locals ([407eb2c](https://github.com/nuxt-community/firebase-module/commit/407eb2cd492adac282fd869d32eb9a2095e6060d))
## [6.1.0](https://github.com/nuxt-community/firebase-module/compare/v6.0.1...v6.1.0) (2020-06-29)
### Features
- **analytics:** added collectionEnabled option to analytics ([5da8a19](https://github.com/nuxt-community/firebase-module/commit/5da8a19e1b6b70f78c5d9701ecd71d767a4a4627))
### Bug Fixes
- typo in README ([c0158c9](https://github.com/nuxt-community/firebase-module/commit/c0158c90abeeceb2e39aa7c5322a365988de0623))
### [6.0.1](https://github.com/nuxt-community/firebase-module/compare/v6.0.0...v6.0.1) (2020-06-08)
### Bug Fixes
- **bug:** fixed "Cannot read property 'memoryOnly' of undefined" bug ([8f69cc3](https://github.com/nuxt-community/firebase-module/commit/8f69cc3681fbb9eab51817bcdcb5d9bc8240178e)), closes [#224](https://github.com/nuxt-community/firebase-module/issues/224)
## [6.0.0](https://github.com/nuxt-community/firebase-module/compare/v5.2.0...v6.0.0) (2020-06-07)
### ⚠ BREAKING CHANGES
- **messaging:** Messaging expects payloads to be delivered according to the new HTTP v1 API.
### Features
- **auth:** add idToken to user's payload ([97d8055](https://github.com/nuxt-community/firebase-module/commit/97d805591cbc3073417f755e0ae9e6c0ed20bed3)), closes [#202](https://github.com/nuxt-community/firebase-module/issues/202)
- **firestore:** added memoryOnly option to firestore ([efde3fe](https://github.com/nuxt-community/firebase-module/commit/efde3fedb448cc60661a3cf5f67e5d13b195d578)), closes [#135](https://github.com/nuxt-community/firebase-module/issues/135)
- **messaging:** implement notificationKey setting ([a985f02](https://github.com/nuxt-community/firebase-module/commit/a985f02e5e45b4c5c64bc4597bf9a41650f23bda))
- **messaging:** migrated to HTTP v1 API for messaging ([9c09a26](https://github.com/nuxt-community/firebase-module/commit/9c09a266472d90e9f9809312006476addddab64e))
### Bug Fixes
- **auth:** add 127.0.0.1 support ([c8b6114](https://github.com/nuxt-community/firebase-module/commit/c8b6114582cc1acc478b886bf5f05c5d05209fed)), closes [#203](https://github.com/nuxt-community/firebase-module/issues/203)
- **messaging:** only pass notificationKey to messaging sw ([5958b25](https://github.com/nuxt-community/firebase-module/commit/5958b251dcffeb5002408f4e275ad41886224b1c))
- **types:** specify preliminary types ([d03799c](https://github.com/nuxt-community/firebase-module/commit/d03799c87f23352bf9404a3abbafad98267fc43d))
## [5.2.0](https://github.com/nuxt-community/firebase-module/compare/v5.0.7...v5.2.0) (2020-05-01)
### Features
- **auth:** implement full ssr support ([17c0968](https://github.com/nuxt-community/firebase-module/commit/17c09686deb471da6faddcec16e140ab3013bdbd))
- **auth:** implement session manager ([5106f44](https://github.com/nuxt-community/firebase-module/commit/5106f448c3b15d14143f7e29f354f0fe47e929c9))
### Bug Fixes
- **helpers:** helper plugins are now exported as CommonJS instaed of ES6 ([806ecce](https://github.com/nuxt-community/firebase-module/commit/806ecce0a3b85478ef71a383e6a64c018c1b76e2))
- **main:** move messaging support check below import statement ([ca02c10](https://github.com/nuxt-community/firebase-module/commit/ca02c1061840f6bf652fe2ef9c36b7050dcfb0ad))
- **main:** remove references to removed session manager template ([9bf87a3](https://github.com/nuxt-community/firebase-module/commit/9bf87a32b73d07a9f64c58a1163d78df20e5c548))
- **manager:** use common js syntax for module imports/exports ([be6ac76](https://github.com/nuxt-community/firebase-module/commit/be6ac76ebd7d235c92b1195226e1000041a9fe19))
- **module:** remove unnecessary deps and simplify options resolution ([2501896](https://github.com/nuxt-community/firebase-module/commit/25018966f1ce52de8fdaa9685efe511b65ea6968))
- **ssr:** avoid using session manager for simple user injection ([8f26383](https://github.com/nuxt-community/firebase-module/commit/8f26383577c9fdc8edb1ccf9e6328fc0a4f1ec4c))
- **ssr:** check for req existence in ssr auth calls ([675aeed](https://github.com/nuxt-community/firebase-module/commit/675aeedecd70b1461d155b07689ca238ba5ed083))
- **templates:** improve type checks for more stability ([11d1f25](https://github.com/nuxt-community/firebase-module/commit/11d1f25ed3303aef24f0f7b159ec509de402d5ea))
- **types:** update credential option to allow ServiceAccount object ([427347d](https://github.com/nuxt-community/firebase-module/commit/427347d3a60f6bd07beb4f54ea7ed7b64e58e3cb))
- syntax on firebase module ([d3da4e9](https://github.com/nuxt-community/firebase-module/commit/d3da4e9506e9abce72ab345d22cbeada01ed91a9))
### [5.0.7](https://github.com/nuxt-community/firebase-module/compare/v5.0.6...v5.0.7) (2020-04-06)
### Bug Fixes
- **ssr-auth:** fixed a regression bug in ssr auth ([01411b3](https://github.com/nuxt-community/firebase-module/commit/01411b3fcfe3300065aaf1fff443eb83928ac755))
### [5.0.6](https://github.com/nuxt-community/firebase-module/compare/v5.0.5...v5.0.6) (2020-03-30)
### Bug Fixes
- **auth:** move ssrAuth plugin to the bottom of the module ([b7d5fe3](https://github.com/nuxt-community/firebase-module/commit/b7d5fe3bff89ff434c957411e7d1da438bd88a74))
### [5.0.5](https://github.com/nuxt-community/firebase-module/compare/v5.0.4...v5.0.5) (2020-03-30)
### [5.0.4](https://github.com/nuxt-community/firebase-module/compare/v5.0.3...v5.0.4) (2020-03-30)
### Bug Fixes
- **auth:** use plugin instead of middleware for ssr authentication ([9171b34](https://github.com/nuxt-community/firebase-module/commit/9171b34c75ba7b048a2270f00d41206f7daf2cb1))
### [5.0.3](https://github.com/nuxt-community/firebase-module/compare/v5.0.2...v5.0.3) (2020-03-18)
### [5.0.2](https://github.com/nuxt-community/firebase-module/compare/v5.0.1...v5.0.2) (2020-03-16)
### [5.0.1](https://github.com/nuxt-community/firebase-module/compare/v5.0.0...v5.0.1) (2020-03-15)
### Bug Fixes
- **module:** fix firebase-auth-sw only loaded when serverLogin === true ([35c434b](https://github.com/nuxt-community/firebase-module/commit/35c434b4a36cf69b72e4ee03828b04eb10217997))
## [5.0.0](https://github.com/nuxt-community/firebase-module/compare/v4.2.2...v5.0.0) (2020-03-15)
### ⚠ BREAKING CHANGES
- **auth:** moved sessionLifetime configuration key
- **auth:** moved configuration key
- **auth:** api changes
- **auth:** success mutation/action properties removed in lieu of sign in/out mutations/actions
- **auth:** set user object on res.locals.user as stipulated with @lupas
### Features
- **auth:** finialize server auth after tests ([2f829a4](https://github.com/nuxt-community/firebase-module/commit/2f829a4fd25d0999c14c9b5fb7b613f8a96c641a))
- **auth:** implement ignorePaths config for ssr functionality ([82a6c2d](https://github.com/nuxt-community/firebase-module/commit/82a6c2dcd8ebf895e9f9d8c71f6327642120d680)), closes [#87](https://github.com/nuxt-community/firebase-module/issues/87) [#117](https://github.com/nuxt-community/firebase-module/issues/117)
- **auth:** implement persistence preset for auth service ([b576f23](https://github.com/nuxt-community/firebase-module/commit/b576f23e3dffccb0874b4a6572e097d80a9d886a)), closes [#122](https://github.com/nuxt-community/firebase-module/issues/122)
- **auth:** implement server side authentication ([b545b74](https://github.com/nuxt-community/firebase-module/commit/b545b7495dfd4f696fd4972a7919c3a2784bd36c))
- **auth:** implement server side client sdk sessions ([3e07b01](https://github.com/nuxt-community/firebase-module/commit/3e07b0128410c594b0d3eaab3dddd25fd0cb314e))
- **auth:** implement sign in/out mutations and actions ([4b4800e](https://github.com/nuxt-community/firebase-module/commit/4b4800e2cc328f62952ebe062c4519b08d97a24b)), closes [#118](https://github.com/nuxt-community/firebase-module/issues/118)
- **auth:** simplify auth state changed handler ([02b13a2](https://github.com/nuxt-community/firebase-module/commit/02b13a244c2aa44bc23dcebe065cb900984d6c58))
### Bug Fixes
- **auth:** update createServerMiddleware function to be default export ([1d6eb46](https://github.com/nuxt-community/firebase-module/commit/1d6eb464c04d4189fcbdd72cba3dd4be12823d87))
- **auth:** update import statement to point to correct file ([2e299af](https://github.com/nuxt-community/firebase-module/commit/2e299afa81278dec40919b0b6d8ef215d71e89a4))
- **auth:** update variable names in render:routeDone ([a93ed39](https://github.com/nuxt-community/firebase-module/commit/a93ed39cc00b67e2b16da17a5a5b66bb0c9403c0))
- **auth:** use error logger on auth verification failure ([82e1a82](https://github.com/nuxt-community/firebase-module/commit/82e1a82763b8cb63fc32b17c0fb89dae39ab2c02))
- **types:** augment correct interface in http module ([7704581](https://github.com/nuxt-community/firebase-module/commit/7704581c9286b1f9f2d086c0893b91e6d6c2a925))
- **types:** update AuthServiceConfig interface ([577c880](https://github.com/nuxt-community/firebase-module/commit/577c880c5c397ae89df8fb7f95c12e9c5d220ab2))
- **types:** update server response augmentation ([0419d12](https://github.com/nuxt-community/firebase-module/commit/0419d129936689df2773edddfd89538814d0ac1e))
- **types:** update types to make ssr options optional ([99bfcde](https://github.com/nuxt-community/firebase-module/commit/99bfcdea9b906e0354f93f4e00c6e236be7a2068))
- **auth:** update documentation ([316894b](https://github.com/nuxt-community/firebase-module/commit/316894b47aafcc53e7f1497608db1f3bf935759a))
### [4.2.2](https://github.com/nuxt-community/firebase-module/compare/v4.2.1...v4.2.2) (2020-03-10)
### [4.2.1](https://github.com/nuxt-community/firebase-module/compare/v4.2.0...v4.2.1) (2020-03-10)
## [4.2.0](https://github.com/nuxt-community/firebase-module/compare/v4.1.0...v4.2.0) (2020-03-10)
### Features
- add option to add fireStore.settings() in nuxt.config.js ([21e32c1](https://github.com/nuxt-community/firebase-module/commit/21e32c1d57457370efc0a8e679033335ee656c09))
### Bug Fixes
- updated firebase version for firebase-auth-sw ([2d460a8](https://github.com/nuxt-community/firebase-module/commit/2d460a856fb234a4f9e005c85a7029baadccde01))
## [4.1.0](https://github.com/nuxt-community/firebase-module/compare/v4.0.0...v4.1.0) (2020-02-28)
### Features
- use consola instead of console ([1d209d8](https://github.com/nuxt-community/firebase-module/commit/1d209d8cb62c549f562036bf7e60690e15bcdbf6))
### Bug Fixes
- add types ([cd8ef74](https://github.com/nuxt-community/firebase-module/commit/cd8ef7470ff7c2844f58c540a4d302a76f3c2ad8))
- added links to license ([d3320e8](https://github.com/nuxt-community/firebase-module/commit/d3320e8ce57fa7bc11e6bfb4a246fc1f59771152))
- delete broken "related" link ([e845d40](https://github.com/nuxt-community/firebase-module/commit/e845d4001114f0d3fa1727dc01d72541cd08eec6))
- re-added unintentionally removed isEmpty() ([559b510](https://github.com/nuxt-community/firebase-module/commit/559b5101e4927a41fb0c105abdede7a443668eb3))
================================================
FILE: packages/firebase-module/babel.config.js
================================================
module.exports = {
env: {
test: {
plugins: ['@babel/plugin-syntax-dynamic-import', 'dynamic-import-node'],
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
},
},
}
================================================
FILE: packages/firebase-module/commitlint.config.js
================================================
module.exports = {
extends: [
'@commitlint/config-conventional'
]
}
================================================
FILE: packages/firebase-module/husky.config.js
================================================
module.exports = {
hooks: {
'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
'pre-commit': 'yarn lint',
'pre-push': 'yarn lint'
}
}
================================================
FILE: packages/firebase-module/jest.config.js
================================================
module.exports = {
collectCoverage: true,
collectCoverageFrom: [
'lib/**/*.js',
'!lib/plugins/**/*.js',
'!lib/serverMiddleware/*.js',
'!lib/sw-templates/*.js',
],
moduleFileExtensions: ['ts', 'js', 'json'],
testEnvironment: 'node',
transform: {
'^.+\\.js$': 'babel-jest',
},
transformIgnorePatterns: ['node_modules'],
}
================================================
FILE: packages/firebase-module/lib/module.js
================================================
const { resolve } = require('path')
const firebase = require('firebase/compat/app')
const logger = require('./utils/logger')
const templateUtils = require('./utils/template-utils')
const r = (...path) => resolve(__dirname, ...path)
module.exports = function (moduleOptions) {
const defaultOptions = {
injectModule: true,
}
const options = Object.assign(
defaultOptions,
this.options.firebase,
moduleOptions
)
const currentEnv = getCurrentEnv(options)
validateOptions(options)
options.config = getFinalUseConfigObject(options.config, currentEnv)
validateConfigKeys(options, currentEnv)
// Assign some defaults
options.services.app = Object.assign({ static: false }, options.services.app)
for (const service in options.services) {
if (options.services[service] === true) {
// If a service is enabled always set an object
// so we dont have to bother about this in the
// service templates
options.services[service] = {}
}
}
loadMessaging.call(this, options)
const loadAuthPlugin = loadAuth.call(this, options)
const enabledServices = []
for (const serviceMapping of Object.values(templateUtils.serviceMappings)) {
// Note: app is always set, see defaults above
const serviceOptions = options.services[serviceMapping.id]
if (!serviceOptions) {
continue
}
this.addTemplate({
src: r(`plugins/services/${serviceMapping.id}.js`),
fileName: `firebase/${serviceMapping.id === 'app' ? '' : 'service.'}${
serviceMapping.id
}.js`,
options: {
...options,
...templateUtils,
serviceMapping,
serviceOptions,
},
})
if (serviceMapping.id !== 'app') {
enabledServices.push(serviceMapping)
}
}
// Register main firebase-module plugin
this.addPlugin({
src: r('plugins/main.js'),
fileName: 'firebase/index.js',
options: {
...options,
...templateUtils,
enabledServices,
},
})
// add ssrAuth plugin last
// so res object is augmented for other plugins of this module
loadAuthPlugin()
// Terminate Database after Nuxt Generate
if (options.terminateDatabasesAfterGenerate) {
terminateDatabasesInGenerateHooks(this)
}
}
/**
* Helper function to add service-worker templates
*/
function addServiceWorker(
{ config, onFirebaseHosting = false },
templateFile,
templateOptions = {}
) {
// Add Service Worker Template
this.addTemplate({
src: r(`sw-templates/${templateFile}`),
fileName: resolve(
this.options.srcDir,
this.options.dir.static,
templateFile
),
options: {
firebaseVersion: firebase.SDK_VERSION,
config,
loadFromFirebaseHosting:
process.env.NODE_ENV === 'production' ? onFirebaseHosting : false,
...templateOptions,
},
})
}
/**
* Adds the messaging service worker template if needed
*/
function loadMessaging(options) {
const { messaging } = options.services
if (!messaging || !messaging.createServiceWorker) {
return
}
addServiceWorker.call(this, options, 'firebase-messaging-sw.js', {
actions: messaging.actions,
inject: messaging.inject,
})
}
/**
* Handles server side authentication & client side auth initialization
*/
function loadAuth(options) {
const { auth } = options.services
const noop = (_) => _
if (!auth) {
return noop
}
if (!isEmpty(auth.initialize)) {
// Register initAuth plugin
if (options.lazy || auth.initialize.subscribeManually) {
this.addTemplate({
src: r('plugins/services/auth.initialize.js'),
fileName: 'firebase/service.auth.initialize.js',
})
} else {
this.addPlugin({
src: r('plugins/services/auth.initialize.js'),
fileName: 'firebase/service.auth.initialize.js',
})
}
}
// Early return when ssr auth is not needed
if (!auth.ssr) {
return noop
}
const ssrConfig = Object.assign({}, auth.ssr)
options.sessions = false
// Resolve credential setting
const credential =
typeof ssrConfig.credential === 'string'
? this.nuxt.resolver.resolveAlias(ssrConfig.credential)
: ssrConfig.credential || false
// Add Service-Worker
addServiceWorker.call(this, options, 'firebase-auth-sw.js', {
authOptions: options.services.auth,
ignorePaths: [
'/__webpack_hmr',
'/_loading',
this.options.build.publicPath,
...(ssrConfig.ignorePaths || []),
],
})
if (ssrConfig.serverLogin && credential) {
options.sessions = Object.assign({}, ssrConfig.serverLogin)
this.addPlugin({
src: r('plugins/services/auth.serverLogin.js'),
fileName: 'firebase/service.auth.serverLogin-server.js',
mode: 'server',
options: {
credential,
config: options.config,
},
})
const sessionLifetime = options.sessions.sessionLifetime || 0
this.nuxt.hook('render:routeDone', async (_, __, { res }) => {
if (!res || !res.locals || !res.locals._session) {
return
}
const { _session: session, _manager: manager } = res.locals
if (manager) {
manager.endSession(session.name)
return
}
// fallback if session manager was not passed (SHOULD NOT HAPPEN)
const elapsed = Date.now() - session.options._created
if (elapsed >= sessionLifetime) {
try {
await session.delete()
} catch (error) {
logger.error('App deletion failed: ' + error.code)
}
}
})
}
return () => {
this.addPlugin({
src: r('plugins/services/auth.ssr.js'),
fileName: 'firebase/service.auth.ssr-server.js',
mode: 'server',
options: {
credential,
config: options.config,
},
})
}
}
/**
* Validates the options defined by the user and throws an error is something is
* missing or wrongly set up.
* See: https://firebase.nuxtjs.org/guide/options/
*/
function validateOptions(options) {
if (isEmpty(options)) {
return logger.error(
'Options are missing or empty, add at least the Firebase config parameters in your nuxt.config.js file.'
)
}
if (isEmpty(options.services)) {
return logger.error(
`The 'services' option is missing or empty, make sure to define it properly.
See: https://firebase.nuxtjs.org/guide/getting-started#configure`
)
}
if (isEmpty(options.config)) {
return logger.error(
'Firebase config not set properly in nuxt.config.js, config object is missing.'
)
}
if (options.customEnv && !process.env.FIRE_ENV) {
return logger.error(
'CustomEnv mode requires process.env.FIRE_ENV variable to be set.'
)
}
}
/**
* Either gets the current environment from the FIRE_ENV env variable
* or the NODE_ENV variable, depending on setup.
* See: https://firebase.nuxtjs.org/guide/options/#customenv
*/
function getCurrentEnv(options) {
if (options.customEnv) {
return process.env.FIRE_ENV
}
return process.env.NODE_ENV
}
/**
* If config is setup within an environment object that is equal to the current environment
* we set that as the new options.config.
* Otherwise, we expect the keys to be set directly in options.config already.
* See: https://firebase.nuxtjs.org/guide/options/#config
*/
function getFinalUseConfigObject(config, currentEnv) {
if (config && config[currentEnv]) {
return config[currentEnv]
}
return config
}
/**
* Checks the Firebase config for the current environment in the nuxt.config.js file.
* Breaks if a required key is missing.
* See: https://firebase.nuxtjs.org/guide/options/#config
*/
function validateConfigKeys(options, currentEnv) {
const configKeys = Object.keys(options.config || false)
const requiredKeys = [
'apiKey',
'authDomain',
// 'databaseURL', // legacy, only available in old projects
'projectId',
'storageBucket',
'messagingSenderId',
'appId',
// 'measurementId' - not a must without Analytics, we throw a warning below
]
// If one of the required keys is missing, throw an error:
if (requiredKeys.some((k) => !configKeys.includes(k))) {
const missingKey =
requiredKeys[requiredKeys.findIndex((k) => !configKeys.includes(k))]
return logger.error(
`Missing or incomplete config for current environment '${currentEnv}': key '${missingKey}' is required!`
)
}
// Only if Analytics is enabled and the measurementId key is missing, throw an error.
if (options.analytics && !configKeys.includes('measurementId')) {
return logger.warn(
'Missing measurementId configuration value. Analytics will be non-functional.'
)
}
}
/**
* This makes sure nuxt generate does finish without running into a timeout issue.
* Might be able to remove this at some point (e.g. with Nuxt 3)
* See https://github.com/nuxt-community/firebase-module/issues/93
*/
function terminateDatabasesInGenerateHooks(ctx) {
ctx.nuxt.hook('generate:before', async (generator) => {
const { default: firebase } = await import('firebase/compat/app')
await import('firebase/compat/database')
await import('firebase/compat/firestore')
if (!firebase.apps.length) {
firebase.initializeApp(generator.options.firebase.config)
}
generator.$fire = firebase.apps[0]
})
ctx.nuxt.hook('generate:done', async ({ $fire }) => {
// Terminate Databases
try {
await $fire.database().goOffline()
console.info('RealTime Database manually terminated.')
} catch (e) {}
try {
await $fire.firestore().terminate()
console.info('Firestore manually terminated.')
} catch (e) {}
})
}
function isEmpty(val) {
return val == null || !(Object.keys(val) || val).length
}
module.exports.meta = require('../package.json')
================================================
FILE: packages/firebase-module/lib/plugins/README.md
================================================
# Plugins
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.
[Lodas Template](https://lodash.com/docs/4.17.15#template) is used to parse these plugins.
================================================
FILE: packages/firebase-module/lib/plugins/main.js
================================================
import createApp from './app.js'
<%
const { enabledServices } = options
serverServices = enabledServices.filter(service => !service.clientOnly)
clientServices = enabledServices
for (const service of enabledServices) { %>
<%= `import ${service.id}Service from './service.${service.id}.js'`%><%
} %>
const appConfig = <%= serialize(options.config) %>
export default async (ctx, inject) => {
<%/****************************************
**************** LAZY MODE **************
****************************************/%>
<% if (options.lazy) { %>
let firebase, session
let firebaseReady = false
const fire = {
async appReady() {
if (!firebaseReady) {
({ firebase, session } = await createApp(appConfig, ctx))
firebaseReady = true;
<% if (options.injectModule) { %>
forceInject(ctx, inject, "fireModule", firebase)
<% } %>
}
return session
},
async ready() {
await fire.appReady()
let servicePromises = []
<% if (serverServices.length) { %>
if (process.server) {
servicePromises = [
<%= serverServices.reduce((acc, service) => `${acc}fire.${service.id}Ready(),\n `, '') %>
]
}
<% } %>
<% if (clientServices.length) { %>
if (process.client) {
servicePromises = [
<%= clientServices.reduce((acc, service) => `${acc}fire.${service.id}Ready(),\n `, '') %>
]
}
<% } %>
await Promise.all(servicePromises)
return session
}
}
if (process.server) {
<% for (service of serverServices) { %>
<% const serviceName = service.id %>
fire.<%= serviceName %> = null
fire.<%= serviceName %>Ready = async () => {
if (!fire.<%= serviceName %>) {
await fire.appReady()
fire.<%= serviceName %> = await <%= `${service.id}Service(session, firebase, ctx, inject)` %>
}
return fire.<%= serviceName %>
}
<% } %>
}
if (process.client) {
<% for (service of clientServices) { %>
<% const serviceName = service.id %>
fire.<%= serviceName %> = null
fire.<%= serviceName %>Ready = async () => {
if (!fire.<%= serviceName %>) {
await fire.appReady()
fire.<%= serviceName %> = await <%= `${service.id}Service(session, firebase, ctx, inject)` %>
}
return fire.<%= serviceName %>
}
<% } %>
}
inject('fire', fire)
ctx.$fire = fire
<%/****************************************
************* NON-LAZY MODE *************
****************************************/%>
<% } else { %>
const { firebase, session } = await createApp(appConfig, ctx)
let servicePromises = []
<% if (serverServices.length) { %>
if (process.server) {
servicePromises = [
<%= serverServices.reduce((acc, service) => `${acc}${service.id}Service(session, firebase, ctx, inject),\n `, '') %>
]
}
<% } %>
<% if (clientServices.length) { %>
if (process.client) {
servicePromises = [
<%= clientServices.reduce((acc, service) => `${acc}${service.id}Service(session, firebase, ctx, inject),\n `, '') %>
]
}
<% } %>
const [
<%= enabledServices.map(service => service.id).join(',\n ') %>
] = await Promise.all(servicePromises)
const fire = {
<%= enabledServices.map(service => `${service.id}: ${service.id}`).join(',\n ') %>
}
<% if (options.injectModule) { %>
inject('fireModule', firebase)
ctx.$fireModule = firebase
<% } %>
inject('fire', fire)
ctx.$fire = fire
<% } %>
}
<%/*************************************
************* HELPERS********************
****************************************/%>
<%/**
Custom inject function that is able to overwrite previously injected values,
which original inject doesn't allow to do.
This method is copied from https://github.com/nuxt-community/sentry-module/blob/master/lib/plugin.lazy.js#L189
which is adapted from the inject method in nuxt/vue-app/template/index.js
Fixes https://github.com/nuxt-community/firebase-module/issues/366
**/%>
function forceInject (ctx, inject, key, value) {
inject(key, value)
const injectKey = '$' + key
ctx[injectKey] = value
if (typeof window !== "undefined" && window.<%= globals.nuxt %>) {
// If clause makes sure it's only run when ready() is called in a component, not in a plugin.
window.<%= globals.nuxt %>.$options[injectKey] = value
}
}
================================================
FILE: packages/firebase-module/lib/plugins/services/analytics.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session, firebase) {
// Can only be initiated on client side
if (!process.client) {
return
}
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
// Only initialize it if the Browser supports it
const isSupported = await firebase.analytics.isSupported()
if (!isSupported) {
console.info('[@nuxtjs/firebase]: Firebase Analytics was not initialized because it is not supported on this browser.')
return
}
const analyticsService = session.<%= serviceMapping.id %>()
<% if ('collectionEnabled' in serviceOptions) { %>
// In development we want to disable analytics collection
analyticsService.setAnalyticsCollectionEnabled(<%= !!serviceOptions.collectionEnabled %>)
<% } %>
return analyticsService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/app.js
================================================
<%= options.writeStaticImports(options) %>
export default async function createApp(config, {res}) {
<%= (statement = options.writeImportStatement(options))
&& `const firebaseModule = ${statement}`
%>
const firebase = firebaseModule.default
<% if (typeof options.sessions === 'object') { %>
/*************************************************
* If Firebase "Auth SSR serverLogin Option" is on
*************************************************/
let session
if (process.server && res && res.locals && res.locals.user) {
const { default: SessionManager } = await import('@nuxtjs/firebase/lib/utils/auth-ssr/ssr-auth-session-manager.js')
const manager = new SessionManager(firebase, {
config,
sessions: <%= serialize(options.sessions) %>
})
// Resolve the firebase app corresponding to the server user
session = await manager.startSession(res.locals.user.uid)
res.locals._session = session
res.locals._manager = manager
} else {
session = firebase.apps.find(a => a.name === '[DEFAULT]') || firebase.initializeApp(config)
}
<% } else { %>
/*****************************************************
* Without "Auth SSR serverLogin Option" -> normal init
*****************************************************/
if (!firebase.apps.length) {
firebase.initializeApp(config)
}
const session = firebase.apps[0]
<% } %>
return {
firebase,
session
}
}
================================================
FILE: packages/firebase-module/lib/plugins/services/appCheck.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
// Can only be initiated on client side
if (!process.client) {
return
}
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
<% /* Uses debug config, if debug token option is set. */ %>
<% if (serviceOptions.debugToken) { %>
self.FIREBASE_APPCHECK_DEBUG_TOKEN = <%= serviceOptions.debugToken %>
<% } %>
const appCheckService = session.<%= serviceMapping.id %>()
return appCheckService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/auth.initialize.js
================================================
// runs the functions once BEFORE the root Vue.js Application is instantiated.
export default ({ $fireAuthStore }) => {
// Can only be initiated on client side
if (!process.client) {
return
}
return $fireAuthStore.subscribe()
}
================================================
FILE: packages/firebase-module/lib/plugins/services/auth.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement } = options %>
<% const hasOnAuthStateChangedMutation = (serviceOptions.initialize && typeof serviceOptions.initialize.onAuthStateChangedMutation === 'string') %>
<% const hasOnAuthStateChangedAction = (serviceOptions.initialize && typeof serviceOptions.initialize.onAuthStateChangedAction === 'string') %>
<% const hasOnAuthStateChanged = (hasOnAuthStateChangedMutation || hasOnAuthStateChangedAction) %>
<% const onIdTokenChangedMutation = (serviceOptions.initialize && typeof serviceOptions.initialize.onIdTokenChangedMutation === 'string') %>
<% const onIdTokenChangedAction = (serviceOptions.initialize && typeof serviceOptions.initialize.onIdTokenChangedAction === 'string') %>
<% const hasIdTokenChanged = (onIdTokenChangedMutation || onIdTokenChangedAction) %>
export default async function (session, firebase, ctx, inject) {
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const authService = session.<%= serviceMapping.id %>()
<% /* Uses emulator, if emulatorPort is set. */ %>
<% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof serviceOptions.emulatorHost === 'string'
? serviceOptions.emulatorHost
: 'http://localhost'
%>
authService.useEmulator('<%= `${emulatorHost}` %>:<%= `${serviceOptions.emulatorPort}` %>'<% if (serviceOptions.disableEmulatorWarnings) { %><%= `, { disableWarnings: true }` %><% } %>)
<% } %>
<% if (serviceOptions.persistence) { %>
if (process.client) {
const persistence = firebase.auth.Auth.Persistence.<%=
serviceOptions.persistence === 'session'
? 'SESSION'
: serviceOptions.persistence === 'none'
? 'NONE'
: 'LOCAL'
%>
try {
await authService.setPersistence(persistence)
} catch (err) {
if (err.code === 'auth/invalid-persistence-type') {
console.warn(`[@nuxtjs/firebase]: Invalid persistence type '${persistence}' provided`)
} else if (err.code === 'auth/unsupported-persistence-type') {
console.warn(`[@nuxtjs/firebase]: Persistence type '${persistence}' is not supported in this environment.`)
}
}
}
<% } %>
<% if (serviceOptions.initialize) { %>
// Sets up a listener, mutations and action for every onAuthStateChanged by Firebase.
const fireAuthStore = {
unsubscribe() {
if (this.unsubscribeAuthStateListener) {
this.unsubscribeAuthStateListener()
delete this.unsubscribeAuthStateListener
}
if (this.unsubscribeIdTokenListener) {
this.unsubscribeIdTokenListener()
delete this.unsubscribeIdTokenListener
}
},
subscribe() {
const promises = []
<% if (hasOnAuthStateChanged && !this.unsubscribeAuthStateListener) { %>
promises.push(new Promise(resolve => {
this.unsubscribeAuthStateListener = authService.onAuthStateChanged(async authUser => {
const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null
<% if (hasOnAuthStateChangedMutation) { %>
ctx.store.commit(<%= serialize(serviceOptions.initialize.onAuthStateChangedMutation) %>, { authUser, claims })
<% } %>
<% if (hasOnAuthStateChangedAction) { %>
await ctx.store.dispatch(<%= serialize(serviceOptions.initialize.onAuthStateChangedAction) %>, { authUser, claims })
<% } %>
resolve()
})
}))
<% } %>
<% if (hasIdTokenChanged && !this.unsubscribeIdTokenListener) { %>
promises.push(new Promise(resolve => {
this.unsubscribeIdTokenListener = authService.onIdTokenChanged(async authUser => {
const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null
<% if (onIdTokenChangedMutation) { %>
ctx.store.commit(<%= serialize(serviceOptions.initialize.onIdTokenChangedMutation) %>, { authUser, claims })
<% } %>
<% if (onIdTokenChangedAction) { %>
await ctx.store.dispatch(<%= serialize(serviceOptions.initialize.onIdTokenChangedAction) %>, { authUser, claims })
<% } %>
resolve()
})
}))
<% } %>
return Promise.all(promises)
}
}
inject('fireAuthStore', fireAuthStore)
<% } %>
return authService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/auth.serverLogin.js
================================================
import admin from 'firebase-admin'
const config = <%= serialize(options.config) %>
if (!admin.apps.length) {
const credential = <%=
options.credential === true
? 'admin.credential.applicationDefault()'
: `admin.credential.cert(require(${serialize(options.credential)}))`
%>
admin.initializeApp({
credential,
...config
})
}
export default async ({ res }) => {
if (res && res.locals && res.locals.user && res.locals.user.uid && res.locals._manager) {
const uid = res.locals.user.uid
const manager = res.locals._manager
// if the user is already logged in to the session, return early
const user = manager.getUser(uid)
if (user) return
try {
// Retrieve a custom auth token from the users uid
const customToken = await admin.auth().createCustomToken(uid)
// attempt client sdk sign
await manager.login(uid, customToken)
} catch (error) {
// @TODO: implement appropriate error handling, if at all necessary
console.error(error)
}
}
}
================================================
FILE: packages/firebase-module/lib/plugins/services/auth.ssr.js
================================================
import admin from 'firebase-admin'
const config = <%= serialize(options.config) %>
const simulateUserRecord = ({
uid,
email,
email_verified: emailVerified,
name: displayName
}) => ({
uid,
email,
emailVerified,
displayName
})
if (!admin.apps.length) {
<% if (options.credential) { %>
const credential = <%=
options.credential === true
? 'admin.credential.applicationDefault()'
: `admin.credential.cert(require(${serialize(options.credential)}))`
%>
admin.initializeApp({
credential,
...config
})
<% } else { %>
admin.initializeApp(config)
<% } %>
}
export default async ({ req, res }) => {
if (!req || !req.headers.authorization) {
return
}
// Parse the injected ID token from the request header.
const authorizationHeader = req.headers.authorization || ''
const components = authorizationHeader.split(' ')
const idToken = components.length > 1 ? components[1] : ''
try {
// Try to verify the id token, additionally checking if the token was revoked
const decodedToken = await admin.auth().verifyIdToken(idToken)
if (decodedToken.uid) {
const authUser = <%=
options.credential
? 'await admin.auth().getUser(decodedToken.uid)'
: 'simulateUserRecord(decodedToken)'
%>
res.locals = {
...res.locals,
user: {
...authUser,
allClaims: decodedToken,
idToken,
}
}
}
} catch (e) {
console.error(e)
}
}
================================================
FILE: packages/firebase-module/lib/plugins/services/database.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const databaseService = session.<%= serviceMapping.id %>()
<% /* Uses emulator, if emulatorPort is set. */ %>
<% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof serviceOptions.emulatorHost === 'string'
? serviceOptions.emulatorHost
: 'localhost'
%>
databaseService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>)
<% } %>
return databaseService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/firestore.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const firestoreService = session.<%= serviceMapping.id %>()
<% if (typeof serviceOptions.settings === 'object') { %>
firestoreService.settings(<%= serialize(serviceOptions.settings) %>)
<% } %>
<% /* Uses emulator, if emulatorPort is set. */ %>
<% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof serviceOptions.emulatorHost === 'string'
? serviceOptions.emulatorHost
: 'localhost'
%>
// If statement fixes Issue #390, only runs useEmulator when not yet called (relevant on server)
if (process.client || firestoreService._delegate._settings.host === 'firestore.googleapis.com') {
firestoreService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>)
}
<% } %>
<% if (serviceOptions.enablePersistence) { %>
// persistence should only be enabled client side
if (process.client) {
try {
<% const enablePersistence = Object.assign({}, serviceOptions.enablePersistence) %>
await firestoreService.enablePersistence(<%= serialize(enablePersistence) %>)
} catch (err) {
if (err.code == 'failed-precondition') {
console.warn('[@nuxtjs/firebase]: Firestore Persistence not enabled. Multiple tabs open, persistence can only be enabled in one tab at a a time.')
} else if (err.code == 'unimplemented') {
console.info('[@nuxtjs/firebase]: Firestore Persistence not enabled. The current browser does not support all of the features required to enable persistence.')
}
}
}
<% } %>
return firestoreService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/functions.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
<% if (serviceOptions.location) { %>
const functionsService = session.<%= serviceMapping.id %>('<%= serviceOptions.location %>')
<% } else { %>
<% /* If .location is undefined, default will be "us-central1" */ %>
const functionsService = session.<%= serviceMapping.id %>()
<% } %>
<% /* Uses emulator, if emulatorPort is set. */ %>
<% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof serviceOptions.emulatorHost === 'string'
? serviceOptions.emulatorHost
: 'http://localhost'
%>
functionsService.useFunctionsEmulator('<%= `${emulatorHost}` %>:<%= `${serviceOptions.emulatorPort}` %>')
<% } %>
return functionsService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/messaging.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session, firebase) {
// Can only be initiated on client side
if (!process.client) {
return
}
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
if (firebase.messaging.isSupported()) {
const messagingService = session.<%= serviceMapping.id %>()
<% if (serviceOptions.fcmPublicVapidKey) { %>
messagingService.getToken({vapidKey: <%= serialize(serviceOptions.fcmPublicVapidKey) %>})
<% } %>
return messagingService
}
}
================================================
FILE: packages/firebase-module/lib/plugins/services/performance.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
// Can only be initiated on client side
if (!process.client) {
return
}
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const performanceService = session.<%= serviceMapping.id %>()
return performanceService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/remoteConfig.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
// Can only be initiated on client side
if (!process.client) {
return
}
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const remoteConfigService = session.<%= serviceMapping.id %>()
<% const settings = Object.assign({}, serviceOptions.settings) %>
remoteConfigService.settings = {
fetchTimeoutMillis: <%= `${settings.fetchTimeoutMillis || 60000 }` %>,
minimumFetchIntervalMillis: <%= `${settings.minimumFetchIntervalMillis || 43200000}` %>
}
<% if (typeof serviceOptions.defaultConfig === 'object') { %>
remoteConfigService.defaultConfig = <%= serialize(serviceOptions.defaultConfig) %>
<% } %>
return remoteConfigService
}
================================================
FILE: packages/firebase-module/lib/plugins/services/storage.js
================================================
<% const { serviceMapping, serviceOptions, writeImportStatement, writeInjections } = options %>
export default async function (session) {
<% if (!serviceOptions.static) { %>
<%= writeImportStatement(options) %>
<% } %>
const storageService = session.<%= serviceMapping.id %>()
<% /* Uses emulator, if emulatorPort is set. */ %>
<% if (['string', 'number'].includes(typeof serviceOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof serviceOptions.emulatorHost === 'string'
? serviceOptions.emulatorHost
: 'localhost'
%>
storageService.useEmulator('<%= `${emulatorHost}` %>', <%= `${serviceOptions.emulatorPort}` %>)
<% } %>
return storageService
}
================================================
FILE: packages/firebase-module/lib/sw-templates/README.md
================================================
# SW-Templates
These *service worker templates* will be parsed by lodash template and then copied in the /static folder of the built project.
[Lodash Template](https://lodash.com/docs/4.17.15#template) is used to parse these plugins.
================================================
FILE: packages/firebase-module/lib/sw-templates/firebase-auth-sw.js
================================================
const ignorePaths = <%= serialize(options.ignorePaths) %>
<% if (options.loadFromFirebaseHosting) { %>
// Only works on Firebase hosting!
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js')
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-auth-compat.js')
importScripts('/__/firebase/init.js')
<% } else { %>
importScripts(
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js'
)
importScripts(
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-auth-compat.js'
)
firebase.initializeApp(<%= serialize(options.config) %>)
<% } %>
// Initialize authService
const authService = firebase.auth()
<% /* Uses emulator, if emulatorPort is set. */ %>
<% const authOptions = options.authOptions %>
<% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof authOptions.emulatorHost === 'string'
? authOptions.emulatorHost
: 'http://localhost'
%>
authService.useEmulator('<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>')
<% } %>
/**
* Returns a promise that resolves with an ID token if available.
* @return {!Promise} The promise that resolves with an ID token if
* available. Otherwise, the promise resolves with null.
*/
const getIdToken = () => {
return new Promise((resolve) => {
const unsubscribe = authService.onAuthStateChanged((user) => {
unsubscribe()
if (user) {
// force token refresh as it might be used to sign in server side
user.getIdToken(true).then((idToken) => {
resolve(idToken)
}, () => {
resolve(null)
})
} else {
resolve(null)
}
})
})
}
const fetchWithAuthorization = async (original, idToken) => {
// Clone headers as request headers are immutable.
const headers = new Headers()
for (let entry of original.headers.entries()) {
headers.append(entry[0], entry[1])
}
// Add ID token to header.
headers.append('Authorization', 'Bearer ' + idToken)
// Create authorized request
const { url, ...props } = original.clone()
const authorized = new Request(url, {
...props,
mode: 'same-origin',
redirect: 'manual',
headers
})
return fetch(authorized)
}
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url)
const expectsHTML = event.request.headers.get('accept').includes('text/html')
const isSameOrigin = self.location.origin === url.origin
const isHttps = (self.location.protocol === 'https:' || self.location.hostname === 'localhost' || self.location.hostname === '127.0.0.1')
const isIgnored = ignorePaths.some(path => {
if (typeof path === 'string') {
return url.pathname.startsWith(path)
}
return path.test(url.pathname.slice(1))
})
// https://github.com/nuxt-community/firebase-module/issues/465
if (!expectsHTML || !isSameOrigin || !isHttps || isIgnored) {
<% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %>
<% const emulatorHost =
typeof authOptions.emulatorHost === 'string'
? authOptions.emulatorHost
: 'http://localhost'
%>
if (event.request.url.startsWith('https://www.googleapis.com/identitytoolkit/')) {
event.respondWith(
fetch({
...event.request,
...{ url: event.request.url.replace(/https:\/\//, '<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>/') }
})
)
} else event.respondWith(fetch(event.request))
<% } else { %>
event.respondWith(fetch(event.request))
<% } %>
return
}
// Fetch the resource after checking for the ID token.
// This can also be integrated with existing logic to serve cached files
// in offline mode.
event.respondWith(
getIdToken().then(
idToken => idToken
// if the token was retrieved we attempt an authorized fetch
// if anything goes wrong we fall back to the original request
? fetchWithAuthorization(event.request, idToken).catch(() => fetch(event.request))
// otherwise we return a fetch of the original request directly
: fetch(event.request)
)
)
})
// In service worker script.
self.addEventListener('activate', event => {
event.waitUntil(clients.claim())
})
================================================
FILE: packages/firebase-module/lib/sw-templates/firebase-messaging-sw.js
================================================
<% if (options.loadFromFirebaseHosting) { %>
// Only works on Firebase hosting & not on localhost!
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js')
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-messaging-compat.js')
importScripts('/__/firebase/init.js')
<% } else { %>
importScripts(
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js'
)
importScripts(
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-messaging-compat.js'
)
firebase.initializeApp(<%= serialize(options.config) %>)
<% } %>
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging()
<% if (options.actions) { %>
// Setup event listeners for actions provided in the config:
self.addEventListener('notificationclick', function(e) {
const actions = <%= serialize(options.actions) %>
const action = actions.find(x => x.action === e.action)
const notification = e.notification
if (!action) return
if (action.url) {
clients.openWindow(action.url)
notification.close()
}
})
<% } %>
<% if (options.inject) { %>
<%= options.inject %>
<% } %>
================================================
FILE: packages/firebase-module/lib/utils/auth-ssr/ssr-auth-session-manager.js
================================================
const logger = require('../logger')
const sessions = {
working: false,
queue: [],
active: [],
}
const logins = {
working: false,
queue: [],
}
async function removeSession(session) {
logger.info('deleting session: ', session.instance.name)
const index = sessions.active.findIndex(
(s) => s.instance.name !== session.instance.name
)
sessions.active.splice(index, 1)
await session.instance.delete()
}
function enqueueSessionOperation(operation) {
return new Promise((resolve) => {
sessions.queue.push({
operation,
resolve,
})
dequeueSessionOperation()
})
}
async function dequeueSessionOperation() {
if (sessions.working) {
return
}
sessions.working = true
const item = sessions.queue.shift()
if (!item) {
sessions.working = false
return
}
const result = await item.operation()
item.resolve(result)
sessions.working = false
dequeueSessionOperation()
}
class SessionManager {
constructor(firebase, { config, sessions: sessionConfig }) {
this.firebase = firebase
this.config = config
this.lifetime = sessionConfig.sessionLifetime || 0
this.loginDelay = sessionConfig.loginDelay || 50
}
getSession(name, touch = true) {
const session = sessions.active.find((s) => s.instance.name === name)
if (session) {
if (session.timeout) {
logger.debug('session retrieved, aborting removal')
clearTimeout(session.timeout)
session.timeout = null
}
if (touch) session.touched = Date.now()
}
return session
}
getUser(name) {
const session = this.getSession(name)
if (!session) {
const error = new Error(`Missing session for user ${name}`)
error.code = 'nuxt-firebase/missing-session'
throw error
}
const auth = session.instance.auth()
return auth.currentUser
}
startSession(name = '[DEFAULT]') {
return enqueueSessionOperation(() => {
logger.info('starting session for: ', name)
const session = this.getSession(name)
if (session) {
if (name === '[DEFAULT]') return session.instance
session.active++
logger.debug('found existing, active sessions: ', session.active)
return session.instance
}
const instance =
this.firebase.apps.find((a) => a.name === name) ??
this.firebase.initializeApp(this.config, name)
sessions.active.push({
instance,
active: 1,
touched: Date.now(),
})
logger.debug('created, active sessions: ', 1)
return instance
})
}
endSession(name = '[DEFAULT]') {
return enqueueSessionOperation(() => {
logger.info('ending session for: ', name)
const session = this.getSession(name, false)
if (!session || name === '[DEFAULT]') return
session.active--
logger.debug('active sessions: ', session.active)
if (session.active < 1) {
const logoutTimer = this.lifetime - (Date.now() - session.touched)
logger.debug('enqueueing session removal in: ', logoutTimer)
session.timeout = setTimeout(() => {
enqueueSessionOperation(() => removeSession(session))
}, logoutTimer)
}
})
}
login(name, token) {
logger.debug('enqueueing login attempt', Date.now())
const session = this.getSession(name)
const auth = session.instance.auth()
return new Promise((resolve, reject) => {
logins.queue.push({
promise: () => auth.signInWithCustomToken(token),
resolve,
reject,
})
this.dequeueLoginAttempts()
})
}
async dequeueLoginAttempts() {
if (logins.working) {
return
}
logins.working = true
const current = logins.queue.shift()
if (!current) {
logins.working = false
return
}
try {
logger.debug('attempting login: ' + Date.now())
const { user } = await current.promise()
current.resolve(user)
} catch (e) {
current.reject(e)
}
setTimeout(() => {
logins.working = false
this.dequeueLoginAttempts()
}, this.loginDelay)
}
}
module.exports = SessionManager
================================================
FILE: packages/firebase-module/lib/utils/logger.js
================================================
const consola = require('consola')
module.exports = consola.withScope('nuxt:firebase')
================================================
FILE: packages/firebase-module/lib/utils/template-utils.js
================================================
/*
id: used in...
- module config
- names of the services .js files
- name of the Firebase object/function, e.g. firebase.remoteConfig
- injection names from version 7+ (e.g. $fire.remoteConfig)
importName: name of the import, e.g. import 'firebase/remote-config'
*/
const serviceMappings = {
app: {
id: 'app',
importName: 'app',
clientOnly: false,
},
auth: {
id: 'auth',
importName: 'auth',
clientOnly: false,
},
database: {
// = realtime DB
id: 'database',
importName: 'database',
clientOnly: false,
},
firestore: {
id: 'firestore',
importName: 'firestore',
clientOnly: false,
},
storage: {
id: 'storage',
importName: 'storage',
clientOnly: false,
},
functions: {
id: 'functions',
importName: 'functions',
clientOnly: false,
},
messaging: {
id: 'messaging',
importName: 'messaging',
clientOnly: true,
},
performance: {
id: 'performance',
importName: 'performance',
clientOnly: true,
},
analytics: {
id: 'analytics',
importName: 'analytics',
clientOnly: true,
},
remoteConfig: {
id: 'remoteConfig',
importName: 'remote-config',
clientOnly: true,
},
appCheck: {
id: 'appCheck',
importName: 'app-check',
clientOnly: true,
},
}
function writeStaticImports(options) {
return Object.values(serviceMappings)
.map((serviceMapping) =>
writeImportStatement(options, serviceMapping, true)
)
.filter(Boolean)
.join('\n')
}
function writeImportStatement(options, serviceMapping, staticOnly = false) {
if (!serviceMapping) {
serviceMapping = options.serviceMapping
// TODO - does this make sense?
}
const serviceOptions = options.services[serviceMapping.id]
if (!serviceOptions) {
return
}
const useStaticImport = serviceOptions.static
let pathAppendix = ''
if (serviceOptions.memoryOnly) {
// Only works with Firestore
pathAppendix = '/memory'
}
const servicePath = serviceMapping.importName
const importPath = `'firebase/compat/${servicePath}${pathAppendix}'`
if (staticOnly) {
if (!useStaticImport) {
return
}
return `import ${importPath}`
}
const webpackComments = []
// Add Chunk Name Comment
let webpackChunkName = serviceOptions.chunkName
if (!webpackChunkName && process.env.NODE_ENV !== 'production') {
webpackChunkName = `firebase-${servicePath}`
}
if (webpackChunkName) {
webpackComments.push(`webpackChunkName: '${webpackChunkName}'`)
}
// Add Preload Comment
if (serviceOptions.preload) {
webpackComments.push('webpackPreload: true')
}
// Add strings surrounding the comment
let webpackCommentsString = ''
if (webpackComments.length) {
webpackCommentsString = `/* ${webpackComments.join(', ')} */`
}
return `await import(${webpackCommentsString}${importPath})`
}
module.exports = {
serviceMappings,
writeStaticImports,
writeImportStatement,
}
================================================
FILE: packages/firebase-module/package.json
================================================
{
"name": "@nuxtjs/firebase",
"version": "8.2.2",
"description": "Intergrate Firebase into your Nuxt project.",
"keywords": [
"firebase",
"firestore",
"google",
"googleauthentication",
"nuxt",
"realtimedatabase"
],
"homepage": "https://firebase.nuxtjs.org/",
"repository": "nuxt-community/firebase-module",
"license": "MIT",
"author": "Pascal Luther",
"files": [
"lib",
"types/*.d.ts"
],
"main": "lib/module.js",
"types": "types/index.d.ts",
"scripts": {
"lint": "eslint --ext .js,.vue lib test",
"release": "standard-version && git push --follow-tags && npm publish",
"test": "npm run lint && jest",
"commit": "npx git-cz",
"docs": "cd docs && npm run dev"
},
"dependencies": {
"consola": "^2.15.3"
},
"devDependencies": {
"@babel/core": "^7.14.5",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.16.8",
"@commitlint/cli": "latest",
"@commitlint/config-conventional": "latest",
"@nuxt/types": "^2.15.6",
"@nuxtjs/eslint-config": "^8.0.0",
"@nuxtjs/module-test-utils": "^1.6.3",
"babel-eslint": "^10.1.0",
"babel-jest": "^28.1.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"codecov": "latest",
"core-js": "^3.14.0",
"cz-conventional-changelog": "latest",
"eslint": "^8.0.1",
"firebase": "^9.6.2",
"husky": "^7.0.2",
"jest": "^28.1.0",
"nuxt": "^2.15.6",
"proxy-mock-js": "^1.0.3",
"standard-version": "^9.3.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.8.4"
},
"peerDependencies": {
"firebase": "^9.6.2",
"nuxt": "^2.15.6"
},
"publishConfig": {
"access": "public"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"optionalDependencies": {
"firebase-admin": "^10.0.0"
}
}
================================================
FILE: packages/firebase-module/renovate.json
================================================
{
"extends": [
"@nuxtjs"
]
}
================================================
FILE: packages/firebase-module/test/__snapshots__/default.test.js.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`default plugin contents 1`] = `
"import createApp from './app.js'
import authService from './service.auth.js'
import databaseService from './service.database.js'
import firestoreService from './service.firestore.js'
import storageService from './service.storage.js'
import functionsService from './service.functions.js'
import messagingService from './service.messaging.js'
import performanceService from './service.performance.js'
import analyticsService from './service.analytics.js'
import remoteConfigService from './service.remoteConfig.js'
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\\"}
export default async (ctx, inject) => {
/****************************************
**************** LAZY MODE **************
****************************************/
const { firebase, session } = await createApp(appConfig, ctx)
let servicePromises = []
if (process.server) {
servicePromises = [
authService(session, firebase, ctx, inject),
databaseService(session, firebase, ctx, inject),
firestoreService(session, firebase, ctx, inject),
storageService(session, firebase, ctx, inject),
functionsService(session, firebase, ctx, inject),
]
}
if (process.client) {
servicePromises = [
authService(session, firebase, ctx, inject),
databaseService(session, firebase, ctx, inject),
firestoreService(session, firebase, ctx, inject),
storageService(session, firebase, ctx, inject),
functionsService(session, firebase, ctx, inject),
messagingService(session, firebase, ctx, inject),
performanceService(session, firebase, ctx, inject),
analyticsService(session, firebase, ctx, inject),
remoteConfigService(session, firebase, ctx, inject),
]
}
const [
auth,
database,
firestore,
storage,
functions,
messaging,
performance,
analytics,
remoteConfig
] = await Promise.all(servicePromises)
const fire = {
auth: auth,
database: database,
firestore: firestore,
storage: storage,
functions: functions,
messaging: messaging,
performance: performance,
analytics: analytics,
remoteConfig: remoteConfig
}
inject('fire', fire)
ctx.$fire = fire
}
"
`;
================================================
FILE: packages/firebase-module/test/__snapshots__/lazy-init-auth.test.js.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`lazy-init-auth init auth plugin exist 1`] = `
"// runs the functions once BEFORE the root Vue.js Application is instantiated.
export default ({ $fireAuthStore }) => {
return $fireAuthStore.subscribe()
}
"
`;
================================================
FILE: packages/firebase-module/test/__snapshots__/lazy.test.js.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`lazy plugin contents 1`] = `
"import createApp from './app.js'
import authService from './service.auth.js'
import databaseService from './service.database.js'
import firestoreService from './service.firestore.js'
import storageService from './service.storage.js'
import functionsService from './service.functions.js'
import messagingService from './service.messaging.js'
import performanceService from './service.performance.js'
import analyticsService from './service.analytics.js'
import remoteConfigService from './service.remoteConfig.js'
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\\"}
export default async (ctx, inject) => {
/****************************************
**************** LAZY MODE **************
****************************************/
let firebase, session
let firebaseReady = false
const fire = {
async appReady() {
if (!firebaseReady) {
({ firebase, session } = await createApp(appConfig, ctx))
firebaseReady = true;
}
return session
},
async ready() {
await fire.appReady()
let servicePromises = []
if (process.server) {
servicePromises = [
fire.authReady(),
fire.databaseReady(),
fire.firestoreReady(),
fire.storageReady(),
fire.functionsReady(),
]
}
if (process.client) {
servicePromises = [
fire.authReady(),
fire.databaseReady(),
fire.firestoreReady(),
fire.storageReady(),
fire.functionsReady(),
fire.messagingReady(),
fire.performanceReady(),
fire.analyticsReady(),
fire.remoteConfigReady(),
]
}
await Promise.all(servicePromises)
return session
}
}
if (process.server) {
fire.auth = null
fire.authReady = async () => {
if (!fire.auth) {
await fire.appReady()
fire.auth = await authService(session, firebase, ctx, inject)
}
return fire.auth
}
fire.database = null
fire.databaseReady = async () => {
if (!fire.database) {
await fire.appReady()
fire.database = await databaseService(session, firebase, ctx, inject)
}
return fire.database
}
fire.firestore = null
fire.firestoreReady = async () => {
if (!fire.firestore) {
await fire.appReady()
fire.firestore = await firestoreService(session, firebase, ctx, inject)
}
return fire.firestore
}
fire.storage = null
fire.storageReady = async () => {
if (!fire.storage) {
await fire.appReady()
fire.storage = await storageService(session, firebase, ctx, inject)
}
return fire.storage
}
fire.functions = null
fire.functionsReady = async () => {
if (!fire.functions) {
await fire.appReady()
fire.functions = await functionsService(session, firebase, ctx, inject)
}
return fire.functions
}
}
if (process.client) {
fire.auth = null
fire.authReady = async () => {
if (!fire.auth) {
await fire.appReady()
fire.auth = await authService(session, firebase, ctx, inject)
}
return fire.auth
}
fire.database = null
fire.databaseReady = async () => {
if (!fire.database) {
await fire.appReady()
fire.database = await databaseService(session, firebase, ctx, inject)
}
return fire.database
}
fire.firestore = null
fire.firestoreReady = async () => {
if (!fire.firestore) {
await fire.appReady()
fire.firestore = await firestoreService(session, firebase, ctx, inject)
}
return fire.firestore
}
fire.storage = null
fire.storageReady = async () => {
if (!fire.storage) {
await fire.appReady()
fire.storage = await storageService(session, firebase, ctx, inject)
}
return fire.storage
}
fire.functions = null
fire.functionsReady = async () => {
if (!fire.functions) {
await fire.appReady()
fire.functions = await functionsService(session, firebase, ctx, inject)
}
return fire.functions
}
fire.messaging = null
fire.messagingReady = async () => {
if (!fire.messaging) {
await fire.appReady()
fire.messaging = await messagingService(session, firebase, ctx, inject)
}
return fire.messaging
}
fire.performance = null
fire.performanceReady = async () => {
if (!fire.performance) {
await fire.appReady()
fire.performance = await performanceService(session, firebase, ctx, inject)
}
return fire.performance
}
fire.analytics = null
fire.analyticsReady = async () => {
if (!fire.analytics) {
await fire.appReady()
fire.analytics = await analyticsService(session, firebase, ctx, inject)
}
return fire.analytics
}
fire.remoteConfig = null
fire.remoteConfigReady = async () => {
if (!fire.remoteConfig) {
await fire.appReady()
fire.remoteConfig = await remoteConfigService(session, firebase, ctx, inject)
}
return fire.remoteConfig
}
}
inject('fire', fire)
ctx.$fire = fire
/****************************************
************* NON-LAZY MODE *************
****************************************/
}
"
`;
================================================
FILE: packages/firebase-module/test/__snapshots__/with-module.test.js.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`with-module plugin contents 1`] = `
"import createApp from './app.js'
import authService from './service.auth.js'
import databaseService from './service.database.js'
import firestoreService from './service.firestore.js'
import storageService from './service.storage.js'
import functionsService from './service.functions.js'
import messagingService from './service.messaging.js'
import performanceService from './service.performance.js'
import analyticsService from './service.analytics.js'
import remoteConfigService from './service.remoteConfig.js'
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\\"}
export default async (ctx, inject) => {
/****************************************
**************** LAZY MODE **************
****************************************/
const { firebase, session } = await createApp(appConfig, ctx)
let servicePromises = []
if (process.server) {
servicePromises = [
authService(session, firebase, ctx, inject),
databaseService(session, firebase, ctx, inject),
firestoreService(session, firebase, ctx, inject),
storageService(session, firebase, ctx, inject),
functionsService(session, firebase, ctx, inject),
]
}
if (process.client) {
servicePromises = [
authService(session, firebase, ctx, inject),
databaseService(session, firebase, ctx, inject),
firestoreService(session, firebase, ctx, inject),
storageService(session, firebase, ctx, inject),
functionsService(session, firebase, ctx, inject),
messagingService(session, firebase, ctx, inject),
performanceService(session, firebase, ctx, inject),
analyticsService(session, firebase, ctx, inject),
remoteConfigService(session, firebase, ctx, inject),
]
}
const [
auth,
database,
firestore,
storage,
functions,
messaging,
performance,
analytics,
remoteConfig
] = await Promise.all(servicePromises)
const fire = {
auth: auth,
database: database,
firestore: firestore,
storage: storage,
functions: functions,
messaging: messaging,
performance: performance,
analytics: analytics,
remoteConfig: remoteConfig
}
inject('fireModule', firebase)
ctx.$fireModule = firebase
inject('fire', fire)
ctx.$fire = fire
}
"
`;
================================================
FILE: packages/firebase-module/test/default.test.js
================================================
const { resolve } = require('path')
const fs = require('fs-extra')
const { Nuxt, Builder } = require('nuxt')
const FirebaseModule = require('..')
jest.mock('firebase/compat/app', () => ({
apps: [
new Proxy(
{},
{
get(target, name) {
return jest.fn(() => ({}))
},
}
),
],
messaging: {
isSupported: jest.fn(),
},
}))
describe('default', () => {
let nuxt
const buildDir = resolve(__dirname, '.nuxt-default')
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, '..'),
buildDir,
srcDir: resolve(__dirname, 'fixture'),
modules: [
[
FirebaseModule,
{
injectModule: false,
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
},
services: {
analytics: true,
auth: true,
firestore: true,
functions: true,
messaging: true,
performance: true,
database: true,
remoteConfig: true,
storage: true,
},
},
],
],
}
config.dev = false
nuxt = new Nuxt(config)
const BundleBuilder = { build: (_) => _ }
const builder = new Builder(nuxt, BundleBuilder)
await builder.build()
}, 60000)
afterAll(async () => {
await nuxt.close()
})
test('plugin contents', async () => {
const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), {
encoding: 'utf8',
})
expect(content).toContain('auth,')
expect(content).toContain('messaging,')
expect(content).not.toContain('Mess')
expect(content).toMatchSnapshot()
})
test('exec plugin (server)', async () => {
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(1)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeUndefined()
})
test('exec plugin (client)', async () => {
process.client = true
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(1)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeUndefined()
})
})
================================================
FILE: packages/firebase-module/test/fixture/nuxt.config.js
================================================
import FirebaseModule from '../..'
export default {
rootDir: __dirname,
render: {
resourceHints: false,
},
modules: [FirebaseModule],
firebase: {
lazy: true,
injectModule: true,
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
databaseURL: 'https://test.firebaseio.com',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
},
services: {
auth: true,
database: true,
messaging: true,
analytics: true,
remoteConfig: true,
},
},
}
================================================
FILE: packages/firebase-module/test/fixture/pages/index.vue
================================================
Works!
================================================
FILE: packages/firebase-module/test/lazy-init-auth.test.js
================================================
const { resolve } = require('path')
const fs = require('fs-extra')
const { Nuxt, Builder } = require('nuxt')
const FirebaseModule = require('..')
jest.mock('firebase/compat/app', () => {
const { getProxyMock } = require('proxy-mock-js')
const spyFn = (name, fn) => jest.fn(fn)
const session = getProxyMock({}, 'firebaseSession', spyFn)
/* const session = new Proxy({}, {
get(target, name) {
return jest.fn(() => ({}))
}
}) */
return {
apps: [session],
messaging: {
isSupported: jest.fn(),
},
}
})
describe('lazy-init-auth', () => {
let nuxt
const buildDir = resolve(__dirname, '.nuxt-lazy-init-auth')
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, '..'),
buildDir,
srcDir: resolve(__dirname, 'fixture'),
modules: [
[
FirebaseModule,
{
injectModule: false,
lazy: true,
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
},
services: {
analytics: true,
auth: {
initialize: {
onAuthStateChangedAction: 'onAuthStateChanged',
},
},
firestore: true,
functions: true,
messaging: true,
performance: true,
database: true,
remoteConfig: true,
storage: true,
},
},
],
],
}
config.dev = false
nuxt = new Nuxt(config)
const BundleBuilder = { build: (_) => _ }
const builder = new Builder(nuxt, BundleBuilder)
await builder.build()
}, 60000)
afterAll(async () => {
await nuxt.close()
})
test('init auth plugin exist', async () => {
const content = await fs.readFile(
resolve(buildDir, 'firebase/service.auth.initialize.js'),
{ encoding: 'utf8' }
)
expect(content).toMatchSnapshot()
})
})
================================================
FILE: packages/firebase-module/test/lazy.test.js
================================================
const { resolve } = require('path')
const fs = require('fs-extra')
const { Nuxt, Builder } = require('nuxt')
const FirebaseModule = require('..')
jest.mock('firebase/compat/app', () => {
const { getProxyMock } = require('proxy-mock-js')
const spyFn = (name, fn) => jest.fn(fn)
const session = getProxyMock({}, 'firebaseSession', spyFn)
/* const session = new Proxy({}, {
get(target, name) {
return jest.fn(() => ({}))
}
}) */
return {
apps: [session],
messaging: {
isSupported: jest.fn(),
},
}
})
describe('lazy', () => {
let nuxt
const buildDir = resolve(__dirname, '.nuxt-lazy')
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, '..'),
buildDir,
srcDir: resolve(__dirname, 'fixture'),
modules: [
[
FirebaseModule,
{
injectModule: false,
lazy: true,
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
},
services: {
analytics: true,
auth: true,
firestore: true,
functions: true,
messaging: true,
performance: true,
database: true,
remoteConfig: true,
storage: true,
},
},
],
],
}
config.dev = false
nuxt = new Nuxt(config)
const BundleBuilder = { build: (_) => _ }
const builder = new Builder(nuxt, BundleBuilder)
await builder.build()
}, 60000)
afterAll(async () => {
await nuxt.close()
})
test('plugin contents', async () => {
const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), {
encoding: 'utf8',
})
expect(content).toContain('fire.auth = null')
expect(content).toContain('fire.messaging = null')
expect(content).not.toContain('Mess')
expect(content).toMatchSnapshot()
})
test('exec plugin (server)', async () => {
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(1)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeUndefined()
expect(ctx.$fire.appReady).toBeDefined()
// TODO: test the appReady call. Doesnt work atm due to Jest not detecting
// a async callback in the session var. Not fully sure whats happening
// const app = await ctx.$fire.appReady()
})
test('exec plugin (client)', async () => {
process.client = true
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(1)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeUndefined()
})
})
================================================
FILE: packages/firebase-module/test/with-module.test.js
================================================
const { resolve } = require('path')
const fs = require('fs-extra')
const { Nuxt, Builder } = require('nuxt')
const FirebaseModule = require('..')
jest.mock('firebase/compat/app', () => ({
apps: [
new Proxy(
{},
{
get(target, name) {
return jest.fn(() => ({}))
},
}
),
],
messaging: {
isSupported: jest.fn(),
},
}))
describe('with-module', () => {
let nuxt
const buildDir = resolve(__dirname, '.nuxt-with-module')
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, '..'),
buildDir,
srcDir: resolve(__dirname, 'fixture'),
modules: [
[
FirebaseModule,
{
injectModule: true,
config: {
// REQUIRED: Official config for firebase.initializeApp(config):
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
},
services: {
analytics: true,
auth: true,
firestore: true,
functions: true,
messaging: true,
performance: true,
database: true,
remoteConfig: true,
storage: true,
},
},
],
],
}
config.dev = false
nuxt = new Nuxt(config)
const BundleBuilder = { build: (_) => _ }
const builder = new Builder(nuxt, BundleBuilder)
await builder.build()
}, 60000)
afterAll(async () => {
await nuxt.close()
})
test('plugin contents', async () => {
const content = await fs.readFile(resolve(buildDir, 'firebase/index.js'), {
encoding: 'utf8',
})
expect(content).toContain('auth,')
expect(content).toContain('messaging,')
expect(content).toContain('firebase')
expect(content).not.toContain('Mess')
expect(content).toMatchSnapshot()
})
test('exec plugin (server)', async () => {
process.server = true
process.client = false
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(2)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeDefined()
})
test('exec plugin (client)', async () => {
process.server = false
process.client = true
const Plugin = await import(resolve(buildDir, 'firebase/index.js')).then(
(m) => m.default || m
)
const ctx = {}
const inject = jest.fn()
await Plugin(ctx, inject)
expect(inject).toHaveBeenCalledTimes(2)
expect(ctx.$fire).toBeDefined()
expect(ctx.$fireModule).toBeDefined()
})
})
================================================
FILE: packages/firebase-module/types/index.d.ts
================================================
import { ServerResponse } from 'http'
import { Vue } from 'vue/types/vue'
import { NuxtAppOptions, Configuration } from '@nuxt/types'
import { NuxtConfiguration } from '@nuxt/vue-app'
import { ServiceAccount } from 'firebase-admin'
import firebase from 'firebase/compat'
import { auth } from 'firebase-admin'
/***********************************
* Module Config
************************************/
export interface FirebaseConfiguration {
apiKey: string
authDomain: string
databaseURL?: string
projectId: string
storageBucket: string
messagingSenderId: string
appId: string
measurementId: string
}
interface ServiceConfig {
static?: boolean
preload?: boolean
chunkName?: string
}
interface messagingAction {
action: string
url?: string
}
export interface AuthServiceConfig extends ServiceConfig {
persistence?: firebase.auth.Auth.Persistence
initialize?: {
onAuthStateChangedMutation?: string
onAuthStateChangedAction?: string
onIdTokenChangedMutation?: string
onIdTokenChangedAction?: string
subscribeManually?: boolean
}
ssr?:
| boolean
| {
credential: string | ServiceAccount | true
serverLogin?:
| boolean
| {
sessionLifetime?: number
loginDelay?: number
}
ignorePaths?: (string | RegExp)[]
}
emulatorPort?: number
emulatorHost?: string
disableEmulatorWarnings?: boolean
}
export interface FirestoreServiceConfig extends ServiceConfig {
memoryOnly?: boolean
enablePersistence?:
| boolean
| {
synchronizeTabs: boolean
}
emulatorPort?: number
emulatorHost?: string
settings?: firebase.firestore.Settings
}
export interface FunctionsServiceConfig extends ServiceConfig {
location?: string
emulatorPort?: number
emulatorHost?: string
}
export interface StorageServiceConfig extends ServiceConfig {
emulatorPort?: number
emulatorHost?: string
}
export interface DatabaseServiceConfig extends ServiceConfig {
emulatorPort?: number
emulatorHost?: string
}
export interface MessagingServiceConfig extends ServiceConfig {
createServiceWorker?:
| boolean
| {
notification: {
title: string
body: string
image: string
vibrate: number[]
clickPath: string
}
}
actions?: messagingAction[]
fcmPublicVapidKey?: string
inject?: string
}
export interface PerformanceServiceConfig extends ServiceConfig {}
export interface AppCheckServiceConfig extends ServiceConfig {
debugToken?: string | boolean
}
export interface AnalyticsServiceConfig extends ServiceConfig {
collectionEnabled?: boolean
}
export interface RemoteConfigServiceConfig extends ServiceConfig {
settings?: {
fetchTimeoutMillis?: number
minimumFetchIntervalMillis?: number
}
defaultConfig?: Record
}
export interface FirebaseModuleConfiguration {
injectModule?: boolean
lazy?: boolean
config:
| {
[envKey: string]: FirebaseConfiguration
}
| FirebaseConfiguration
services: {
auth?: boolean | AuthServiceConfig
firestore?: boolean | FirestoreServiceConfig
functions?: boolean | FunctionsServiceConfig
storage?: boolean | StorageServiceConfig
database?: boolean | DatabaseServiceConfig
messaging?: boolean | MessagingServiceConfig
performance?: boolean | PerformanceServiceConfig
appCheck?: boolean | AppCheckServiceConfig
analytics?: boolean | AnalyticsServiceConfig
remoteConfig?: boolean | RemoteConfigServiceConfig
}
customEnv?: boolean
onFirebaseHosting?: boolean | object
terminateDatabasesAfterGenerate?: boolean
}
/***********************************
* Injections
************************************/
interface ReadyFunction {
(): void
}
interface NuxtFireInstance {
auth: firebase.auth.Auth
authReady: ReadyFunction
database: firebase.database.Database
databaseReady: ReadyFunction
firestore: firebase.firestore.Firestore
firestoreReady: ReadyFunction
functions: firebase.functions.Functions
functionsReady: ReadyFunction
storage: firebase.storage.Storage
storageReady: ReadyFunction
messaging: firebase.messaging.Messaging
messagingReady: ReadyFunction
performance: firebase.performance.Performance
performanceReady: ReadyFunction
appCheck: firebase.appCheck.AppCheck
appCheckReady: ReadyFunction
analytics: firebase.analytics.Analytics
analyticsReady: ReadyFunction
remoteConfig: firebase.remoteConfig.RemoteConfig
remoteConfigReady: ReadyFunction
}
interface NuxtFireAuthStore {
subscribe: () => Promise
unsubscribe: () => void
}
declare module '@nuxt/vue-app' {
interface NuxtConfiguration {
firebase?: FirebaseModuleConfiguration
}
interface Context {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
interface NuxtAppOptions {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
}
declare module '@nuxt/types' {
interface Context {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
interface NuxtAppOptions {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
interface Configuration {
firebase?: FirebaseModuleConfiguration
}
}
declare module 'vue/types/vue' {
interface Vue {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
}
declare module '@nuxt/vue-app' {
interface NuxtAppOptions {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
}
declare module 'vuex/types/index' {
interface Store {
$fireModule: typeof firebase
$fire: NuxtFireInstance
$fireAuthStore: NuxtFireAuthStore
}
}
/***********************************
* Misc
************************************/
export type FireAuthServerUser = Omit<
auth.UserRecord,
'disabled' | 'metadata' | 'providerData'
> &
Partial> & {
allClaims: auth.DecodedIdToken
idToken: string
}
declare module 'http' {
interface ServerResponse {
locals: Record<'user', FireAuthServerUser> & Record
}
}