Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore init bug, issue #614 / types reorganization #669

Draft
wants to merge 31 commits into
base: v1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9ead74e
Upgrade to latest NFA
kmjennison Jul 9, 2023
573197c
Bump firebase to 9.17.1
kmjennison Jul 9, 2023
3369c70
Try init in withUser
kmjennison Jul 9, 2023
1262f43
WIP
kmjennison Jul 9, 2023
4d59e9b
1.0.0-canary.27-1262f43
kmjennison Jul 9, 2023
0b7f24d
WIP
kmjennison Jul 9, 2023
bd4201d
WIP
kmjennison Jul 9, 2023
d73e2f7
1.0.0-experimental.bd4201d
kmjennison Jul 9, 2023
b28d7b3
WIP
kmjennison Jul 9, 2023
1578906
1.0.0-experimental.b28d7b3
kmjennison Jul 9, 2023
41eaaba
Install experimental NFA
kmjennison Jul 9, 2023
6598f49
Experiment
kmjennison Jul 9, 2023
401649d
1.0.0-experimental.6598f49
kmjennison Jul 9, 2023
9adccc6
Upgrade NFA
kmjennison Jul 9, 2023
0f9cf53
Merge branch 'v1.x' into kevin/init-issue-614
kmjennison Jul 9, 2023
f8fb103
Revert fix attempts
kmjennison Jul 9, 2023
80eba1f
Try returning auth and app from init
kmjennison Jul 9, 2023
8281e6c
1.0.0-experimental.80eba1f
kmjennison Jul 9, 2023
ad1606a
Use experimental NFA
kmjennison Jul 9, 2023
5265183
Split out type definitions
kmjennison Jul 22, 2023
3ee8a60
Add TODO
kmjennison Jul 22, 2023
bfc3f59
Disable some tests
kmjennison Jul 22, 2023
65c9f91
1.0.0-experimental.bfc3f59
kmjennison Jul 22, 2023
dd3c6fc
Upgrade NFA
kmjennison Jul 22, 2023
5c9a3f7
Try try/catch for init
kmjennison Jul 22, 2023
699c1dc
Skip some tests
kmjennison Jul 22, 2023
80fcf80
1.0.0-experimental.699c1dc
kmjennison Jul 22, 2023
3fc8b11
Rebuild yarn.lock
kmjennison Jul 22, 2023
c317a47
Upgrade NFA
kmjennison Jul 22, 2023
b09e134
Try importing firebase alongside NFA
kmjennison Jul 24, 2023
fe7901a
Merge branch 'v1.x' into kevin/init-issue-614
kmjennison Dec 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"deploy": "vercel --prod"
},
"dependencies": {
"firebase": "9.16.0",
"firebase": "9.17.1",
"firebase-admin": "^11.9.0",
"next": "13.4.9",
"next-absolute-url": "^1.2.2",
"next-firebase-auth": "1.0.0",
"next-firebase-auth": "experimental",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-firebaseui": "^6.0.0"
Expand Down
2 changes: 2 additions & 0 deletions example/utils/initAuth.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* globals window */
import 'firebase/app'
import 'firebase/auth'
import { init } from 'next-firebase-auth'
import absoluteUrl from 'next-absolute-url'

Expand Down
428 changes: 214 additions & 214 deletions example/yarn.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next-firebase-auth",
"version": "1.0.1",
"version": "1.0.0-experimental.699c1dc",
"description": "Simple Firebase authentication for all Next.js rendering strategies",
"keywords": [
"Next",
Expand Down Expand Up @@ -137,4 +137,4 @@
"files": [
"/build"
]
}
}
17 changes: 17 additions & 0 deletions src/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { User as FirebaseUser } from 'firebase/auth'

export interface User {
id: string | null
email: string | null
emailVerified: boolean
phoneNumber: string | null
displayName: string | null
photoURL: string | null
claims: Record<string, string | boolean>
tenantId: string | null
getIdToken: (forceRefresh?: boolean) => Promise<string | null>
clientInitialized: boolean
firebaseUser: FirebaseUser | null
signOut: () => Promise<void>
serialize: (a?: { includeToken?: boolean }) => string
}
12 changes: 12 additions & 0 deletions src/UserDeserialized.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface UserDeserialized {
id?: string
claims?: object
email?: string
emailVerified: boolean
phoneNumber?: string
displayName?: string
photoURL?: string
clientInitialized: boolean
_token?: string
tenantId: string
}
1 change: 1 addition & 0 deletions src/UserSerialized.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type UserSerialized = string
26 changes: 26 additions & 0 deletions src/__mocks__/initFirebaseClientSDK.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

