@forward-software/react-auth 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 ForWarD Software
3
+ Copyright (c) 2025 ForWarD Software (https://forwardsoftware.solutions/)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,12 +1,8 @@
1
1
  # React Auth
2
2
 
3
- <div align="center">
4
- <img src="./assets/cover.jpeg" width="100%" />
5
- </div>
6
-
7
3
  > Simplify your Auth flow when working with React apps
8
4
 
9
- [![license](https://img.shields.io/github/license/Forward-Software/react-auth.svg)](https://github.com/Forward-Software/react-auth/blob/main/LICENSE) [![CI](https://github.com/Forward-Software/react-auth/actions/workflows/main.yml/badge.svg)](https://github.com/Forward-Software/react-auth/actions/workflows/main.yml) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/Forward-Software/react-auth.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Forward-Software/react-auth/context:javascript) [![Coverage Status](https://coveralls.io/repos/github/Forward-Software/react-auth/badge.svg?branch=main)](https://coveralls.io/github/Forward-Software/react-auth?branch=main) [![Github Issues](https://img.shields.io/github/issues/Forward-Software/react-auth.svg)](https://github.com/Forward-Software/react-auth/issues)
5
+ [![license](https://img.shields.io/github/license/forwardsoftware/react-auth.svg)](https://github.com/forwardsoftware/react-auth/blob/main/LICENSE) [![Build & Test](https://github.com/forwardsoftware/react-auth/actions/workflows/build-test.yml/badge.svg)](https://github.com/forwardsoftware/react-auth/actions/workflows/build-test.yml) [![Github Issues](https://img.shields.io/github/issues/forwardsoftware/react-auth.svg)](https://github.com/forwardsoftware/react-auth/issues)
10
6
 
11
7
  [![npm](https://img.shields.io/npm/v/@forward-software/react-auth)](https://npmjs.com/package/@forward-software/react-auth) [![NPM downloads](https://img.shields.io/npm/dm/@forward-software/react-auth.svg)](https://npmjs.com/package/@forward-software/react-auth)
12
8
 
@@ -17,86 +13,137 @@ This React package allows you to streamline the integration of user authenticati
17
13
  ## Install
18
14
 
19
15
  ```sh
20
- yarn add @forward-software/react-auth
16
+ npm install @forward-software/react-auth
21
17
  ```
22
18
 
23
19
  ## Setup
24
20
 
25
- ### Define an AuthClient class
26
-
27
- Create a new `AuthClient` class which extends the `BaseAuthClient` provided by this library and implements the 4 required methods:
21
+ ### Define an AuthClient
28
22
 
29
- - **onInit**, called when the AuthClient gets initialized
30
- - **onLogin**, invoked when the `login` method of the AuthClient gets called
31
- - **onRefresh**, invoked when the `refresh` method of the AuthClient gets called
32
- - **onLogout**, invoked when the `logout` method of the AuthClient gets called
23
+ Create a new object that implements the `AuthClient` interface provided by this library. The interface includes several lifecycle methods, some of which are optional:
33
24
 
34
25
  ```ts
35
- import { BaseAuthClient } from '@forward-software/react-auth';
26
+ import type { AuthClient } from '@forward-software/react-auth';
36
27
 
37
28
  // The type for your credentials
38
29
  type AuthCredentials = {
39
30
  username: string;
40
-
41
31
  password: string;
42
32
  };
43
33
 
44
34
  // The type for your tokens
45
35
  type AuthTokens = {
46
36
  authToken: string;
47
-
48
37
  refreshToken: string;
49
38
  };
50
39
 
51
- class AuthClient extends BaseAuthClient<AuthTokens, AuthCredentials> {
52
- protected onInit(): Promise<void> {
40
+ const authClient: AuthClient<AuthTokens, AuthCredentials> = {
41
+ // Optional: Called when the AuthClient gets initialized
42
+ onInit: async (): Promise<AuthTokens | null> => {
53
43
  // Implement the initialization logic for your client
54
- }
44
+ return null;
45
+ },
55
46
 
56
- protected onLogin(credentials?: AuthCredentials): Promise<AuthTokens> {
57
- // Implement the logic required to exchange the provided credentials for user tokens
58
- }
47
+ // Optional: Called after initialization completes
48
+ onPostInit: async (): Promise<void> => {
49
+ // Implement any post-initialization logic
50
+ },
59
51
 
60
- protected onRefresh(minValidity?: number): Promise<AuthTokens> {
61
- // Implement the logic required to refresh the current user tokens
62
- }
52
+ // Optional: Called before login starts
53
+ onPreLogin: async (): Promise<void> => {
54
+ // Implement any pre-login logic
55
+ },
63
56
 
64
- protected onLogout(): Promise<void> {
57
+ // Required: Called when login is requested
58
+ onLogin: async (credentials?: AuthCredentials): Promise<AuthTokens> => {
59
+ // Implement the logic required to exchange the provided credentials for user tokens
60
+ return {
61
+ authToken: '...',
62
+ refreshToken: '...'
63
+ };
64
+ },
65
+
66
+ // Optional: Called after login completes
67
+ onPostLogin: async (isSuccess: boolean): Promise<void> => {
68
+ // Implement any post-login logic
69
+ },
70
+
71
+ // Optional: Called before refresh starts
72
+ onPreRefresh: async (): Promise<void> => {
73
+ // Implement any pre-refresh logic
74
+ },
75
+
76
+ // Optional: Called when refresh is requested
77
+ // The current tokens are passed as the first argument
78
+ onRefresh: async (currentTokens: AuthTokens, minValidity?: number): Promise<AuthTokens> => {
79
+ // Implement the logic required to refresh the current user tokens
80
+ return {
81
+ authToken: '...',
82
+ refreshToken: '...'
83
+ };
84
+ },
85
+
86
+ // Optional: Called after refresh completes
87
+ onPostRefresh: async (isSuccess: boolean): Promise<void> => {
88
+ // Implement any post-refresh logic
89
+ },
90
+
91
+ // Optional: Called before logout starts
92
+ onPreLogout: async (): Promise<void> => {
93
+ // Implement any pre-logout logic
94
+ },
95
+
96
+ // Optional: Called when logout is requested
97
+ onLogout: async (): Promise<void> => {
65
98
  // Implement the logic required to invalidate the current user tokens
99
+ },
100
+
101
+ // Optional: Called after logout completes
102
+ onPostLogout: async (isSuccess: boolean): Promise<void> => {
103
+ // Implement any post-logout logic
66
104
  }
67
- }
105
+ };
68
106
  ```
69
107
 
70
- ### Instantiate an AuthClient
108
+ ### Use the AuthClient
71
109
 
72
- Create an instance of the `AuthClient` class defined
110
+ The `AuthClient` instance can be used directly with the `createAuth` function:
73
111
 
74
112
  ```ts
75
- const authClient = new AuthClient();
113
+ import { createAuth } from '@forward-software/react-auth';
114
+
115
+ export const { AuthProvider, useAuthClient, authClient: enhancedAuthClient } = createAuth(authClient);
76
116
  ```
77
117
 
78
- #### AuthClient Props
118
+ The `createAuth` function returns:
79
119
 
80
- - `isInitialized`, a boolean indicating if the AuthClient has been initialized
81
- - `isAuthenticated`, a boolean indicating if the login process has been successfull and the user is authenticated
82
- - `tokens`, the current tokens returned by the `login` or the `refresh` process
120
+ - `AuthProvider`, the context Provider component that should wrap your app and provide access to your AuthClient
121
+ - `useAuthClient`, the hook to retrieve and interact with your AuthClient
122
+ - `authClient`, the enhanced authentication client instance
123
+
124
+ #### AuthProvider
125
+
126
+ The context Provider component that should wrap your app and provide access to your AuthClient, this component also accepts 2 additional props
127
+
128
+ - `ErrorComponent`, displayed when the AuthClient initialization fails
129
+ - `LoadingComponent`, displayed while the AuthClient is being initialized
130
+
131
+ #### EnhancedAuthClient
83
132
 
84
- #### AuthClient Methods
133
+ The `createAuth` function wraps your `AuthClient` implementation with an `EnhancedAuthClient` that provides additional functionality:
85
134
 
86
- ##### Core
135
+ ##### Properties
136
+ - `isInitialized`, a boolean indicating if the AuthClient has been initialized
137
+ - `isAuthenticated`, a boolean indicating if the login process has been successful and the user is authenticated
138
+ - `tokens`, the current tokens returned by the `login` or the `refresh` process
87
139
 
88
- - `init()`, initialize the AuthClient (**N.B.** this shouldn't be called if using `AuthProvider` - see below)
140
+ ##### Methods
141
+ - `init()`, initialize the AuthClient (**N.B.** this shouldn't be called if using `AuthProvider` - see above)
89
142
  - `login(credentials)`, start the login process
90
143
  - `refresh()`, refresh the current tokens
91
144
  - `logout()`, logout and invalidate the current tokens
92
-
93
- ##### EventEmitter
94
-
95
145
  - `on(eventName, listenerFn)`, subscribe to `eventName` events emitted by the AuthClient
96
146
  - `off(eventName, listenerFn)`, unsubscribe from `eventName` events emitted by the AuthClient
97
-
98
- ##### Observable
99
-
100
147
  - `subscribe(() => { })`, subscribe to AuthClient state changes
101
148
  - `getSnapshot()`, returns the current state of the AuthClient
102
149
 
@@ -136,6 +183,6 @@ MIT
136
183
 
137
184
  ---
138
185
 
139
- Made with ✨ & ❤️ by [ForWarD Software](https://github.com/Forward-Software) and [contributors](https://github.com/Forward-Software/react-auth/graphs/contributors)
186
+ Made with ✨ & ❤️ by [ForWarD Software](https://github.com/forwardsoftware) and [contributors](https://github.com/forwardsoftware/react-auth/graphs/contributors)
140
187
 
141
188
  If you found this project to be helpful, please consider contacting us to develop your React and React Native projects.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,237 @@
1
+ import React from 'react';
2
+ import type { PropsWithChildren } from 'react';
3
+ import { EventReceiver } from "./utils";
4
+ import type { EventKey } from "./utils";
5
+ /**
6
+ * Represents authentication tokens used for API authorization
7
+ */
8
+ type AuthTokens = {};
9
+ /**
10
+ * Represents user credentials used for authentication
11
+ */
12
+ type AuthCredentials = {};
13
+ /**
14
+ * Maps authentication events to their corresponding payload types
15
+ * @template E - The error type used throughout the authentication flow
16
+ */
17
+ type AuthEventsMap<E extends Error> = {
18
+ initSuccess: undefined;
19
+ initFailed: E;
20
+ loginStarted: undefined;
21
+ loginSuccess: undefined;
22
+ loginFailed: E;
23
+ refreshStarted: undefined;
24
+ refreshSuccess: undefined;
25
+ refreshFailed: E;
26
+ logoutStarted: undefined;
27
+ logoutSuccess: undefined;
28
+ logoutFailed: E;
29
+ };
30
+ /**
31
+ * Function type for subscription callbacks
32
+ */
33
+ type SubscribeFn = () => void;
34
+ /**
35
+ * Function type for unsubscribing from events
36
+ * @returns {boolean} - Returns true if the subscription was successfully removed
37
+ */
38
+ type UnsubscribeFn = () => boolean;
39
+ /**
40
+ * Interface defining the core authentication client functionality
41
+ * @template T - The type of authentication tokens
42
+ * @template C - The type of authentication credentials
43
+ */
44
+ export interface AuthClient<T = AuthTokens, C = AuthCredentials> {
45
+ /**
46
+ * Optional initialization hook called before authentication
47
+ * @returns {Promise<T | null>} - Returns authentication tokens if available
48
+ */
49
+ onInit?(): Promise<T | null>;
50
+ /**
51
+ * Optional post-initialization hook
52
+ */
53
+ onPostInit?(): Promise<void>;
54
+ /**
55
+ * Optional pre-login hook
56
+ */
57
+ onPreLogin?(): Promise<void>;
58
+ /**
59
+ * Handles the login process
60
+ * @param {C} [credentials] - Optional credentials for authentication
61
+ * @returns {Promise<T>} - Returns authentication tokens upon successful login
62
+ */
63
+ onLogin(credentials?: C): Promise<T>;
64
+ /**
65
+ * Optional post-login hook
66
+ * @param {boolean} isSuccess - Indicates whether the login was successful
67
+ */
68
+ onPostLogin?(isSuccess: boolean): Promise<void>;
69
+ /**
70
+ * Optional pre-refresh hook
71
+ */
72
+ onPreRefresh?(): Promise<void>;
73
+ /**
74
+ * Optional token refresh handler.
75
+ * Implement this method to handle token refresh logic.
76
+ * @param {T} currentTokens - The current authentication tokens.
77
+ * @param {number} [minValidity] - Optional minimum token validity period in seconds.
78
+ * @returns {Promise<T>} - A promise that resolves with the refreshed authentication tokens.
79
+ */
80
+ onRefresh?(currentTokens: T, minValidity?: number): Promise<T>;
81
+ /**
82
+ * Optional post-refresh hook
83
+ * @param {boolean} isSuccess - Indicates whether the token refresh was successful
84
+ */
85
+ onPostRefresh?(isSuccess: boolean): Promise<void>;
86
+ /**
87
+ * Optional pre-logout hook
88
+ */
89
+ onPreLogout?(): Promise<void>;
90
+ /**
91
+ * Optional logout handler
92
+ */
93
+ onLogout?(): Promise<void>;
94
+ /**
95
+ * Optional post-logout hook
96
+ * @param {boolean} isSuccess - Indicates whether the logout was successful
97
+ */
98
+ onPostLogout?(isSuccess: boolean): Promise<void>;
99
+ }
100
+ /**
101
+ * Extracts token type from an AuthClient implementation
102
+ * @template AC - The AuthClient implementation type
103
+ */
104
+ type AuthClientTokens<AC extends AuthClient> = Partial<Awaited<ReturnType<AC["onLogin"]>>>;
105
+ /**
106
+ * Extracts credentials type from an AuthClient implementation
107
+ * @template AC - The AuthClient implementation type
108
+ */
109
+ type AuthClientCredentials<AC extends AuthClient> = Parameters<AC["onLogin"]>;
110
+ /**
111
+ * Represents the current state of an AuthClient
112
+ * @template AC - The AuthClient implementation type
113
+ */
114
+ type AuthClientState<AC extends AuthClient> = {
115
+ isAuthenticated: boolean;
116
+ isInitialized: boolean;
117
+ tokens: AuthClientTokens<AC>;
118
+ };
119
+ declare class AuthClientEnhancements<AC extends AuthClient, E extends Error> {
120
+ private _state;
121
+ private refreshQ;
122
+ private eventEmitter;
123
+ private subscribers;
124
+ private _authClient;
125
+ constructor(authClient: AC);
126
+ /**
127
+ * Indicates whether the authentication client has been initialized
128
+ * @readonly
129
+ */
130
+ get isInitialized(): boolean;
131
+ /**
132
+ * Indicates whether the user is currently authenticated
133
+ * @readonly
134
+ */
135
+ get isAuthenticated(): boolean;
136
+ /**
137
+ * Current authentication tokens
138
+ * @readonly
139
+ */
140
+ get tokens(): Partial<Awaited<ReturnType<AC["onLogin"]>>>;
141
+ /**
142
+ * Initializes the authentication client
143
+ * @returns {Promise<boolean>} - Returns true if initialization was successful
144
+ */
145
+ init(): Promise<boolean>;
146
+ /**
147
+ * Attempts to authenticate the user with provided credentials
148
+ * @param {...AuthClientCredentials<AC>} params - Authentication credentials
149
+ * @returns {Promise<boolean>} - Returns true if login was successful
150
+ */
151
+ login(...params: AuthClientCredentials<AC>): Promise<boolean>;
152
+ /**
153
+ * Refreshes the authentication tokens
154
+ * @param {number} [minValidity] - Minimum token validity period in seconds
155
+ * @returns {Promise<boolean>} - Returns true if token refresh was successful
156
+ */
157
+ refresh(minValidity?: number): Promise<boolean>;
158
+ /**
159
+ * Logs out the current user
160
+ * @returns {Promise<void>}
161
+ */
162
+ logout(): Promise<void>;
163
+ /**
164
+ * Registers an event listener for authentication events
165
+ * @template K - The event key type
166
+ * @param {K} eventName - The name of the event to listen for
167
+ * @param {EventReceiver<AuthEventsMap<E>[K]>} listener - The event handler function
168
+ */
169
+ on<K extends EventKey<AuthEventsMap<E>>>(eventName: K, listener: EventReceiver<AuthEventsMap<E>[K]>): void;
170
+ /**
171
+ * Removes an event listener for authentication events
172
+ * @template K - The event key type
173
+ * @param {K} eventName - The name of the event to stop listening for
174
+ * @param {EventReceiver<AuthEventsMap<E>[K]>} listener - The event handler function to remove
175
+ */
176
+ off<K extends EventKey<AuthEventsMap<E>>>(eventName: K, listener: EventReceiver<AuthEventsMap<E>[K]>): void;
177
+ /**
178
+ * Subscribes to authentication state changes
179
+ * @param {SubscribeFn} subscription - The callback function to be called on state changes
180
+ * @returns {UnsubscribeFn} - A function to unsubscribe from state changes
181
+ */
182
+ subscribe: (subscription: SubscribeFn) => UnsubscribeFn;
183
+ /**
184
+ * Gets the current authentication state
185
+ * @returns {AuthClientState<AC>} - The current authentication state
186
+ */
187
+ getSnapshot: () => AuthClientState<AC>;
188
+ private setState;
189
+ private runRefresh;
190
+ private emit;
191
+ private notifySubscribers;
192
+ }
193
+ /**
194
+ * Enhanced authentication client with additional functionality and state management
195
+ * @template AC - The AuthClient implementation type
196
+ * @template E - The error type used throughout the authentication flow
197
+ */
198
+ export type EnhancedAuthClient<AC extends AuthClient, E extends Error> = AC & AuthClientEnhancements<AC, E>;
199
+ /**
200
+ * Wraps a basic AuthClient implementation with enhanced functionality
201
+ * @template AC - The AuthClient implementation type
202
+ * @template E - The error type used throughout the authentication flow
203
+ * @param {AC} authClient - The base authentication client to enhance
204
+ * @returns {EnhancedAuthClient<AC, E>} - An enhanced authentication client with additional features
205
+ */
206
+ export declare function wrapAuthClient<AC extends AuthClient, E extends Error = Error>(authClient: AC): EnhancedAuthClient<AC, E>;
207
+ /**
208
+ * Props that can be passed to AuthProvider
209
+ */
210
+ export type AuthProviderProps = PropsWithChildren<{
211
+ /**
212
+ * An optional component to display if AuthClient initialization failed.
213
+ */
214
+ ErrorComponent?: React.ReactNode;
215
+ /**
216
+ * An optional component to display while AuthClient instance is being initialized.
217
+ */
218
+ LoadingComponent?: React.ReactNode;
219
+ }>;
220
+ /**
221
+ * Creates an authentication context and provider for a React application.
222
+ * It wraps the provided `authClient` with enhanced state management and event handling.
223
+ *
224
+ * @template AC - The type of the base `AuthClient` implementation.
225
+ * @template E - The type of error expected during authentication flows. Defaults to `Error`.
226
+ * @param {AC} authClient - The base authentication client instance to use.
227
+ * @returns An object containing:
228
+ * - `AuthProvider`: A React component to wrap the application or parts of it.
229
+ * - `authClient`: The enhanced authentication client instance.
230
+ * - `useAuthClient`: A hook to access the enhanced `authClient` within the `AuthProvider`.
231
+ */
232
+ export declare function createAuth<AC extends AuthClient, E extends Error = Error>(authClient: AC): {
233
+ AuthProvider: React.FC<AuthProviderProps>;
234
+ authClient: EnhancedAuthClient<AC, E>;
235
+ useAuthClient: () => EnhancedAuthClient<AC, E>;
236
+ };
237
+ export {};
package/dist/auth.js ADDED
@@ -0,0 +1,215 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { createContext, useContext, useEffect, useState } from 'react';
12
+ import { useSyncExternalStore } from 'use-sync-external-store/shim';
13
+ import { createEventEmitter, Deferred } from "./utils";
14
+ class AuthClientEnhancements {
15
+ constructor(authClient) {
16
+ this._state = {
17
+ isAuthenticated: false,
18
+ isInitialized: false,
19
+ tokens: {},
20
+ };
21
+ this.refreshQ = [];
22
+ this.eventEmitter = createEventEmitter();
23
+ this.subscribers = new Set();
24
+ this.subscribe = (subscription) => {
25
+ this.subscribers.add(subscription);
26
+ return () => this.subscribers.delete(subscription);
27
+ };
28
+ this.getSnapshot = () => {
29
+ return this._state;
30
+ };
31
+ this._authClient = authClient;
32
+ }
33
+ get isInitialized() {
34
+ return this._state.isInitialized;
35
+ }
36
+ get isAuthenticated() {
37
+ return this._state.isAuthenticated;
38
+ }
39
+ get tokens() {
40
+ return this._state.tokens;
41
+ }
42
+ init() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ var _a, _b, _c, _d;
45
+ try {
46
+ const prevTokens = yield ((_b = (_a = this._authClient).onInit) === null || _b === void 0 ? void 0 : _b.call(_a));
47
+ this.setState({
48
+ isInitialized: true,
49
+ isAuthenticated: !!prevTokens,
50
+ tokens: prevTokens || {},
51
+ });
52
+ this.emit("initSuccess", undefined);
53
+ }
54
+ catch (error) {
55
+ this.setState({
56
+ isInitialized: false,
57
+ });
58
+ this.emit("initFailed", error);
59
+ }
60
+ yield ((_d = (_c = this._authClient).onPostInit) === null || _d === void 0 ? void 0 : _d.call(_c));
61
+ return this.isInitialized;
62
+ });
63
+ }
64
+ login(...params) {
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ var _a, _b, _c, _d;
67
+ this.emit("loginStarted", undefined);
68
+ yield ((_b = (_a = this._authClient).onPreLogin) === null || _b === void 0 ? void 0 : _b.call(_a));
69
+ let isSuccess = false;
70
+ try {
71
+ const tokens = yield this._authClient.onLogin(...params);
72
+ this.setState({
73
+ isAuthenticated: !!tokens,
74
+ tokens,
75
+ });
76
+ this.emit("loginSuccess", undefined);
77
+ isSuccess = true;
78
+ }
79
+ catch (err) {
80
+ this.setState({
81
+ isAuthenticated: false,
82
+ tokens: {},
83
+ });
84
+ this.emit("loginFailed", err);
85
+ isSuccess = false;
86
+ }
87
+ yield ((_d = (_c = this._authClient).onPostLogin) === null || _d === void 0 ? void 0 : _d.call(_c, isSuccess));
88
+ return this.isAuthenticated;
89
+ });
90
+ }
91
+ refresh(minValidity) {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ const deferred = new Deferred();
94
+ this.runRefresh(deferred, minValidity);
95
+ return deferred.getPromise();
96
+ });
97
+ }
98
+ logout() {
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ var _a, _b, _c, _d, _e, _f;
101
+ this.emit("logoutStarted", undefined);
102
+ yield ((_b = (_a = this._authClient).onPreLogout) === null || _b === void 0 ? void 0 : _b.call(_a));
103
+ let isSuccess = false;
104
+ try {
105
+ yield ((_d = (_c = this._authClient).onLogout) === null || _d === void 0 ? void 0 : _d.call(_c));
106
+ this.setState({
107
+ isAuthenticated: false,
108
+ tokens: {},
109
+ });
110
+ this.emit("logoutSuccess", undefined);
111
+ isSuccess = true;
112
+ }
113
+ catch (err) {
114
+ this.emit("logoutFailed", err);
115
+ isSuccess = false;
116
+ }
117
+ yield ((_f = (_e = this._authClient).onPostLogout) === null || _f === void 0 ? void 0 : _f.call(_e, isSuccess));
118
+ });
119
+ }
120
+ on(eventName, listener) {
121
+ this.eventEmitter.on(eventName, listener);
122
+ }
123
+ off(eventName, listener) {
124
+ this.eventEmitter.off(eventName, listener);
125
+ }
126
+ setState(stateUpdate) {
127
+ this._state = Object.assign(Object.assign({}, this._state), stateUpdate);
128
+ this.notifySubscribers();
129
+ }
130
+ runRefresh(deferred, minValidity) {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ var _a, _b, _c, _d, _e, _f, _g;
133
+ this.refreshQ.push(deferred);
134
+ if (this.refreshQ.length !== 1) {
135
+ return;
136
+ }
137
+ this.emit("refreshStarted", undefined);
138
+ yield ((_b = (_a = this._authClient).onPreRefresh) === null || _b === void 0 ? void 0 : _b.call(_a));
139
+ let isAuthenticated = false;
140
+ let tokens = {};
141
+ try {
142
+ tokens = (_e = (yield ((_d = (_c = this._authClient).onRefresh) === null || _d === void 0 ? void 0 : _d.call(_c, this.tokens, minValidity)))) !== null && _e !== void 0 ? _e : {};
143
+ isAuthenticated = true;
144
+ this.emit("refreshSuccess", undefined);
145
+ }
146
+ catch (err) {
147
+ isAuthenticated = false;
148
+ this.emit("refreshFailed", err);
149
+ }
150
+ this.setState({
151
+ isAuthenticated,
152
+ tokens,
153
+ });
154
+ yield ((_g = (_f = this._authClient).onPostRefresh) === null || _g === void 0 ? void 0 : _g.call(_f, isAuthenticated));
155
+ for (let p = this.refreshQ.pop(); p != null; p = this.refreshQ.pop()) {
156
+ p.resolve(isAuthenticated);
157
+ }
158
+ });
159
+ }
160
+ emit(eventName, error) {
161
+ this.eventEmitter.emit(eventName, error);
162
+ }
163
+ notifySubscribers() {
164
+ this.subscribers.forEach((s) => {
165
+ try {
166
+ s();
167
+ }
168
+ catch (_a) { }
169
+ });
170
+ }
171
+ }
172
+ export function wrapAuthClient(authClient) {
173
+ Object.setPrototypeOf(AuthClientEnhancements.prototype, authClient);
174
+ return new AuthClientEnhancements(authClient);
175
+ }
176
+ export function createAuth(authClient) {
177
+ const authContext = createContext(null);
178
+ const enhancedAuthClient = wrapAuthClient(authClient);
179
+ const AuthProvider = ({ children, ErrorComponent, LoadingComponent }) => {
180
+ const [isInitFailed, setInitFailed] = useState(false);
181
+ const { isAuthenticated, isInitialized } = useSyncExternalStore(enhancedAuthClient.subscribe, enhancedAuthClient.getSnapshot);
182
+ useEffect(() => {
183
+ function initAuthClient() {
184
+ return __awaiter(this, void 0, void 0, function* () {
185
+ const initSuccess = yield enhancedAuthClient.init();
186
+ setInitFailed(!initSuccess);
187
+ });
188
+ }
189
+ initAuthClient();
190
+ }, []);
191
+ if (!!ErrorComponent && isInitFailed) {
192
+ return ErrorComponent;
193
+ }
194
+ if (!!LoadingComponent && !isInitialized) {
195
+ return LoadingComponent;
196
+ }
197
+ return (_jsx(authContext.Provider, { value: {
198
+ authClient: enhancedAuthClient,
199
+ isAuthenticated,
200
+ isInitialized,
201
+ }, children: children }));
202
+ };
203
+ const useAuthClient = function () {
204
+ const ctx = useContext(authContext);
205
+ if (!ctx) {
206
+ throw new Error('useAuthClient hook should be used inside AuthProvider');
207
+ }
208
+ return ctx.authClient;
209
+ };
210
+ return {
211
+ AuthProvider,
212
+ authClient: enhancedAuthClient,
213
+ useAuthClient,
214
+ };
215
+ }