Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@propelauth/react

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@propelauth/react - npm Package Compare versions

Comparing version 1.2.4 to 1.2.5

dist/types/withRequiredAuthInfo.d.ts

626

dist/index.cjs.js

@@ -394,281 +394,2 @@ 'use strict';

const AuthContext = /*#__PURE__*/React__default["default"].createContext(undefined);
const initialAuthInfoState = {
loading: true,
authInfo: null
};
function authInfoStateReducer(_state, action) {
return {
loading: false,
authInfo: action.authInfo
};
}
const AuthProvider = props => {
const [authInfoState, dispatch] = React.useReducer(authInfoStateReducer, initialAuthInfoState);
const [heartbeatCounter, setHeartbeatCounter] = React.useState(0);
const [userSelectedOrgId, setUserSelectedOrgId] = React.useState(null);
const triggerRefreshAuthentication = () => setHeartbeatCounter(x => x + 1); // Create client and register observer
const client = React.useMemo(() => {
// Disable background token refresh as we will do it within React instead
const client = createClient({
authUrl: props.authUrl,
enableBackgroundTokenRefresh: false
});
client.addLoggedInChangeObserver(triggerRefreshAuthentication);
return client;
}, [props.authUrl]); // On unmount, destroy the client
React.useEffect(() => {
return () => {
client.destroy();
};
}, []); // Periodically refresh the token. The client will only make requests when the authInfo is stale
// Errors are logged and the token will be invalidated separately
React.useEffect(() => {
let didCancel = false;
async function refreshToken() {
try {
const authInfo = await client.getAuthenticationInfoOrNull();
if (!didCancel) {
dispatch({
authInfo
});
}
} catch (err) {
console.error("Authentication error", err);
}
}
refreshToken();
return () => {
didCancel = true;
};
}, [client, heartbeatCounter]);
React.useEffect(() => {
const interval = setInterval(triggerRefreshAuthentication, 60000);
return () => clearInterval(interval);
}, []); // Watchdog timer to make sure that if we hit the expiration we get rid of the token.
// This should only be triggered if we are unable to get a new token due to an unexpected error/network timeouts.
const expiresAtSeconds = authInfoState.authInfo ? authInfoState.authInfo.expiresAtSeconds : 0;
React.useEffect(() => {
if (!authInfoState.authInfo) {
return;
}
const millisUntilTokenExpires = getMillisUntilTokenExpires(authInfoState.authInfo.expiresAtSeconds);
const timeout = setTimeout(() => {
dispatch({
authInfo: null
});
}, millisUntilTokenExpires);
return () => clearTimeout(timeout);
}, [expiresAtSeconds]);
const logout = React.useCallback(client.logout, []);
const redirectToLoginPage = React.useCallback(client.redirectToLoginPage, []);
const redirectToSignupPage = React.useCallback(client.redirectToSignupPage, []);
const redirectToAccountPage = React.useCallback(client.redirectToAccountPage, []);
const redirectToOrgPage = React.useCallback(client.redirectToOrgPage, []);
const redirectToCreateOrgPage = React.useCallback(client.redirectToCreateOrgPage, []);
const value = {
loading: authInfoState.loading,
triggerRefreshAuthentication,
authInfo: authInfoState.authInfo,
logout,
userSelectedOrgId,
selectOrgId: setUserSelectedOrgId,
redirectToLoginPage,
redirectToSignupPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
return /*#__PURE__*/React__default["default"].createElement(AuthContext.Provider, {
value: value
}, props.children);
};
function getMillisUntilTokenExpires(expiresAtSeconds) {
let millisUntilTokenExpires = expiresAtSeconds * 1000 - Date.now();
return Math.max(0, millisUntilTokenExpires);
}
function getOrgHelper(orgIdToOrgMemberInfo, selectOrgId, userSelectedOrgId) {
return {
getOrg(orgId) {
if (orgIdToOrgMemberInfo.hasOwnProperty(orgId)) {
return orgIdToOrgMemberInfo[orgId];
} else {
return undefined;
}
},
getOrgIds() {
return Object.keys(orgIdToOrgMemberInfo);
},
getOrgs() {
return Object.values(orgIdToOrgMemberInfo);
},
getSelectedOrg(inferDefault) {
// default for inferDefault is true
inferDefault = inferDefault === undefined ? true : inferDefault; // if the user has selected an org already, return it
if (userSelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(userSelectedOrgId)) {
return orgIdToOrgMemberInfo[userSelectedOrgId];
} else if (!inferDefault) {
return undefined;
} // otherwise, infer it from local storage
const previouslySelectedOrgId = loadOrgSelectionFromLocalStorage();
if (previouslySelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(previouslySelectedOrgId)) {
return orgIdToOrgMemberInfo[previouslySelectedOrgId];
} // if the user has never selected one before, select one deterministically by name
let alphabeticallyFirstOrgName = undefined;
let alphabeticallyFirstOrg = undefined;
for (let org of this.getOrgs()) {
if (!alphabeticallyFirstOrgName || org.orgName < alphabeticallyFirstOrgName) {
alphabeticallyFirstOrgName = org.orgName;
alphabeticallyFirstOrg = org;
}
}
return alphabeticallyFirstOrg;
},
selectOrg(orgId) {
selectOrgId(orgId);
saveOrgSelectionToLocalStorage(orgId);
},
getNotSelectedOrgs(inferDefault) {
const selectedOrg = this.getSelectedOrg(inferDefault);
if (selectedOrg) {
return this.getOrgs().filter(org => org.orgId !== selectedOrg.orgId);
} else {
return this.getOrgs();
}
}
};
}
const ORG_SELECTION_LOCAL_STORAGE_KEY = "__last_selected_org";
function saveOrgSelectionToLocalStorage(orgId) {
if (localStorage) {
localStorage.setItem(ORG_SELECTION_LOCAL_STORAGE_KEY, orgId);
}
}
function loadOrgSelectionFromLocalStorage() {
if (localStorage) {
return localStorage.getItem(ORG_SELECTION_LOCAL_STORAGE_KEY);
}
return null;
}
function useAuthInfo() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuthInfo must be used within an AuthProvider");
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return {
loading: true
};
} else if (authInfo && authInfo.accessToken) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
return {
loading: false,
isLoggedIn: true,
accessToken: authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
}
return {
loading: false,
isLoggedIn: false,
accessToken: null,
orgHelper: null,
user: null
};
}
function useLogoutFunction() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useLogoutFunction must be used within an AuthProvider");
}
const {
logout
} = context;
return logout;
}
function useRedirectFunctions() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useRedirectFunctions must be used within an AuthProvider");
}
const {
redirectToAccountPage,
redirectToSignupPage,
redirectToLoginPage,
redirectToOrgPage,
redirectToCreateOrgPage
} = context;
return {
redirectToSignupPage,
redirectToLoginPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
}
function RedirectToSignup(props) {
const {
redirectToSignupPage
} = useRedirectFunctions();
redirectToSignupPage();
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
}
function RedirectToLogin(props) {
const {
redirectToLoginPage
} = useRedirectFunctions();
redirectToLoginPage();
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
}
function createCommonjsModule(fn) {

@@ -1016,2 +737,345 @@ var module = { exports: {} };

function getOrgHelper(orgIdToOrgMemberInfo, selectOrgId, userSelectedOrgId) {
return {
getOrg(orgId) {
if (orgIdToOrgMemberInfo.hasOwnProperty(orgId)) {
return orgIdToOrgMemberInfo[orgId];
} else {
return undefined;
}
},
getOrgIds() {
return Object.keys(orgIdToOrgMemberInfo);
},
getOrgs() {
return Object.values(orgIdToOrgMemberInfo);
},
getSelectedOrg(inferDefault) {
// default for inferDefault is true
inferDefault = inferDefault === undefined ? true : inferDefault; // if the user has selected an org already, return it
if (userSelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(userSelectedOrgId)) {
return orgIdToOrgMemberInfo[userSelectedOrgId];
} else if (!inferDefault) {
return undefined;
} // otherwise, infer it from local storage
const previouslySelectedOrgId = loadOrgSelectionFromLocalStorage();
if (previouslySelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(previouslySelectedOrgId)) {
return orgIdToOrgMemberInfo[previouslySelectedOrgId];
} // if the user has never selected one before, select one deterministically by name
let alphabeticallyFirstOrgName = undefined;
let alphabeticallyFirstOrg = undefined;
for (let org of this.getOrgs()) {
if (!alphabeticallyFirstOrgName || org.orgName < alphabeticallyFirstOrgName) {
alphabeticallyFirstOrgName = org.orgName;
alphabeticallyFirstOrg = org;
}
}
return alphabeticallyFirstOrg;
},
selectOrg(orgId) {
selectOrgId(orgId);
saveOrgSelectionToLocalStorage(orgId);
},
getNotSelectedOrgs(inferDefault) {
const selectedOrg = this.getSelectedOrg(inferDefault);
if (selectedOrg) {
return this.getOrgs().filter(org => org.orgId !== selectedOrg.orgId);
} else {
return this.getOrgs();
}
}
};
}
const ORG_SELECTION_LOCAL_STORAGE_KEY = "__last_selected_org";
function saveOrgSelectionToLocalStorage(orgId) {
if (localStorage) {
localStorage.setItem(ORG_SELECTION_LOCAL_STORAGE_KEY, orgId);
}
}
function loadOrgSelectionFromLocalStorage() {
if (localStorage) {
return localStorage.getItem(ORG_SELECTION_LOCAL_STORAGE_KEY);
}
return null;
}
function useRedirectFunctions() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useRedirectFunctions must be used within an AuthProvider or RequiredAuthProvider");
}
const {
redirectToAccountPage,
redirectToSignupPage,
redirectToLoginPage,
redirectToOrgPage,
redirectToCreateOrgPage
} = context;
return {
redirectToSignupPage,
redirectToLoginPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
}
function RedirectToSignup(props) {
const {
redirectToSignupPage
} = useRedirectFunctions();
redirectToSignupPage();
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
}
function RedirectToLogin(props) {
const {
redirectToLoginPage
} = useRedirectFunctions();
redirectToLoginPage();
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
}
function withRequiredAuthInfo(Component, args) {
const displayName = `withRequiredAuthInfo(${Component.displayName || Component.name || "Component"})`;
const WithRequiredAuthInfoWrapper = props => {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("withRequiredAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}
function displayLoading() {
if (args && args.displayWhileLoading) {
return args.displayWhileLoading;
} else {
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null);
}
}
function displayLoggedOut() {
if (args && args.displayIfLoggedOut) {
return args.displayIfLoggedOut;
} else {
return /*#__PURE__*/React__default["default"].createElement(RedirectToLogin, null);
}
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return displayLoading();
} else if (authInfo) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
const loggedInProps = { ...props,
accessToken: authInfo.accessToken,
isLoggedIn: !!authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
return /*#__PURE__*/React__default["default"].createElement(Component, loggedInProps);
} else {
return displayLoggedOut();
}
};
WithRequiredAuthInfoWrapper.displayName = displayName;
WithRequiredAuthInfoWrapper.WrappedComponent = Component;
return hoistNonReactStatics_cjs(WithRequiredAuthInfoWrapper, Component);
}
const AuthContext = /*#__PURE__*/React__default["default"].createContext(undefined);
const initialAuthInfoState = {
loading: true,
authInfo: null
};
function authInfoStateReducer(_state, action) {
return {
loading: false,
authInfo: action.authInfo
};
}
const AuthProvider = props => {
const [authInfoState, dispatch] = React.useReducer(authInfoStateReducer, initialAuthInfoState);
const [heartbeatCounter, setHeartbeatCounter] = React.useState(0);
const [userSelectedOrgId, setUserSelectedOrgId] = React.useState(null);
const triggerRefreshAuthentication = () => setHeartbeatCounter(x => x + 1); // Create client and register observer
const client = React.useMemo(() => {
// Disable background token refresh as we will do it within React instead
const client = createClient({
authUrl: props.authUrl,
enableBackgroundTokenRefresh: false
});
client.addLoggedInChangeObserver(triggerRefreshAuthentication);
return client;
}, [props.authUrl]); // On unmount, destroy the client
React.useEffect(() => {
return () => {
client.destroy();
};
}, []); // Periodically refresh the token. The client will only make requests when the authInfo is stale
// Errors are logged and the token will be invalidated separately
React.useEffect(() => {
let didCancel = false;
async function refreshToken() {
try {
const authInfo = await client.getAuthenticationInfoOrNull();
if (!didCancel) {
dispatch({
authInfo
});
}
} catch (_) {// Exceptions are logged in the JS library
}
}
refreshToken();
return () => {
didCancel = true;
};
}, [client, heartbeatCounter]);
React.useEffect(() => {
const interval = setInterval(triggerRefreshAuthentication, 60000);
return () => clearInterval(interval);
}, []); // Watchdog timer to make sure that if we hit the expiration we get rid of the token.
// This should only be triggered if we are unable to get a new token due to an unexpected error/network timeouts.
const expiresAtSeconds = authInfoState.authInfo ? authInfoState.authInfo.expiresAtSeconds : 0;
React.useEffect(() => {
if (!authInfoState.authInfo) {
return;
}
const millisUntilTokenExpires = getMillisUntilTokenExpires(authInfoState.authInfo.expiresAtSeconds);
const timeout = setTimeout(() => {
dispatch({
authInfo: null
});
}, millisUntilTokenExpires);
return () => clearTimeout(timeout);
}, [expiresAtSeconds]);
const logout = React.useCallback(client.logout, []);
const redirectToLoginPage = React.useCallback(client.redirectToLoginPage, []);
const redirectToSignupPage = React.useCallback(client.redirectToSignupPage, []);
const redirectToAccountPage = React.useCallback(client.redirectToAccountPage, []);
const redirectToOrgPage = React.useCallback(client.redirectToOrgPage, []);
const redirectToCreateOrgPage = React.useCallback(client.redirectToCreateOrgPage, []);
const value = {
loading: authInfoState.loading,
triggerRefreshAuthentication,
authInfo: authInfoState.authInfo,
logout,
userSelectedOrgId,
selectOrgId: setUserSelectedOrgId,
redirectToLoginPage,
redirectToSignupPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
return /*#__PURE__*/React__default["default"].createElement(AuthContext.Provider, {
value: value
}, props.children);
};
const RequiredAuthProvider = props => {
const WrappedComponent = withRequiredAuthInfo(props => {
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
}, {
displayWhileLoading: props.displayWhileLoading,
displayIfLoggedOut: props.displayIfLoggedOut
});
return /*#__PURE__*/React__default["default"].createElement(AuthProvider, {
authUrl: props.authUrl
}, /*#__PURE__*/React__default["default"].createElement(WrappedComponent, props));
};
function getMillisUntilTokenExpires(expiresAtSeconds) {
let millisUntilTokenExpires = expiresAtSeconds * 1000 - Date.now();
return Math.max(0, millisUntilTokenExpires);
}
function useAuthInfo() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return {
loading: true
};
} else if (authInfo && authInfo.accessToken) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
return {
loading: false,
isLoggedIn: true,
accessToken: authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
}
return {
loading: false,
isLoggedIn: false,
accessToken: null,
orgHelper: null,
user: null
};
}
function useLogoutFunction() {
const context = React.useContext(AuthContext);
if (context === undefined) {
throw new Error("useLogoutFunction must be used within an AuthProvider or RequiredAuthProvider");
}
const {
logout
} = context;
return logout;
}
function withAuthInfo(Component, args) {

@@ -1024,3 +1088,3 @@ const displayName = `withAuthInfo(${Component.displayName || Component.name || "Component"})`;

if (context === undefined) {
throw new Error("withAuthInfo must be used within an AuthProvider");
throw new Error("withAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}

@@ -1073,2 +1137,3 @@

exports.RedirectToSignup = RedirectToSignup;
exports.RequiredAuthProvider = RequiredAuthProvider;
exports.useAuthInfo = useAuthInfo;

@@ -1078,2 +1143,3 @@ exports.useLogoutFunction = useLogoutFunction;

exports.withAuthInfo = withAuthInfo;
exports.withRequiredAuthInfo = withRequiredAuthInfo;
//# sourceMappingURL=index.cjs.js.map

@@ -1,2 +0,2 @@

import React, { useReducer, useState, useMemo, useEffect, useCallback, useContext } from 'react';
import React, { useContext, useReducer, useState, useMemo, useEffect, useCallback } from 'react';

@@ -386,281 +386,2 @@ let UserRole;

const AuthContext = /*#__PURE__*/React.createContext(undefined);
const initialAuthInfoState = {
loading: true,
authInfo: null
};
function authInfoStateReducer(_state, action) {
return {
loading: false,
authInfo: action.authInfo
};
}
const AuthProvider = props => {
const [authInfoState, dispatch] = useReducer(authInfoStateReducer, initialAuthInfoState);
const [heartbeatCounter, setHeartbeatCounter] = useState(0);
const [userSelectedOrgId, setUserSelectedOrgId] = useState(null);
const triggerRefreshAuthentication = () => setHeartbeatCounter(x => x + 1); // Create client and register observer
const client = useMemo(() => {
// Disable background token refresh as we will do it within React instead
const client = createClient({
authUrl: props.authUrl,
enableBackgroundTokenRefresh: false
});
client.addLoggedInChangeObserver(triggerRefreshAuthentication);
return client;
}, [props.authUrl]); // On unmount, destroy the client
useEffect(() => {
return () => {
client.destroy();
};
}, []); // Periodically refresh the token. The client will only make requests when the authInfo is stale
// Errors are logged and the token will be invalidated separately
useEffect(() => {
let didCancel = false;
async function refreshToken() {
try {
const authInfo = await client.getAuthenticationInfoOrNull();
if (!didCancel) {
dispatch({
authInfo
});
}
} catch (err) {
console.error("Authentication error", err);
}
}
refreshToken();
return () => {
didCancel = true;
};
}, [client, heartbeatCounter]);
useEffect(() => {
const interval = setInterval(triggerRefreshAuthentication, 60000);
return () => clearInterval(interval);
}, []); // Watchdog timer to make sure that if we hit the expiration we get rid of the token.
// This should only be triggered if we are unable to get a new token due to an unexpected error/network timeouts.
const expiresAtSeconds = authInfoState.authInfo ? authInfoState.authInfo.expiresAtSeconds : 0;
useEffect(() => {
if (!authInfoState.authInfo) {
return;
}
const millisUntilTokenExpires = getMillisUntilTokenExpires(authInfoState.authInfo.expiresAtSeconds);
const timeout = setTimeout(() => {
dispatch({
authInfo: null
});
}, millisUntilTokenExpires);
return () => clearTimeout(timeout);
}, [expiresAtSeconds]);
const logout = useCallback(client.logout, []);
const redirectToLoginPage = useCallback(client.redirectToLoginPage, []);
const redirectToSignupPage = useCallback(client.redirectToSignupPage, []);
const redirectToAccountPage = useCallback(client.redirectToAccountPage, []);
const redirectToOrgPage = useCallback(client.redirectToOrgPage, []);
const redirectToCreateOrgPage = useCallback(client.redirectToCreateOrgPage, []);
const value = {
loading: authInfoState.loading,
triggerRefreshAuthentication,
authInfo: authInfoState.authInfo,
logout,
userSelectedOrgId,
selectOrgId: setUserSelectedOrgId,
redirectToLoginPage,
redirectToSignupPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
return /*#__PURE__*/React.createElement(AuthContext.Provider, {
value: value
}, props.children);
};
function getMillisUntilTokenExpires(expiresAtSeconds) {
let millisUntilTokenExpires = expiresAtSeconds * 1000 - Date.now();
return Math.max(0, millisUntilTokenExpires);
}
function getOrgHelper(orgIdToOrgMemberInfo, selectOrgId, userSelectedOrgId) {
return {
getOrg(orgId) {
if (orgIdToOrgMemberInfo.hasOwnProperty(orgId)) {
return orgIdToOrgMemberInfo[orgId];
} else {
return undefined;
}
},
getOrgIds() {
return Object.keys(orgIdToOrgMemberInfo);
},
getOrgs() {
return Object.values(orgIdToOrgMemberInfo);
},
getSelectedOrg(inferDefault) {
// default for inferDefault is true
inferDefault = inferDefault === undefined ? true : inferDefault; // if the user has selected an org already, return it
if (userSelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(userSelectedOrgId)) {
return orgIdToOrgMemberInfo[userSelectedOrgId];
} else if (!inferDefault) {
return undefined;
} // otherwise, infer it from local storage
const previouslySelectedOrgId = loadOrgSelectionFromLocalStorage();
if (previouslySelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(previouslySelectedOrgId)) {
return orgIdToOrgMemberInfo[previouslySelectedOrgId];
} // if the user has never selected one before, select one deterministically by name
let alphabeticallyFirstOrgName = undefined;
let alphabeticallyFirstOrg = undefined;
for (let org of this.getOrgs()) {
if (!alphabeticallyFirstOrgName || org.orgName < alphabeticallyFirstOrgName) {
alphabeticallyFirstOrgName = org.orgName;
alphabeticallyFirstOrg = org;
}
}
return alphabeticallyFirstOrg;
},
selectOrg(orgId) {
selectOrgId(orgId);
saveOrgSelectionToLocalStorage(orgId);
},
getNotSelectedOrgs(inferDefault) {
const selectedOrg = this.getSelectedOrg(inferDefault);
if (selectedOrg) {
return this.getOrgs().filter(org => org.orgId !== selectedOrg.orgId);
} else {
return this.getOrgs();
}
}
};
}
const ORG_SELECTION_LOCAL_STORAGE_KEY = "__last_selected_org";
function saveOrgSelectionToLocalStorage(orgId) {
if (localStorage) {
localStorage.setItem(ORG_SELECTION_LOCAL_STORAGE_KEY, orgId);
}
}
function loadOrgSelectionFromLocalStorage() {
if (localStorage) {
return localStorage.getItem(ORG_SELECTION_LOCAL_STORAGE_KEY);
}
return null;
}
function useAuthInfo() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuthInfo must be used within an AuthProvider");
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return {
loading: true
};
} else if (authInfo && authInfo.accessToken) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
return {
loading: false,
isLoggedIn: true,
accessToken: authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
}
return {
loading: false,
isLoggedIn: false,
accessToken: null,
orgHelper: null,
user: null
};
}
function useLogoutFunction() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useLogoutFunction must be used within an AuthProvider");
}
const {
logout
} = context;
return logout;
}
function useRedirectFunctions() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useRedirectFunctions must be used within an AuthProvider");
}
const {
redirectToAccountPage,
redirectToSignupPage,
redirectToLoginPage,
redirectToOrgPage,
redirectToCreateOrgPage
} = context;
return {
redirectToSignupPage,
redirectToLoginPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
}
function RedirectToSignup(props) {
const {
redirectToSignupPage
} = useRedirectFunctions();
redirectToSignupPage();
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
}
function RedirectToLogin(props) {
const {
redirectToLoginPage
} = useRedirectFunctions();
redirectToLoginPage();
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
}
function createCommonjsModule(fn) {

@@ -1008,2 +729,345 @@ var module = { exports: {} };

function getOrgHelper(orgIdToOrgMemberInfo, selectOrgId, userSelectedOrgId) {
return {
getOrg(orgId) {
if (orgIdToOrgMemberInfo.hasOwnProperty(orgId)) {
return orgIdToOrgMemberInfo[orgId];
} else {
return undefined;
}
},
getOrgIds() {
return Object.keys(orgIdToOrgMemberInfo);
},
getOrgs() {
return Object.values(orgIdToOrgMemberInfo);
},
getSelectedOrg(inferDefault) {
// default for inferDefault is true
inferDefault = inferDefault === undefined ? true : inferDefault; // if the user has selected an org already, return it
if (userSelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(userSelectedOrgId)) {
return orgIdToOrgMemberInfo[userSelectedOrgId];
} else if (!inferDefault) {
return undefined;
} // otherwise, infer it from local storage
const previouslySelectedOrgId = loadOrgSelectionFromLocalStorage();
if (previouslySelectedOrgId && orgIdToOrgMemberInfo.hasOwnProperty(previouslySelectedOrgId)) {
return orgIdToOrgMemberInfo[previouslySelectedOrgId];
} // if the user has never selected one before, select one deterministically by name
let alphabeticallyFirstOrgName = undefined;
let alphabeticallyFirstOrg = undefined;
for (let org of this.getOrgs()) {
if (!alphabeticallyFirstOrgName || org.orgName < alphabeticallyFirstOrgName) {
alphabeticallyFirstOrgName = org.orgName;
alphabeticallyFirstOrg = org;
}
}
return alphabeticallyFirstOrg;
},
selectOrg(orgId) {
selectOrgId(orgId);
saveOrgSelectionToLocalStorage(orgId);
},
getNotSelectedOrgs(inferDefault) {
const selectedOrg = this.getSelectedOrg(inferDefault);
if (selectedOrg) {
return this.getOrgs().filter(org => org.orgId !== selectedOrg.orgId);
} else {
return this.getOrgs();
}
}
};
}
const ORG_SELECTION_LOCAL_STORAGE_KEY = "__last_selected_org";
function saveOrgSelectionToLocalStorage(orgId) {
if (localStorage) {
localStorage.setItem(ORG_SELECTION_LOCAL_STORAGE_KEY, orgId);
}
}
function loadOrgSelectionFromLocalStorage() {
if (localStorage) {
return localStorage.getItem(ORG_SELECTION_LOCAL_STORAGE_KEY);
}
return null;
}
function useRedirectFunctions() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useRedirectFunctions must be used within an AuthProvider or RequiredAuthProvider");
}
const {
redirectToAccountPage,
redirectToSignupPage,
redirectToLoginPage,
redirectToOrgPage,
redirectToCreateOrgPage
} = context;
return {
redirectToSignupPage,
redirectToLoginPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
}
function RedirectToSignup(props) {
const {
redirectToSignupPage
} = useRedirectFunctions();
redirectToSignupPage();
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
}
function RedirectToLogin(props) {
const {
redirectToLoginPage
} = useRedirectFunctions();
redirectToLoginPage();
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
}
function withRequiredAuthInfo(Component, args) {
const displayName = `withRequiredAuthInfo(${Component.displayName || Component.name || "Component"})`;
const WithRequiredAuthInfoWrapper = props => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("withRequiredAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}
function displayLoading() {
if (args && args.displayWhileLoading) {
return args.displayWhileLoading;
} else {
return /*#__PURE__*/React.createElement(React.Fragment, null);
}
}
function displayLoggedOut() {
if (args && args.displayIfLoggedOut) {
return args.displayIfLoggedOut;
} else {
return /*#__PURE__*/React.createElement(RedirectToLogin, null);
}
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return displayLoading();
} else if (authInfo) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
const loggedInProps = { ...props,
accessToken: authInfo.accessToken,
isLoggedIn: !!authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
return /*#__PURE__*/React.createElement(Component, loggedInProps);
} else {
return displayLoggedOut();
}
};
WithRequiredAuthInfoWrapper.displayName = displayName;
WithRequiredAuthInfoWrapper.WrappedComponent = Component;
return hoistNonReactStatics_cjs(WithRequiredAuthInfoWrapper, Component);
}
const AuthContext = /*#__PURE__*/React.createContext(undefined);
const initialAuthInfoState = {
loading: true,
authInfo: null
};
function authInfoStateReducer(_state, action) {
return {
loading: false,
authInfo: action.authInfo
};
}
const AuthProvider = props => {
const [authInfoState, dispatch] = useReducer(authInfoStateReducer, initialAuthInfoState);
const [heartbeatCounter, setHeartbeatCounter] = useState(0);
const [userSelectedOrgId, setUserSelectedOrgId] = useState(null);
const triggerRefreshAuthentication = () => setHeartbeatCounter(x => x + 1); // Create client and register observer
const client = useMemo(() => {
// Disable background token refresh as we will do it within React instead
const client = createClient({
authUrl: props.authUrl,
enableBackgroundTokenRefresh: false
});
client.addLoggedInChangeObserver(triggerRefreshAuthentication);
return client;
}, [props.authUrl]); // On unmount, destroy the client
useEffect(() => {
return () => {
client.destroy();
};
}, []); // Periodically refresh the token. The client will only make requests when the authInfo is stale
// Errors are logged and the token will be invalidated separately
useEffect(() => {
let didCancel = false;
async function refreshToken() {
try {
const authInfo = await client.getAuthenticationInfoOrNull();
if (!didCancel) {
dispatch({
authInfo
});
}
} catch (_) {// Exceptions are logged in the JS library
}
}
refreshToken();
return () => {
didCancel = true;
};
}, [client, heartbeatCounter]);
useEffect(() => {
const interval = setInterval(triggerRefreshAuthentication, 60000);
return () => clearInterval(interval);
}, []); // Watchdog timer to make sure that if we hit the expiration we get rid of the token.
// This should only be triggered if we are unable to get a new token due to an unexpected error/network timeouts.
const expiresAtSeconds = authInfoState.authInfo ? authInfoState.authInfo.expiresAtSeconds : 0;
useEffect(() => {
if (!authInfoState.authInfo) {
return;
}
const millisUntilTokenExpires = getMillisUntilTokenExpires(authInfoState.authInfo.expiresAtSeconds);
const timeout = setTimeout(() => {
dispatch({
authInfo: null
});
}, millisUntilTokenExpires);
return () => clearTimeout(timeout);
}, [expiresAtSeconds]);
const logout = useCallback(client.logout, []);
const redirectToLoginPage = useCallback(client.redirectToLoginPage, []);
const redirectToSignupPage = useCallback(client.redirectToSignupPage, []);
const redirectToAccountPage = useCallback(client.redirectToAccountPage, []);
const redirectToOrgPage = useCallback(client.redirectToOrgPage, []);
const redirectToCreateOrgPage = useCallback(client.redirectToCreateOrgPage, []);
const value = {
loading: authInfoState.loading,
triggerRefreshAuthentication,
authInfo: authInfoState.authInfo,
logout,
userSelectedOrgId,
selectOrgId: setUserSelectedOrgId,
redirectToLoginPage,
redirectToSignupPage,
redirectToAccountPage,
redirectToOrgPage,
redirectToCreateOrgPage
};
return /*#__PURE__*/React.createElement(AuthContext.Provider, {
value: value
}, props.children);
};
const RequiredAuthProvider = props => {
const WrappedComponent = withRequiredAuthInfo(props => {
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
}, {
displayWhileLoading: props.displayWhileLoading,
displayIfLoggedOut: props.displayIfLoggedOut
});
return /*#__PURE__*/React.createElement(AuthProvider, {
authUrl: props.authUrl
}, /*#__PURE__*/React.createElement(WrappedComponent, props));
};
function getMillisUntilTokenExpires(expiresAtSeconds) {
let millisUntilTokenExpires = expiresAtSeconds * 1000 - Date.now();
return Math.max(0, millisUntilTokenExpires);
}
function useAuthInfo() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}
const {
loading,
authInfo,
selectOrgId,
userSelectedOrgId
} = context;
if (loading) {
return {
loading: true
};
} else if (authInfo && authInfo.accessToken) {
const orgHelper = getOrgHelper(authInfo.orgIdToOrgMemberInfo || {}, selectOrgId, userSelectedOrgId);
return {
loading: false,
isLoggedIn: true,
accessToken: authInfo.accessToken,
orgHelper: orgHelper,
user: authInfo.user
};
}
return {
loading: false,
isLoggedIn: false,
accessToken: null,
orgHelper: null,
user: null
};
}
function useLogoutFunction() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useLogoutFunction must be used within an AuthProvider or RequiredAuthProvider");
}
const {
logout
} = context;
return logout;
}
function withAuthInfo(Component, args) {

@@ -1016,3 +1080,3 @@ const displayName = `withAuthInfo(${Component.displayName || Component.name || "Component"})`;

if (context === undefined) {
throw new Error("withAuthInfo must be used within an AuthProvider");
throw new Error("withAuthInfo must be used within an AuthProvider or RequiredAuthProvider");
}

@@ -1062,3 +1126,3 @@

export { AuthProvider, RedirectToLogin, RedirectToSignup, UserRole, useAuthInfo, useLogoutFunction, useRedirectFunctions, withAuthInfo };
export { AuthProvider, RedirectToLogin, RedirectToSignup, RequiredAuthProvider, UserRole, useAuthInfo, useLogoutFunction, useRedirectFunctions, withAuthInfo, withRequiredAuthInfo };
//# sourceMappingURL=index.esm.js.map

@@ -20,4 +20,9 @@ import { AuthenticationInfo } from "@propelauth/javascript";

};
export interface RequiredAuthProviderProps extends AuthProviderProps {
displayWhileLoading?: React.ReactElement;
displayIfLoggedOut?: React.ReactElement;
}
export declare const AuthContext: React.Context<InternalAuthState | undefined>;
export declare const AuthProvider: (props: AuthProviderProps) => JSX.Element;
export declare const RequiredAuthProvider: (props: RequiredAuthProviderProps) => JSX.Element;
export {};
export { UserRole } from "@propelauth/javascript";
export type { OrgIdToOrgMemberInfo, OrgMemberInfo, User } from "@propelauth/javascript";
export { AuthProvider } from "./AuthContext";
export type { AuthProviderProps } from "./AuthContext";
export { AuthProvider, RequiredAuthProvider } from "./AuthContext";
export type { AuthProviderProps, RequiredAuthProviderProps } from "./AuthContext";
export type { OrgHelper } from "./OrgHelper";

