@go-avro/avro-js 0.0.2-beta.60 → 0.0.2-beta.61
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>;
|
package/dist/auth/AuthManager.js
CHANGED
|
@@ -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>;
|
|
@@ -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) =>
|
|
48
|
-
.
|
|
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.
|
|
3
|
+
"version": "0.0.2-beta.61",
|
|
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
|
}
|