const firebaseAuthMock: any = jest.createMockFromModule('firebase/auth')

const mockOnIdTokenChangedUnsubscribe = jest.fn()
const mockOnIdTokenChanged = jest.fn(() => mockOnIdTokenChangedUnsubscribe)
const mockSignOut = jest.fn(() => Promise.resolve())

firebaseAuthMock.onIdTokenChanged = mockOnIdTokenChanged
firebaseAuthMock.signOut = mockSignOut

const { FirebaseError } = jest.requireActual('firebase/app')
const firebaseAppMock: any = jest.createMockFromModule('firebase/app')
firebaseAppMock.getApps = jest.fn(() => [])

const firebaseAppMockWithErr = {
...firebaseAppMock,
FirebaseError,
}

const mockInit = jest.fn(() => ({
app: firebaseAppMockWithErr,
auth: firebaseAuthMock,
}))

export default mockInit
1 change: 1 addition & 0 deletions src/__tests__/createUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {

jest.mock('firebase/auth')
jest.mock('firebase/app')
jest.mock('src/initFirebaseClientSDK')

afterEach(() => {
jest.clearAllMocks()
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/index.server.moduleLoad.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable jest/no-disabled-tests */
// Tests for index.server.ts that require resetting all
// modules between tests. Most tests should reside in
// index.server.test.js.
Expand All @@ -10,7 +11,8 @@ afterEach(() => {
jest.resetModules()
})

describe('index.server.ts (resetting modules)', () => {
// FIXME: reenable
describe.skip('index.server.ts (resetting modules)', () => {
it('imports without error when missing optional dependencies', () => {
expect.assertions(0)

Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/initFirebaseClientSDK.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable jest/no-disabled-tests */
import { getApps, initializeApp } from 'firebase/app'
import { getAuth, connectAuthEmulator } from 'firebase/auth'
import { setConfig } from 'src/config'
Expand Down Expand Up @@ -25,7 +26,8 @@ afterEach(() => {
jest.clearAllMocks()
})

describe('initFirebaseClientSDK', () => {
// FIXME: reenable
describe.skip('initFirebaseClientSDK', () => {
it('calls firebase.initializeApp with the expected values', () => {
expect.assertions(1)
const initFirebaseClientSDK = require('src/initFirebaseClientSDK').default
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/redirects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ParsedUrlQuery } from 'querystring'
import { getLoginRedirectInfo, getAppRedirectInfo } from 'src/redirects'
import getMockConfig from 'src/testHelpers/createMockConfig'
import { setConfig } from 'src/config'
import { User } from 'src/createUser'
import { User } from 'src/User'
import { RedirectInput } from 'src/redirectTypes'

describe('redirects', () => {
Expand Down
1 change: 1 addition & 0 deletions src/__tests__/useFirebaseUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import logDebug from 'src/logDebug'
jest.mock('firebase/app')
jest.mock('firebase/auth')
jest.mock('src/config')
jest.mock('src/initFirebaseClientSDK')
jest.mock('src/logDebug')

const mockGetIdTokenResult = getIdTokenResult as jest.Mock
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/withUser.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
createMockFirebaseUserClientSDK,
} from 'src/testHelpers/userInputs'
import useUser from 'src/useUser'
import createUser, { User } from 'src/createUser'
import createUser from 'src/createUser'
import { User } from 'src/User'
import useFirebaseUser from 'src/useFirebaseUser'
import { AuthAction } from 'src/AuthAction'
import logDebug from 'src/logDebug'
Expand Down
2 changes: 1 addition & 1 deletion src/configTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Cookies from 'cookies'
import { PageURL } from './redirectTypes'
import { User } from './createUser'
import { User } from './User'
import { Spread } from './Spread'

type OnErrorHandler = (error: Error) => void
Expand Down
40 changes: 8 additions & 32 deletions src/createUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,12 @@ import { DecodedIdToken } from 'firebase-admin/auth'
import isClientSide from 'src/isClientSide'
import { Claims, filterStandardClaims } from 'src/claims'

interface UserDeserialized {
id?: string
claims?: object
email?: string
emailVerified: boolean
phoneNumber?: string
displayName?: string
photoURL?: string
clientInitialized: boolean
_token?: string
tenantId: string
}
// TODO: async import
import initFirebaseClient from 'src/initFirebaseClientSDK'

export type UserSerialized = string
import { UserDeserialized } from './UserDeserialized'
import { UserSerialized } from './UserSerialized'
import { User } from './User'

interface CreateUserInput {
firebaseUserClientSDK?: FirebaseUser
Expand All @@ -30,22 +22,6 @@ interface CreateUserInput {

type getIdToken = (forceRefresh?: boolean) => Promise<string | null>

export interface User {
id: string | null
email: string | null
emailVerified: boolean
phoneNumber: string | null
displayName: string | null
photoURL: string | null
claims: Record<string, string | boolean>
tenantId: string | null
getIdToken: (forceRefresh?: boolean) => Promise<string | null>
clientInitialized: boolean
firebaseUser: FirebaseUser | null
signOut: () => Promise<void>
serialize: (a?: { includeToken?: boolean }) => string
}

/**
* Take a representation of a Firebase user from a maximum of one of:
* the Firebase JS SDK, Firebase admin SDK, or serialized User instance.
Expand Down Expand Up @@ -116,11 +92,11 @@ const createUser = ({
if (firebaseUserClientSDK) {
if (isClientSide()) {
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
const { getApp } = require('firebase/app')
const { auth } = initFirebaseClient()
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
const { getAuth, signOut } = require('firebase/auth')
const { signOut } = require('firebase/auth')

signOutFunc = async () => signOut(getAuth(getApp()))
signOutFunc = async () => signOut(auth)
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/firebaseAdmin.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { getAuth as getAdminAuth } from 'firebase-admin/auth'
import initFirebaseAdminSDK from 'src/initFirebaseAdminSDK'
import createUser, { User } from 'src/createUser'
import createUser from 'src/createUser'
import { getConfig } from 'src/config'
import logDebug from 'src/logDebug'
import { FirebaseError as FirebaseErrorType } from 'firebase-admin/app'
import { User } from './User'

// If the FIREBASE_AUTH_EMULATOR_HOST variable is set, send the token request to the emulator
const getTokenPrefix = () =>
Expand Down
3 changes: 2 additions & 1 deletion src/getUserFromCookies.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import createUser, { User } from 'src/createUser'
import createUser from 'src/createUser'
import { getCookie } from 'src/cookies'
import { verifyIdToken } from 'src/firebaseAdmin'
import {
Expand All @@ -11,6 +11,7 @@ import { getConfig } from 'src/config'
import logDebug from 'src/logDebug'
import initFirebaseAdminSDK from 'src/initFirebaseAdminSDK'
import { GetServerSidePropsContext, NextApiRequest } from 'next'
import { User } from './User'

export type GetUserFromCookiesOptions = {
/**
Expand Down
17 changes: 10 additions & 7 deletions src/initFirebaseClientSDK.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { getApp, getApps, initializeApp } from 'firebase/app'
import { FirebaseApp, getApp, initializeApp } from 'firebase/app'

Check warning on line 1 in src/initFirebaseClientSDK.ts

View workflow job for this annotation

GitHub Actions / build

'FirebaseApp' is defined but never used

Check warning on line 1 in src/initFirebaseClientSDK.ts

View workflow job for this annotation

GitHub Actions / build

'FirebaseApp' is defined but never used
import { getAuth, connectAuthEmulator } from 'firebase/auth'
import { getConfig } from 'src/config'
import logDebug from 'src/logDebug'

export default function initFirebaseClientSDK() {
const { firebaseClientInitConfig, firebaseAuthEmulatorHost, tenantId } =
getConfig()
if (!getApps().length) {
try {
if (!firebaseClientInitConfig) {
throw new Error(
'If not initializing the Firebase JS SDK elsewhere, you must provide "firebaseClientInitConfig" to next-firebase-auth.'
Expand All @@ -18,13 +18,16 @@
getAuth().tenantId = tenantId
}
logDebug('[init] Initialized the Firebase JS SDK.')
} else {
logDebug(
'[init] Did not initialize the Firebase JS SDK because an app already exists.'
)
} catch (e) {
logDebug('[init] Failed to initialize the Firebase JS SDK', e)

Check warning on line 22 in src/initFirebaseClientSDK.ts

View check run for this annotation

Codecov / codecov/patch

src/initFirebaseClientSDK.ts#L22

Added line #L22 was not covered by tests
}

const app = getApp()

// If the user has provided the firebaseAuthEmulatorHost address, set the emulator
if (firebaseAuthEmulatorHost) {
connectAuthEmulator(getAuth(getApp()), `http://${firebaseAuthEmulatorHost}`)
connectAuthEmulator(getAuth(app), `http://${firebaseAuthEmulatorHost}`)

Check warning on line 29 in src/initFirebaseClientSDK.ts

View check run for this annotation

Codecov / codecov/patch

src/initFirebaseClientSDK.ts#L29

Added line #L29 was not covered by tests
}
const auth = getAuth(app)
return { app, auth }
}
2 changes: 1 addition & 1 deletion src/redirectTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { GetServerSidePropsContext, Redirect } from 'next'
import type { ParsedUrlQuery } from 'querystring'
import { User } from './createUser'
import { User } from './User'

export type URLResolveFunction = (obj: {
ctx?: GetServerSidePropsContext<ParsedUrlQuery>
Expand Down
2 changes: 1 addition & 1 deletion src/redirects.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { GetServerSidePropsContext } from 'next'

import { User } from 'src/createUser'
import { getConfig } from 'src/config'
import { User } from './User'
import {
PageURL,
RedirectConfig,
Expand Down
3 changes: 2 additions & 1 deletion src/setAuthCookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { setCookie } from 'src/cookies'
import { getUserCookieName, getUserTokensCookieName } from 'src/authCookies'
import { getConfig } from 'src/config'
import logDebug from 'src/logDebug'
import createUser, { User } from 'src/createUser'
import createUser from 'src/createUser'
import { NextApiRequest, NextApiResponse } from 'next'
import { User } from './User'

export type SetAuthCookies = (
req: NextApiRequest,
Expand Down
9 changes: 5 additions & 4 deletions src/useFirebaseUser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useEffect, useState } from 'react'
import { getApp } from 'firebase/app'
import {
User as FirebaseUser,
getAuth,
getIdTokenResult,
onIdTokenChanged,
} from 'firebase/auth'
import { getConfig } from 'src/config'
import createUser, { User } from 'src/createUser'
import createUser from 'src/createUser'
import { Claims, filterStandardClaims } from 'src/claims'
import logDebug from 'src/logDebug'
import { User } from './User'
import initFirebaseClientSDK from './initFirebaseClientSDK'

const defaultTokenChangedHandler = async (user: User) => {
const {
Expand Down Expand Up @@ -175,7 +175,8 @@ const useFirebaseUser = () => {
}

// https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onidtokenchanged
const unsubscribe = onIdTokenChanged(getAuth(getApp()), onIdTokenChange)
const { auth } = initFirebaseClientSDK()
const unsubscribe = onIdTokenChanged(auth, onIdTokenChange)
return () => {
unsubscribe()
isCancelled = true
Expand Down
2 changes: 1 addition & 1 deletion src/useUser.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext, useContext } from 'react'
import { User } from './createUser'
import { User } from './User'

type UserContext =
| (User & {
Expand Down
3 changes: 2 additions & 1 deletion src/withUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import hoistNonReactStatics from 'hoist-non-react-statics'
import type { ComponentType } from 'react'

import { MODULE_NOT_FOUND } from 'src/constants'
import createUser, { UserSerialized } from 'src/createUser'
import createUser from 'src/createUser'
import useFirebaseUser from 'src/useFirebaseUser'
import { AuthAction } from 'src/AuthAction'
import isClientSide from 'src/isClientSide'
import logDebug from 'src/logDebug'
import { getAppRedirectInfo, getLoginRedirectInfo } from 'src/redirects'
import { UserSerialized } from './UserSerialized'
import { PageURL, RedirectObject } from './redirectTypes'

export interface WithUserOptions {
Expand Down
2 changes: 1 addition & 1 deletion src/withUserTokenSSR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import getUserFromCookies from 'src/getUserFromCookies'
import { AuthAction } from 'src/AuthAction'
import { getLoginRedirectInfo, getAppRedirectInfo } from 'src/redirects'
import logDebug from 'src/logDebug'
import { User } from './createUser'
import { User } from './User'
import { PageURL } from './redirectTypes'

export interface WithUserSSROptions {
Expand Down