@go-avro/avro-js 0.0.2-beta.14 → 0.0.2-beta.140

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.
Files changed (57) hide show
  1. package/README.md +1 -0
  2. package/dist/auth/AuthManager.d.ts +12 -3
  3. package/dist/auth/AuthManager.js +56 -12
  4. package/dist/auth/storage.d.ts +8 -8
  5. package/dist/auth/storage.js +19 -14
  6. package/dist/client/AvroQueryClientProvider.d.ts +14 -0
  7. package/dist/client/AvroQueryClientProvider.js +32 -0
  8. package/dist/client/QueryClient.d.ts +447 -15
  9. package/dist/client/QueryClient.js +405 -201
  10. package/dist/client/core/fetch.d.ts +1 -0
  11. package/dist/client/core/fetch.js +62 -0
  12. package/dist/client/core/utils.d.ts +1 -0
  13. package/dist/client/core/utils.js +14 -0
  14. package/dist/client/core/xhr.d.ts +1 -0
  15. package/dist/client/core/xhr.js +84 -0
  16. package/dist/client/hooks/analytics.d.ts +1 -0
  17. package/dist/client/hooks/analytics.js +26 -0
  18. package/dist/client/hooks/avro.d.ts +1 -0
  19. package/dist/client/hooks/avro.js +9 -0
  20. package/dist/client/hooks/bills.d.ts +1 -0
  21. package/dist/client/hooks/bills.js +165 -0
  22. package/dist/client/hooks/chats.d.ts +1 -0
  23. package/dist/client/hooks/chats.js +37 -0
  24. package/dist/client/hooks/companies.d.ts +1 -0
  25. package/dist/client/hooks/companies.js +140 -0
  26. package/dist/client/hooks/events.d.ts +1 -0
  27. package/dist/client/hooks/events.js +308 -0
  28. package/dist/client/hooks/groups.d.ts +1 -0
  29. package/dist/client/hooks/groups.js +130 -0
  30. package/dist/client/hooks/jobs.d.ts +1 -0
  31. package/dist/client/hooks/jobs.js +213 -0
  32. package/dist/client/hooks/messages.d.ts +1 -0
  33. package/dist/client/hooks/messages.js +30 -0
  34. package/dist/client/hooks/months.d.ts +1 -0
  35. package/dist/client/hooks/months.js +93 -0
  36. package/dist/client/hooks/plans.d.ts +1 -0
  37. package/dist/client/hooks/plans.js +8 -0
  38. package/dist/client/hooks/root.d.ts +1 -0
  39. package/dist/client/hooks/root.js +8 -0
  40. package/dist/client/hooks/routes.d.ts +1 -0
  41. package/dist/client/hooks/routes.js +167 -0
  42. package/dist/client/hooks/sessions.d.ts +1 -0
  43. package/dist/client/hooks/sessions.js +175 -0
  44. package/dist/client/hooks/skills.d.ts +1 -0
  45. package/dist/client/hooks/skills.js +123 -0
  46. package/dist/client/hooks/teams.d.ts +1 -0
  47. package/dist/client/hooks/teams.js +128 -0
  48. package/dist/client/hooks/users.d.ts +1 -0
  49. package/dist/client/hooks/users.js +104 -0
  50. package/dist/index.d.ts +24 -1
  51. package/dist/index.js +24 -1
  52. package/dist/types/api.d.ts +138 -34
  53. package/dist/types/api.js +10 -1
  54. package/dist/types/auth.d.ts +0 -5
  55. package/dist/types/cache.d.ts +9 -0
  56. package/dist/types/cache.js +1 -0
  57. package/package.json +6 -4
@@ -1,6 +1,14 @@
1
+ import io from 'socket.io-client';
2
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
3
+ import { LoginResponse } from '../types/api';
1
4
  import { StandardError } from '../types/error';