@@ -12,1 +12,3 @@ export { useAuthInfo } from "./useAuthInfo";

export type { WithAuthInfoArgs, WithAuthInfoProps, WithLoggedInAuthInfoProps, WithNotLoggedInAuthInfoProps, } from "./withAuthInfo";
export { withRequiredAuthInfo } from "./withRequiredAuthInfo";
export type { WithRequiredAuthInfoArgs } from "./withRequiredAuthInfo";

@@ -8,3 +8,3 @@ {

},
"version": "1.2.4",
"version": "1.2.5",
"license": "MIT",

@@ -11,0 +11,0 @@ "keywords": [

@@ -8,3 +8,3 @@ /**

import { v4 as uuidv4 } from "uuid"
import { AuthProvider } from "./AuthContext"
import { AuthProvider, RequiredAuthProvider } from "./AuthContext"
import { useAuthInfo } from "./useAuthInfo"

@@ -14,2 +14,3 @@ import { useLogoutFunction } from "./useLogoutFunction"

import { withAuthInfo } from "./withAuthInfo"
import { withRequiredAuthInfo } from "./withRequiredAuthInfo"

@@ -135,2 +136,92 @@ // Fake timer setup

it("withAuthInfo passes values from client as props, with RequiredAuthProvider", async () => {
const authenticationInfo = createAuthenticationInfo()
mockClient.getAuthenticationInfoOrNull.mockReturnValue(authenticationInfo)
const Component = (props) => {
expect(props.accessToken).toBe(authenticationInfo.accessToken)
expect(props.user).toStrictEqual(authenticationInfo.user)
expect(props.isLoggedIn).toBe(true)
expect(props.orgHelper.getOrgs().sort()).toEqual(Object.values(authenticationInfo.orgIdToOrgMemberInfo).sort())
return <div>Finished</div>
}
const WrappedComponent = withAuthInfo(Component)
render(
<RequiredAuthProvider authUrl={AUTH_URL}>
<WrappedComponent />
</RequiredAuthProvider>
)
await waitFor(() => screen.getByText("Finished"))
expectCreateClientWasCalledCorrectly()
})
it("withRequiredAuthInfo passes values from client as props, with RequiredAuthProvider", async () => {
const authenticationInfo = createAuthenticationInfo()
mockClient.getAuthenticationInfoOrNull.mockReturnValue(authenticationInfo)
const Component = (props) => {
expect(props.accessToken).toBe(authenticationInfo.accessToken)
expect(props.user).toStrictEqual(authenticationInfo.user)
expect(props.isLoggedIn).toBe(true)
expect(props.orgHelper.getOrgs().sort()).toEqual(Object.values(authenticationInfo.orgIdToOrgMemberInfo).sort())
return <div>Finished</div>
}
const WrappedComponent = withRequiredAuthInfo(Component)
render(
<RequiredAuthProvider authUrl={AUTH_URL}>
<WrappedComponent />
</RequiredAuthProvider>
)
await waitFor(() => screen.getByText("Finished"))
expectCreateClientWasCalledCorrectly()
})
it("RequiredAuthProvider displays logged out value if logged out", async () => {
mockClient.getAuthenticationInfoOrNull.mockReturnValue(null)
const ErrorComponent = () => {
return <div>Error</div>
}
const SuccessComponent = () => {
return <div>Finished</div>
}
const WrappedComponent = withAuthInfo(ErrorComponent)
render(
<RequiredAuthProvider authUrl={AUTH_URL} displayIfLoggedOut={<SuccessComponent />}>
<WrappedComponent />
</RequiredAuthProvider>
)
await waitFor(() => screen.getByText("Finished"))
expectCreateClientWasCalledCorrectly()
})
it("withRequiredAuthInfo displays logged out value if logged out", async () => {
mockClient.getAuthenticationInfoOrNull.mockReturnValue(null)
const ErrorComponent = () => {
return <div>Error</div>
}
const SuccessComponent = () => {
return <div>Finished</div>
}
const WrappedComponent = withRequiredAuthInfo(ErrorComponent, {
displayIfLoggedOut: <SuccessComponent />,
})
render(
<AuthProvider authUrl={AUTH_URL}>
<WrappedComponent />
</AuthProvider>
)
await waitFor(() => screen.getByText("Finished"))
expectCreateClientWasCalledCorrectly()
})
it("withAuthInfo passes logged out values from client as props", async () => {

@@ -137,0 +228,0 @@ mockClient.getAuthenticationInfoOrNull.mockReturnValue(null)

@@ -31,3 +31,3 @@ import { User } from "@propelauth/javascript"

if (context === undefined) {
throw new Error("useAuthInfo must be used within an AuthProvider")
throw new Error("useAuthInfo must be used within an AuthProvider or RequiredAuthProvider")
}

@@ -34,0 +34,0 @@

@@ -7,3 +7,3 @@ import { useContext } from "react"

if (context === undefined) {
throw new Error("useLogoutFunction must be used within an AuthProvider")
throw new Error("useLogoutFunction must be used within an AuthProvider or RequiredAuthProvider")
}

@@ -10,0 +10,0 @@ const { logout } = context

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc