@go-avro/avro-js 0.0.2-beta.76 → 0.0.2-beta.78

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.
@@ -3,6 +3,7 @@ export declare class AuthManager {
3
3
  private storages;
4
4
  private baseUrl;
5
5
  private tokenRefreshedCallbacks;
6
+ private tokenRefreshFailedCallbacks;
6
7
  constructor({ baseUrl, storage, }: {
7
8
  baseUrl: string;
8
9
  storage: TokenStorage | TokenStorage[];
@@ -11,6 +12,7 @@ export declare class AuthManager {
11
12
  fetchNewTokens(): Promise<Tokens>;
12
13
  accessToken(): Promise<string | undefined>;
13
14
  onTokenRefreshed(callback: (accessToken: string) => void): void;
15
+ onTokenRefreshFailed(callback: () => void): void;
14
16
  refreshTokens(): Promise<Tokens | null>;
15
17
  setTokens(tokens: Tokens): Promise<void>;
16
18
  clearTokens(): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  export class AuthManager {
2
2
  constructor({ baseUrl, storage, }) {
3
3
  this.tokenRefreshedCallbacks = [];
4
+ this.tokenRefreshFailedCallbacks = [];
4
5
  this.storages = Array.isArray(storage) ? storage : [storage];
5
6
  if (this.storages.length === 0) {
6
7
  throw new Error('At least one token storage must be provided');
@@ -92,6 +93,9 @@ export class AuthManager {
92
93
  onTokenRefreshed(callback) {
93
94
  this.tokenRefreshedCallbacks.push(callback);
94
95
  }
96
+ onTokenRefreshFailed(callback) {
97
+ this.tokenRefreshFailedCallbacks.push(callback);
98
+ }
95
99
  async refreshTokens() {
96
100
  try {
97
101
  const newToken = await this.fetchNewTokens();
@@ -103,6 +107,7 @@ export class AuthManager {
103
107
  return newToken;
104
108
  }
105
109
  catch (error) {
110
+ this.tokenRefreshFailedCallbacks.forEach(cb => cb());
106
111
  console.error('Failed to refresh tokens:', error);
107
112
  return null;
108
113
  }
@@ -246,6 +246,7 @@ declare module '../client/QueryClient' {
246
246
  export declare class AvroQueryClient {
247
247
  protected config: Required<AvroQueryClientConfig>;
248
248
  readonly socket: Socket;
249
+ _isAuthenticated: boolean;
249
250
  constructor(config: AvroQueryClientConfig);
250
251
  emit(eventName: string, data: unknown): void;
251
252
  on<T>(eventName: string, callback: (data: T) => void): void;
@@ -254,13 +255,16 @@ export declare class AvroQueryClient {
254
255
  post<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
255
256
  put<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
256
257
  delete<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
257
- login(data: {
258
+ useLogin(): ReturnType<typeof useMutation<LoginResponse, StandardError, {
258
259
  username: string;
259
260
  password: string;
260
261
  code?: string;
261
- }, cancelToken?: CancelToken): Promise<LoginResponse>;
262
+ cancelToken?: CancelToken;
263
+ }>>;
262
264
  setTokens(tokens: Tokens): Promise<void>;
263
265
  clearTokens(): Promise<void>;
266
+ isAuthenticated(): boolean;
267
+ isAuthenticatedAsync(): Promise<boolean>;
264
268
  useLogout(): ReturnType<typeof useMutation<void, StandardError, CancelToken | undefined>>;
265
269
  fetchJobs(companyGuid: string, body?: {
266
270
  amt?: number;
@@ -4,6 +4,7 @@ import { LoginResponse } from '../types/api';
4
4
  import { StandardError } from '../types/error';
5
5
  export class AvroQueryClient {
6
6
  constructor(config) {
7
+ this._isAuthenticated = false;
7
8
  this.config = {
8
9
  baseUrl: config.baseUrl,
9
10
  authManager: config.authManager,
@@ -11,6 +12,9 @@ export class AvroQueryClient {
11
12
  retryStrategy: config.retryStrategy ?? 'fixed',
12
13
  timeout: config.timeout ?? 0,
13
14
  };
15
+ config.authManager.isAuthenticated().then(isAuth => {
16
+ this._isAuthenticated = isAuth;
17
+ });
14
18
  this.socket = io(config.baseUrl, { autoConnect: false, transports: ["websocket"], });
15
19
  if (!this.socket.connected) {
16
20
  this.config.authManager.accessToken().then(token => {
@@ -20,6 +24,7 @@ export class AvroQueryClient {
20
24
  });
21
25
  }
22
26
  this.socket.on('connect', () => {
27
+ this._isAuthenticated = true;
23
28
  console.log(`Socket connected with ID: ${this.socket?.id}`);
24
29
  });
25
30
  this.socket.on('disconnect', (reason) => {
@@ -30,11 +35,18 @@ export class AvroQueryClient {
30
35
  });
31
36
  this.config.authManager.onTokenRefreshed((newAccessToken) => {
32
37
  if (this.socket && newAccessToken) {
38
+ this._isAuthenticated = true;
33
39
  console.log('Access token refreshed, updating socket auth...');
34
40
  this.socket.auth = { token: newAccessToken };
35
41
  this.socket.disconnect().connect();
36
42
  }
37
43
  });
44
+ config.authManager.onTokenRefreshFailed(() => {
45
+ this._isAuthenticated = false;
46
+ if (this.socket && this.socket.connected) {
47
+ this.socket.disconnect();
48
+ }
49
+ });
38
50
  }
39
51
  emit(eventName, data) {
40
52
  if (!this.socket?.connected) {
@@ -61,26 +73,32 @@ export class AvroQueryClient {
61
73
  delete(path, cancelToken, headers = {}, progressUpdateCallback) {
62
74
  return this._xhr('DELETE', path, null, cancelToken, headers, false, this.config.maxRetries, progressUpdateCallback);
63
75
  }
64
- login(data, cancelToken) {
65
- return this._fetch('POST', '/login', data, cancelToken)
66
- .then(resp => {
67
- if (!resp || !('access_token' in resp)) {
68
- if (resp.msg === "TOTP email sent") {
69
- return LoginResponse.NEEDS_TOTP;
76
+ useLogin() {
77
+ const queryClient = useQueryClient();
78
+ return useMutation({
79
+ mutationFn: async ({ username, password, code, cancelToken }) => {
80
+ const resp = await this._fetch('POST', '/login', { username, password, code }, cancelToken);
81
+ if (!resp || !('access_token' in resp)) {
82
+ if (resp.msg === "TOTP email sent") {
83
+ return LoginResponse.NEEDS_TOTP;
84
+ }
85
+ throw new StandardError(401, 'Invalid login response');
70
86
  }
71
- throw new StandardError(401, 'Invalid login response');
72
- }
73
- this.socket.auth = { token: resp.access_token };
74
- if (!this.socket.connected) {
75
- this.socket.connect();
76
- }
77
- return this.config.authManager.setTokens({ access_token: resp.access_token, refresh_token: resp.refresh_token }).then(() => {
87
+ this.socket.auth = { token: resp.access_token };
88
+ if (!this.socket.connected) {
89
+ this.socket.connect();
90
+ }
91
+ await this.config.authManager.setTokens({ access_token: resp.access_token, refresh_token: resp.refresh_token });
78
92
  return LoginResponse.SUCCESS;
79
- });
80
- })
81
- .catch(err => {
82
- console.error('Login failed:', err);
83
- throw new StandardError(401, 'Login failed');
93
+ },
94
+ onSettled: () => {
95
+ queryClient.invalidateQueries();
96
+ },
97
+ onError: (err) => {
98
+ this.config.authManager.clearTokens();
99
+ console.error('Login failed:', err);
100
+ throw new StandardError(401, 'Login failed');
101
+ }
84
102
  });
85
103
  }
86
104
  setTokens(tokens) {
@@ -89,6 +107,12 @@ export class AvroQueryClient {
89
107
  clearTokens() {
90
108
  return this.config.authManager.clearTokens();
91
109
  }
110
+ isAuthenticated() {
111
+ return this._isAuthenticated;
112
+ }
113
+ isAuthenticatedAsync() {
114
+ return this.config.authManager.isAuthenticated();
115
+ }
92
116
  useLogout() {
93
117
  const queryClient = useQueryClient();
94
118
  return useMutation({
@@ -100,6 +124,7 @@ export class AvroQueryClient {
100
124
  }
101
125
  },
102
126
  onSettled: () => {
127
+ this._isAuthenticated = false;
103
128
  queryClient.invalidateQueries();
104
129
  },
105
130
  onError: (err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.2-beta.76",
3
+ "version": "0.0.2-beta.78",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",