@go-avro/avro-js 0.0.2-beta.60 → 0.0.2-beta.62

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.
@@ -2,6 +2,7 @@ import { TokenStorage, Tokens } from '../types/auth';
2
2
  export declare class AuthManager {
3
3
  private storages;
4
4
  private baseUrl;
5
+ private tokenRefreshedCallbacks;
5
6
  constructor({ baseUrl, storage, }: {
6
7
  baseUrl: string;
7
8
  storage: TokenStorage | TokenStorage[];
@@ -9,6 +10,7 @@ export declare class AuthManager {
9
10
  isAuthenticated(): Promise<boolean>;
10
11
  fetchNewTokens(): Promise<Tokens>;
11
12
  accessToken(): Promise<string | undefined>;
13
+ onTokenRefreshed(callback: (accessToken: string) => void): void;
12
14
  refreshTokens(): Promise<Tokens | null>;
13
15
  setTokens(tokens: Tokens): Promise<void>;
14
16
  clearTokens(): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  export class AuthManager {
2
2
  constructor({ baseUrl, storage, }) {
3
+ this.tokenRefreshedCallbacks = [];
3
4
  this.storages = Array.isArray(storage) ? storage : [storage];
4
5
  if (this.storages.length === 0) {
5
6
  throw new Error('At least one token storage must be provided');
@@ -88,10 +89,17 @@ export class AuthManager {
88
89
  const newToken = await this.refreshTokens();
89
90
  return newToken?.access_token;
90
91
  }
92
+ onTokenRefreshed(callback) {
93
+ this.tokenRefreshedCallbacks.push(callback);
94
+ }
91
95
  async refreshTokens() {
92
96
  try {
93
97
  const newToken = await this.fetchNewTokens();
94
98
  await Promise.all(this.storages.map(s => s.set(newToken)));
99
+ this.tokenRefreshedCallbacks.forEach(cb => {
100
+ if (newToken?.access_token)
101
+ cb(newToken.access_token);
102
+ });
95
103
  return newToken;
96
104
  }
97
105
  catch (error) {
@@ -4,6 +4,7 @@ import { _Event, ApiInfo, Bill, Break, Company, Job, LineItem, Route, ServiceMon
4
4
  import { Tokens } from '../types/auth';
5
5
  import { CancelToken, RetryStrategy } from '../types/client';
6
6
  import { StandardError } from '../types/error';
7
+ import { Socket } from 'socket.io-client';
7
8
  export interface AvroQueryClientConfig {
8
9
  baseUrl: string;
9
10
  authManager: AuthManager;
@@ -107,10 +108,7 @@ declare module '../client/QueryClient' {
107
108
  id: string;
108
109
  }, StandardError, {
109
110
  sessionId: string;
110
- breakData: {
111
- start_time: string;
112
- end_time?: string;
113
- };
111
+ breakData: Partial<Break>;
114
112
  }>>;
115
113
  useUpdateEvent(): ReturnType<typeof useMutation<{
116
114
  msg: string;
@@ -204,7 +202,11 @@ declare module '../client/QueryClient' {
204
202
  }
205
203
  export declare class AvroQueryClient {
206
204
  protected config: Required<AvroQueryClientConfig>;
205
+ readonly socket: Socket;
207
206
  constructor(config: AvroQueryClientConfig);
207
+ emit(eventName: string, data: unknown): void;
208
+ on<T>(eventName: string, callback: (data: T) => void): void;
209
+ off(eventName: string, callback?: Function): void;
208
210
  get<T>(path: string, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
209
211
  post<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
210
212
  put<T>(path: string, data: any, cancelToken?: CancelToken, headers?: Record<string, string>, progressUpdateCallback?: (loaded: number, total: number) => void): Promise<T>;
@@ -212,6 +214,7 @@ export declare class AvroQueryClient {
212
214
  login(data: {
213
215
  username: string;
214
216
  password: string;
217
+ code?: string;
215
218
  }, cancelToken?: CancelToken): Promise<Boolean>;
216
219
  setTokens(tokens: Tokens): Promise<void>;
217
220
  clearTokens(): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { useMutation, useQueryClient } from '@tanstack/react-query';
2
2
  import { StandardError } from '../types/error';
3
+ import io from 'socket.io-client';
3
4
  export class AvroQueryClient {
4
5
  constructor(config) {
5
6
  this.config = {
@@ -9,6 +10,43 @@ export class AvroQueryClient {
9
10
  retryStrategy: config.retryStrategy ?? 'fixed',
10
11
  timeout: config.timeout ?? 0,
11
12
  };
13
+ this.socket = io(config.baseUrl, { autoConnect: false, transports: ["websocket"], });
14
+ if (!this.socket.connected) {
15
+ this.config.authManager.accessToken().then(token => {
16
+ console.log('Initializing socket connection with token...');
17
+ this.socket.auth = { token: token };
18
+ this.socket.connect();
19
+ });
20
+ }
21
+ this.socket.on('connect', () => {
22
+ console.log(`Socket connected with ID: ${this.socket?.id}`);
23
+ });
24
+ this.socket.on('disconnect', (reason) => {
25
+ console.log(`Socket disconnected: ${reason}`);
26
+ });
27
+ this.socket.on('connect_error', (err) => {
28
+ console.error(`Socket connection error: ${err.message}`);
29
+ });
30
+ this.config.authManager.onTokenRefreshed((newAccessToken) => {
31
+ if (this.socket && newAccessToken) {
32
+ console.log('Access token refreshed, updating socket auth...');
33
+ this.socket.auth = { token: newAccessToken };
34
+ this.socket.disconnect().connect();
35
+ }
36
+ });
37
+ }
38
+ emit(eventName, data) {
39
+ if (!this.socket?.connected) {
40
+ console.error('Socket is not connected. Cannot emit event.');
41
+ return;
42
+ }
43
+ this.socket.emit(eventName, data);
44
+ }
45
+ on(eventName, callback) {
46
+ this.socket?.on(eventName, callback);
47
+ }
48
+ off(eventName, callback) {
49
+ this.socket?.off(eventName, callback);
12
50
  }
13
51
  get(path, cancelToken, headers = {}, progressUpdateCallback) {
14
52
  return this._xhr('GET', path, null, cancelToken, headers, true, this.config.maxRetries, progressUpdateCallback);
@@ -28,6 +66,10 @@ export class AvroQueryClient {
28
66
  if (!tokens || !tokens.access_token || !tokens.refresh_token) {
29
67
  throw new StandardError(401, 'Invalid login response');
30
68
  }
69
+ this.socket.auth = { token: tokens.access_token };
70
+ if (!this.socket.connected) {
71
+ this.socket.connect();
72
+ }
31
73
  return this.config.authManager.setTokens(tokens).then(() => true);
32
74
  })
33
75
  .catch(err => {
@@ -44,8 +86,13 @@ export class AvroQueryClient {
44
86
  useLogout() {
45
87
  const queryClient = useQueryClient();
46
88
  return useMutation({
47
- mutationFn: (cancelToken) => this._fetch('POST', '/logout', null, cancelToken)
48
- .then(() => this.config.authManager.clearTokens()),
89
+ mutationFn: async (cancelToken) => {
90
+ await this._fetch('POST', '/logout', null, cancelToken);
91
+ await this.config.authManager.clearTokens();
92
+ if (this.socket && this.socket.connected) {
93
+ this.socket.disconnect();
94
+ }
95
+ },
49
96
  onSettled: () => {
50
97
  queryClient.invalidateQueries();
51
98
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.2-beta.60",
3
+ "version": "0.0.2-beta.62",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -53,6 +53,7 @@
53
53
  "access": "public"
54
54
  },
55
55
  "dependencies": {
56
- "@tanstack/react-query": "^5.90.2"
56
+ "@tanstack/react-query": "^5.90.2",
57
+ "socket.io-client": "^4.8.1"
57
58
  }
58
59
  }