2
5
  export class AvroQueryClient {
3
6
  constructor(config) {
7
+ this._isAuthenticated = false;
8
+ this.companyId = null;
9
+ this.company = null;
10
+ this.initialized = false;
11
+ this.initializedListeners = [];
4
12
  this.config = {
5
13
  baseUrl: config.baseUrl,
6
14
  authManager: config.authManager,
@@ -8,234 +16,311 @@ export class AvroQueryClient {
8
16
  retryStrategy: config.retryStrategy ?? 'fixed',
9
17
  timeout: config.timeout ?? 0,
10
18
  };
19
+ this.socket = io(config.baseUrl, { autoConnect: false, transports: ["websocket"], });
20
+ config.authManager.isAuthenticated().then(isAuth => {
21
+ this._isAuthenticated = isAuth;
22
+ this.getCompanyId().then(id => {
23
+ this.companyId = id;
24
+ this.updateInitialized();
25
+ });
26
+ });
27
+ if (!this.socket.connected) {
28
+ this.config.authManager.accessToken().then(token => {
29
+ console.log('Initializing socket connection with token...');
30
+ this.socket.auth = { token: token };
31
+ this.socket.connect();
32
+ });
33
+ }
34
+ this.socket.on('connect', () => {
35
+ this._isAuthenticated = true;
36
+ console.log(`Socket connected with ID: ${this.socket?.id}`);
37
+ this.updateInitialized();
38
+ });
39
+ this.socket.on('disconnect', (reason) => {
40
+ console.log(`Socket disconnected: ${reason}`);
41
+ this.updateInitialized();
42
+ });
43
+ this.socket.on('connect_error', (err) => {
44
+ console.error(`Socket connection error: ${err.message}`);
45
+ });
46
+ this.config.authManager.onTokenRefreshed((newAccessToken) => {
47
+ if (this.socket && newAccessToken) {
48
+ this._isAuthenticated = true;
49
+ console.log('Access token refreshed, updating socket auth...');
50
+ this.socket.auth = { token: newAccessToken };
51
+ this.socket.disconnect().connect();
52
+ }
53
+ });
54
+ config.authManager.onTokenRefreshFailed(() => {
55
+ this._isAuthenticated = false;
56
+ if (this.socket && this.socket.connected) {
57
+ this.socket.disconnect();
58
+ }
59
+ });
60
+ }
61
+ computeInitialized() {
62
+ return !!(this.socket?.connected && this.companyId !== null);
11
63
  }
12
- getDelay(strategy, attempt) {
13
- if (typeof strategy === 'function') {
14
- return strategy(attempt);
64
+ updateInitialized() {
65
+ const next = this.computeInitialized();
66
+ if (this.initialized !== next) {
67
+ this.initialized = next;
68
+ this.initializedListeners.forEach(cb => {
69
+ try {
70
+ cb(next);
71
+ }
72
+ catch (_) {
73
+ console.error(_);
74
+ }
75
+ });
15
76
  }
16
- else if (strategy === 'fixed') {
17
- return 1000;
77
+ }
78
+ onInitializedChange(cb) {
79
+ this.initializedListeners.push(cb);
80
+ // call immediately with current value
81
+ try {
82
+ cb(this.initialized);
18
83
  }
19
- else if (strategy === 'exponential') {
20
- return Math.pow(2, attempt) * 100;
84
+ catch (_) {
85
+ console.error(_);
21
86
  }
22
- throw new Error(`Invalid retry strategy: ${strategy}`);
87
+ return () => this.offInitializedChange(cb);
23
88
  }
24
- _xhr(method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
25
- const checkCancelled = () => {
26
- if (cancelToken?.isCancelled()) {
27
- return new StandardError(0, 'Request cancelled');
28
- }
29
- return null;
30
- };
31
- return this.config.authManager.accessToken().then(token => {
32
- return new Promise((resolve, reject) => {
33
- const cancelErr = checkCancelled();
34
- if (cancelErr)
35
- return reject(cancelErr);
36
- const xhr = new XMLHttpRequest();
37
- const url = this.config.baseUrl + path;
38
- xhr.open(method, url, true);
39
- if (token) {
40
- xhr.setRequestHeader('Authorization', `Bearer ${token}`);
41
- }
42
- Object.entries(headers).forEach(([key, value]) => {
43
- xhr.setRequestHeader(key, value);
44
- });
45
- xhr.onload = () => {
46
- const cancelErr = checkCancelled();
47
- if (cancelErr)
48
- return reject(cancelErr);
49
- if (xhr.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
50
- this.config.authManager
51
- .refreshTokens()
52
- .then(() => {
53
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
54
- })
55
- .catch(() => {
56
- reject(new StandardError(401, 'Unauthorized (refresh failed)'));
57
- });
58
- return;
59
- }
60
- if (xhr.status >= 200 && xhr.status < 300) {
61
- try {
62
- resolve(JSON.parse(xhr.responseText));
63
- }
64
- catch {
65
- resolve(xhr.responseText);
66
- }
67
- }
68
- else {
69
- if (retryCount < this.config.maxRetries) {
70
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
71
- setTimeout(() => {
72
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
73
- }, delay);
74
- }
75
- else {
76
- let msg = xhr.statusText;
77
- try {
78
- const parsed = JSON.parse(xhr.responseText);
79
- msg = parsed.message || msg;
80
- }
81
- catch {
82
- console.warn('Failed to parse error response:', xhr.responseText);
83
- }
84
- reject(new StandardError(xhr.status, msg));
85
- }
86
- }
87
- };
88
- xhr.onerror = () => {
89
- if (retryCount < this.config.maxRetries) {
90
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
91
- setTimeout(() => {
92
- this._xhr(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1).then(resolve, reject);
93
- }, delay);
94
- }
95
- else {
96
- reject(new StandardError(0, 'Network Error'));
89
+ offInitializedChange(cb) {
90
+ this.initializedListeners = this.initializedListeners.filter(c => c !== cb);
91
+ }
92
+ isInitialized() {
93
+ return this.initialized;
94
+ }
95
+ emit(eventName, data) {
96
+ if (!this.socket?.connected) {
97
+ console.error('Socket is not connected. Cannot emit event.');
98
+ return;
99
+ }
100
+ this.socket.emit(eventName, data);
101
+ }
102
+ on(eventName, callback) {
103
+ this.socket?.on(eventName, callback);
104
+ }
105
+ off(eventName, callback) {
106
+ this.socket?.off(eventName, callback);
107
+ }
108
+ get(path, cancelToken, headers = {}, progressUpdateCallback) {
109
+ return this._xhr('GET', path, null, cancelToken, headers, true, this.config.maxRetries, progressUpdateCallback);
110
+ }
111
+ post(path, data, cancelToken, headers = {}, progressUpdateCallback) {
112
+ return this._xhr('POST', path, data, cancelToken, headers, false, this.config.maxRetries, progressUpdateCallback);
113
+ }
114
+ put(path, data, cancelToken, headers = {}, progressUpdateCallback) {
115
+ return this._xhr('PUT', path, data, cancelToken, headers, true, this.config.maxRetries, progressUpdateCallback);
116
+ }
117
+ delete(path, cancelToken, headers = {}, progressUpdateCallback) {
118
+ return this._xhr('DELETE', path, null, cancelToken, headers, false, this.config.maxRetries, progressUpdateCallback);
119
+ }
120
+ useLogin() {
121
+ const queryClient = this.getQueryClient();
122
+ return useMutation({
123
+ mutationFn: async ({ username, password, code, cancelToken }) => {
124
+ const resp = await this.post('/login', JSON.stringify({ username, password, code }), cancelToken, { 'Content-Type': 'application/json' });
125
+ if (!resp || !('access_token' in resp)) {
126
+ if (resp.msg === "TOTP required") {
127
+ return LoginResponse.NEEDS_TOTP;
97
128
  }
98
- };
99
- if (this.config.timeout) {
100
- xhr.timeout = this.config.timeout;
101
- xhr.ontimeout = () => reject(new StandardError(0, 'Request timed out'));
129
+ throw new StandardError(401, 'Invalid login response');
102
130
  }
103
- xhr.send(body);
104
- });
105
- });
106
- }
107
- _fetch(method, path, body, cancelToken, headers = {}, isIdempotent = false, retryCount = 0) {
108
- const checkCancelled = () => {
109
- try {
110
- if (cancelToken?.isCancelled()) {
111
- return new StandardError(0, 'Request cancelled');
131
+ this._isAuthenticated = true;
132
+ this.socket.auth = { token: resp.access_token };
133
+ if (!this.socket.connected) {
134
+ this.socket.connect();
112
135
  }
136
+ await this.config.authManager.setTokens({ access_token: resp.access_token, refresh_token: resp.refresh_token });
137
+ return LoginResponse.SUCCESS;
138
+ },
139
+ onSettled: () => {
140
+ queryClient.invalidateQueries();
141
+ },
142
+ onError: (err) => {
143
+ this.config.authManager.clearCache();
144
+ throw new StandardError(401, err.message || 'Login failed');
113
145
  }
114
- catch (error) {
115
- throw new StandardError(0, `Error checking cancellation (${typeof cancelToken}): ${error}`);
146
+ });
147
+ }
148
+ useRequestCode() {
149
+ const queryClient = this.getQueryClient();
150
+ return useMutation({
151
+ mutationFn: async ({ username, email, cancelToken }) => {
152
+ const resp = await this.post('/code', JSON.stringify({ username, email }), cancelToken, { 'Content-Type': 'application/json' });
153
+ return resp;
154
+ },
155
+ onSettled: () => {
156
+ queryClient.invalidateQueries();
157
+ },
158
+ onError: (err) => {
159
+ throw new StandardError(err.status, err.message || 'Request code failed');
116
160
  }
117
- return null;
118
- };
119
- return this.config.authManager.accessToken().then(token => {
120
- const cancelErr = checkCancelled();
121
- if (cancelErr)
122
- return Promise.reject(cancelErr);
123
- const url = this.config.baseUrl + path;
124
- const requestHeaders = {
125
- 'Content-Type': 'application/json',
126
- ...headers,
127
- };
128
- if (token) {
129
- requestHeaders['Authorization'] = `Bearer ${token}`;
161
+ });
162
+ }
163
+ useUpdatePassword() {
164
+ const queryClient = this.getQueryClient();
165
+ return useMutation({
166
+ mutationFn: async ({ username, email, code, newPassword, cancelToken }) => {
167
+ await this.post(`/user/${username ?? email}/password`, JSON.stringify({ code, password: newPassword }), cancelToken, { 'Content-Type': 'application/json' });
168
+ },
169
+ onSettled: () => {
170
+ queryClient.invalidateQueries();
171
+ },
172
+ onError: (err) => {
173
+ throw new StandardError(err.status, err.message || 'Update password failed');
130
174
  }
131
- const options = {
132
- method,
133
- headers: requestHeaders,
134
- body: body ? JSON.stringify(body) : null,
135
- };
136
- return fetch(url, options).then(response => {
137
- if (response.status === 401 && this.config.authManager.refreshTokens && retryCount === 0) {
138
- return this.config.authManager
139
- .refreshTokens()
140
- .then(() => this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1))
141
- .catch(() => Promise.reject(new StandardError(401, 'Unauthorized (refresh failed)')));
142
- }
143
- if (!response.ok) {
144
- if (retryCount < this.config.maxRetries) {
145
- const delay = this.getDelay(this.config.retryStrategy, retryCount);
146
- return new Promise((resolve, reject) => {
147
- setTimeout(() => {
148
- this._fetch(method, path, body, cancelToken, headers, isIdempotent, retryCount + 1)
149
- .then(resolve)
150
- .catch(reject);
151
- }, delay);
152
- });
153
- }
154
- else {
155
- return response.text().then(text => {
156
- let msg = response.statusText;
157
- try {
158
- const parsed = JSON.parse(text);
159
- msg = parsed.message || msg;
160
- }
161
- catch {
162
- console.warn('Failed to parse error response:', text);
163
- }
164
- throw new StandardError(response.status, msg);
165
- });
175
+ });
176
+ }
177
+ useGoogleLogin() {
178
+ const queryClient = this.getQueryClient();
179
+ return useMutation({
180
+ mutationFn: async ({ token, cancelToken }) => {
181
+ const resp = await this._xhr('POST', `/google/authorize?token=${token}`, {}, cancelToken, { 'Content-Type': 'application/json' });
182
+ if (!resp || !('access_token' in resp)) {
183
+ if (resp.msg === "TOTP required") {
184
+ return LoginResponse.NEEDS_TOTP;
166
185
  }
186
+ throw new StandardError(401, 'Invalid Google login response');
167
187
  }
168
- return response.json();
169
- });
188
+ this._isAuthenticated = true;
189
+ this.socket.auth = { token: resp.access_token };
190
+ if (!this.socket.connected) {
191
+ this.socket.connect();
192
+ }
193
+ await this.config.authManager.setTokens({ access_token: resp.access_token, refresh_token: resp.refresh_token });
194
+ return LoginResponse.SUCCESS;
195
+ },
196
+ onSettled: () => {
197
+ queryClient.invalidateQueries();
198
+ },
199
+ onError: (err) => {
200
+ this.config.authManager.clearCache();
201
+ throw new StandardError(err.status, err.message || 'Google Login failed');
202
+ }
170
203
  });
171
204
  }
172
- get(path, cancelToken, headers = {}) {
173
- return this._xhr('GET', path, null, cancelToken, headers, true);
205
+ setTokens(tokens) {
206
+ return this.config.authManager.setTokens(tokens);
207
+ }
208
+ setCache(data) {
209
+ return this.config.authManager.setCache(data);
210
+ }
211
+ getCache(key) {
212
+ return this.config.authManager.getCache(key);
213
+ }
214
+ setCompanyId(companyId) {
215
+ this.companyId = companyId;
216
+ this.updateInitialized();
217
+ return this.config.authManager.setCompanyId(companyId);
218
+ }
219
+ getCompanyId() {
220
+ if (this.companyId) {
221
+ return Promise.resolve(this.companyId);
222
+ }
223
+ return this.config.authManager.getCompanyId();
224
+ }
225
+ clearCache() {
226
+ return this.config.authManager.clearCache();
174
227
  }
175
- post(path, data, cancelToken, headers = {}) {
176
- return this._xhr('POST', path, data, cancelToken, headers, false);
228
+ isAuthenticated() {
229
+ return this._isAuthenticated;
177
230
  }
178
- put(path, data, cancelToken, headers = {}) {
179
- return this._xhr('PUT', path, data, cancelToken, headers, true);
231
+ isAuthenticatedAsync() {
232
+ return this.config.authManager.isAuthenticated();
180
233
  }
181
- delete(path, cancelToken, headers = {}) {
182
- return this._xhr('DELETE', path, null, cancelToken, headers, false);
234
+ getQueryClient() {
235
+ return useQueryClient();
183
236
  }
184
- login(data, cancelToken) {
185
- return this._fetch('POST', '/login', data, cancelToken)
186
- .then(tokens => {
187
- if (!tokens || !tokens.access_token || !tokens.refresh_token) {
188
- throw new StandardError(401, 'Invalid login response');
237
+ useLogout() {
238
+ const queryClient = this.getQueryClient();
239
+ return useMutation({
240
+ mutationFn: async (cancelToken) => {
241
+ await this.post('/logout', null, cancelToken);
242
+ await this.config.authManager.clearCache();
243
+ if (this.socket && this.socket.connected) {
244
+ this.socket.disconnect();
245
+ }
246
+ },
247
+ onSettled: () => {
248
+ this._isAuthenticated = false;
249
+ this.clearCache();
250
+ queryClient.invalidateQueries();
251
+ },
252
+ onError: (err) => {
253
+ this.clearCache();
254
+ console.error('Logout failed:', err);
255
+ throw new StandardError(500, 'Logout failed');
256
+ }
257
+ });
258
+ }
259
+ fetchJobs(body = {}, cancelToken, headers = {}) {
260
+ if (!this.companyId || this.companyId.trim() === '') {
261
+ throw new StandardError(400, 'Company ID is required');
262
+ }
263
+ return this._fetch('POST', `/company/${this.companyId}/jobs`, JSON.stringify(body), cancelToken, {
264
+ ...headers,
265
+ 'Content-Type': 'application/json',
266
+ })
267
+ .then(response => {
268
+ if (!response || !Array.isArray(response)) {
269
+ throw new StandardError(400, 'Invalid jobs response');
189
270
  }
190
- return this.config.authManager.setTokens(tokens).then(() => true);
271
+ return response;
191
272
  })
192
273
  .catch(err => {
193
- console.error('Login failed:', err);
194
- throw new StandardError(401, 'Login failed');
274
+ console.error('Failed to fetch jobs:', err);
275
+ throw new StandardError(500, `Failed to fetch jobs: ${err.message ?? err}`);
195
276
  });
196
277
  }
197
- logout(cancelToken) {
198
- return this._fetch('POST', '/logout', null, cancelToken)
199
- .then(() => this.config.authManager.clearTokens())
278
+ fetchChats(body = {}, cancelToken, headers = {}) {
279
+ if (!this.companyId || this.companyId.trim() === '') {
280
+ throw new StandardError(400, 'Company ID is required');
281
+ }
282
+ return this._fetch('POST', `/company/${this.companyId}/chats`, JSON.stringify(body), cancelToken, {
283
+ ...headers,
284
+ 'Content-Type': 'application/json',
285
+ })
286
+ .then(response => {
287
+ if (!response || !Array.isArray(response)) {
288
+ throw new StandardError(400, 'Invalid chats response');
289
+ }
290
+ return response;
291
+ })
200
292
  .catch(err => {
201
- console.error('Logout failed:', err);
202
- throw new StandardError(500, 'Logout failed');
293
+ console.error('Failed to fetch chats:', err);
294
+ throw new StandardError(500, 'Failed to fetch chats');
203
295
  });
204
296
  }
205
- fetchJobs(companyGuid, amt = 50, knownIds = [], unknownIds = [], keyword = '', offset = 0, cancelToken, headers = {}) {
206
- const body = {
207
- amt,
208
- known_ids: knownIds,
209
- unknown_ids: unknownIds,
210
- query: keyword,
211
- };
212
- if (!companyGuid) {
213
- return Promise.reject(new StandardError(400, 'Company GUID is required'));
297
+ fetchMessages(chatId, body = {}, cancelToken, headers = {}) {
298
+ if (!chatId || chatId.trim() === '') {
299
+ throw new StandardError(400, 'Chat ID is required');
214
300
  }
215
- return this._fetch('POST', `/company/${companyGuid}/jobs?amt=${amt}&offset=${offset}`, body, cancelToken, headers)
301
+ return this._fetch('POST', `/chat/${chatId}/messages`, JSON.stringify(body), cancelToken, {
302
+ ...headers,
303
+ 'Content-Type': 'application/json',
304
+ })
216
305
  .then(response => {
217
306
  if (!response || !Array.isArray(response)) {
218
- throw new StandardError(400, 'Invalid jobs response');
307
+ throw new StandardError(400, 'Invalid messages response');
219
308
  }
220
309
  return response;
221
310
  })
222
311
  .catch(err => {
223
- console.error('Failed to fetch jobs:', err);
224
- throw new StandardError(500, 'Failed to fetch jobs');
312
+ console.error('Failed to fetch messages:', err);
313
+ throw new StandardError(500, 'Failed to fetch messages');
225
314
  });
226
315
  }
227
- fetchEvents(companyGuid, amt = 50, knownIds = [], unknownIds = [], keyword = '', offset = 0, unbilled = true, billed = true, paid = true, jobId = null, cancelToken, headers = {}) {
228
- const body = {
229
- amt,
230
- known_ids: knownIds,
231
- unknown_ids: unknownIds,
232
- query: keyword,
233
- job_id: jobId,
234
- };
235
- if (!companyGuid) {
236
- return Promise.reject(new StandardError(400, 'Company GUID is required'));
316
+ async fetchEvents(body = {}, cancelToken, headers = {}) {
317
+ if (!this.companyId || this.companyId.trim() === '') {
318
+ throw new StandardError(400, 'Company ID is required');
237
319
  }
238
- return this._fetch('POST', `/company/${companyGuid}/events?amt=${amt}&offset=${offset}&unbilled=${unbilled}&billed=${billed}&paid=${paid}`, body, cancelToken, headers)
320
+ return this._fetch('POST', `/company/${this.companyId}/events`, JSON.stringify(body), cancelToken, {
321
+ ...headers,
322
+ 'Content-Type': 'application/json',
323
+ })
239
324
  .then(response => {
240
325
  if (!response || !Array.isArray(response)) {
241
326
  throw new StandardError(400, 'Invalid events response');
@@ -247,17 +332,33 @@ export class AvroQueryClient {
247
332
  throw new StandardError(500, 'Failed to fetch events');
248
333
  });
249
334
  }
250
- fetchBills(companyGuid, amt = 50, knownIds = [], unknownIds = [], keyword = '', offset = 0, paid = true, cancelToken, headers = {}) {
251
- const body = {
252
- amt,
253
- known_ids: knownIds,
254
- unknown_ids: unknownIds,
255
- query: keyword,
256
- };
257
- if (!companyGuid) {
258
- return Promise.reject(new StandardError(400, 'Company GUID is required'));
335
+ fetchMonths(body = {}, cancelToken, headers = {}) {
336
+ if (!this.companyId || this.companyId.trim() === '') {
337
+ throw new StandardError(400, 'Company ID is required');
338
+ }
339
+ return this._fetch('POST', `/company/${this.companyId}/months`, JSON.stringify(body), cancelToken, {
340
+ ...headers,
341
+ 'Content-Type': 'application/json',
342
+ })
343
+ .then(response => {
344
+ if (!response || !Array.isArray(response)) {
345
+ throw new StandardError(400, 'Invalid months response');
346
+ }
347
+ return response;
348
+ })
349
+ .catch(err => {
350
+ console.error('Failed to fetch months:', err);
351
+ throw new StandardError(500, 'Failed to fetch months');
352
+ });
353
+ }
354
+ fetchBills(body = {}, cancelToken, headers = {}) {
355
+ if (!this.companyId || this.companyId.trim() === '') {
356
+ throw new StandardError(400, 'Company ID is required');
259
357
  }
260
- return this._fetch('POST', `/company/${companyGuid}/bills?amt=${amt}&offset=${offset}&paid=${paid}`, body, cancelToken, headers)
358
+ return this._fetch('POST', `/company/${this.companyId}/bills`, JSON.stringify(body), cancelToken, {
359
+ ...headers,
360
+ 'Content-Type': 'application/json',
361
+ })
261
362
  .then(response => {
262
363
  if (!response || !Array.isArray(response)) {
263
364
  throw new StandardError(400, 'Invalid bills response');
@@ -269,4 +370,107 @@ export class AvroQueryClient {
269
370
  throw new StandardError(500, 'Failed to fetch bills');
270
371
  });
271
372
  }
373
+ fetchRoutes(body = {}, cancelToken, headers = {}) {
374
+ if (!this.companyId || this.companyId.trim() === '') {
375
+ throw new StandardError(400, 'Company ID is required');
376
+ }
377
+ return this._fetch('POST', `/company/${this.companyId}/routes`, JSON.stringify(body), cancelToken, {
378
+ ...headers,
379
+ 'Content-Type': 'application/json',
380
+ })
381
+ .then(response => {
382
+ if (!response || !Array.isArray(response)) {
383
+ throw new StandardError(400, 'Invalid routes response');
384
+ }
385
+ return response;
386
+ })
387
+ .catch(err => {
388
+ console.error('Failed to fetch routes:', err);
389
+ throw new StandardError(500, 'Failed to fetch routes');
390
+ });
391
+ }
392
+ fetchTeams(body = {}, cancelToken, headers = {}) {
393
+ if (!this.companyId || this.companyId.trim() === '') {
394
+ throw new StandardError(400, 'Company ID is required');
395
+ }
396
+ return this._fetch('POST', `/company/${this.companyId}/teams`, JSON.stringify(body), cancelToken, {
397
+ ...headers,
398
+ 'Content-Type': 'application/json',
399
+ })
400
+ .then(response => {
401
+ if (!response || !Array.isArray(response)) {
402
+ throw new StandardError(400, 'Invalid teams response');
403
+ }
404
+ return response;
405
+ })
406
+ .catch(err => {
407
+ console.error('Failed to fetch teams:', err);
408
+ throw new StandardError(500, 'Failed to fetch teams');
409
+ });
410
+ }
411
+ fetchGroups(body = {}, cancelToken, headers = {}) {
412
+ if (!this.companyId || this.companyId.trim() === '') {
413
+ throw new StandardError(400, 'Company ID is required');
414
+ }
415
+ return this._fetch('POST', `/company/${this.companyId}/groups`, JSON.stringify(body), cancelToken, {
416
+ ...headers,
417
+ 'Content-Type': 'application/json',
418
+ })
419
+ .then(response => {
420
+ if (!response || !Array.isArray(response)) {
421
+ throw new StandardError(400, 'Invalid groups response');
422
+ }
423
+ return response;
424
+ })
425
+ .catch(err => {
426
+ console.error('Failed to fetch groups:', err);
427
+ throw new StandardError(500, 'Failed to fetch groups');
428
+ });
429
+ }
430
+ fetchSkills(body = {}, cancelToken, headers = {}) {
431
+ if (!this.companyId || this.companyId.trim() === '') {
432
+ throw new StandardError(400, 'Company ID is required');
433
+ }
434
+ return this._fetch('POST', `/company/${this.companyId}/skills`, JSON.stringify(body), cancelToken, {
435
+ ...headers,
436
+ 'Content-Type': 'application/json',
437
+ })
438
+ .then(response => {
439
+ if (!response || !Array.isArray(response)) {
440
+ throw new StandardError(400, 'Invalid skills response');
441
+ }
442
+ return response;
443
+ })
444
+ .catch(err => {
445
+ console.error('Failed to fetch skills:', err);
446
+ throw new StandardError(500, 'Failed to fetch skills');
447
+ });
448
+ }
449
+ fetchSessions(body = {}, cancelToken, headers = {}) {
450
+ if (!this.companyId || this.companyId.trim() === '') {
451
+ throw new StandardError(400, 'Company ID is required');
452
+ }
453
+ return this._fetch('POST', `/company/${this.companyId}/sessions`, JSON.stringify(body), cancelToken, {
454
+ ...headers,
455
+ 'Content-Type': 'application/json',
456
+ })
457
+ .then(response => {
458
+ if (!response || !Array.isArray(response)) {
459
+ throw new StandardError(400, 'Invalid sessions response');
460
+ }
461
+ return response;
462
+ })
463
+ .catch(err => {
464
+ console.error('Failed to fetch sessions:', err);
465
+ throw new StandardError(500, 'Failed to fetch sessions');
466
+ });
467
+ }
468
+ sendEmail(emailId, formData, progressUpdateCallback) {
469
+ try {
470
+ return this.post(`/email/${emailId}`, formData, undefined, {}, progressUpdateCallback);
471
+ }
472
+ catch (error) {
473
+ throw new StandardError(500, `Failed to send email: ${error}`);
474
+ }
475
+ }
272
476
  }